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 struct dahdi_pvt * | handle_init_event (struct dahdi_pvt *i, int event) |
| static char * | handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_no_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_really_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_unset_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static 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 154 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 225 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmfup(), and process_dahdi().
| #define CALLPROGRESS_FAX_INCOMING 4 |
Definition at line 224 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_FAX_OUTGOING 2 |
Definition at line 223 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_PROGRESS 1 |
Definition at line 222 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 330 of file chan_dahdi.c.
| #define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 1295 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 1296 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and dahdi_new().
| #define CHAN_PSEUDO -2 |
Definition at line 207 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 152 of file chan_dahdi.c.
| #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define CONF_USER_REAL (1 << 0) |
Definition at line 512 of file chan_dahdi.c.
| #define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 513 of file chan_dahdi.c.
| #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
Definition at line 219 of file chan_dahdi.c.
Referenced by process_dahdi(), and start_pri().
| #define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 218 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), pri_dchannel(), process_dahdi(), and ss_thread().
| #define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 216 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 217 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 213 of file chan_dahdi.c.
Referenced by pri_find_dchan(), and pri_is_up().
| #define DCHAN_NOTINALARM (1 << 1) |
Definition at line 210 of file chan_dahdi.c.
Referenced by build_status(), pri_dchannel(), and start_pri().
| #define DCHAN_PROVISIONED (1 << 0) |
Definition at line 209 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
| #define DCHAN_UP (1 << 2) |
Definition at line 211 of file chan_dahdi.c.
Referenced by build_status(), and pri_dchannel().
| #define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 150 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
| #define DEFAULT_PRI_DEBUG 0 |
Definition at line 453 of file chan_dahdi.c.
Referenced by start_pri().
| #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 334 of file chan_dahdi.c.
| #define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
| #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1220 of file chan_dahdi.c.
Referenced by update_conf().
| #define HANGUP 1 |
Definition at line 13382 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 1292 of file chan_dahdi.c.
Referenced by dahdi_indicate(), and ss_thread().
| #define LINKSET_FLAG_EXPLICITACM (1 << 0) |
Definition at line 353 of file chan_dahdi.c.
Referenced by process_dahdi(), and ss7_start_call().
| #define LINKSTATE_DOWN (1 << 3) |
Definition at line 349 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_INALARM (1 << 0) |
Definition at line 346 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_STARTING (1 << 1) |
Definition at line 347 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define LINKSTATE_UP (1 << 2) |
Definition at line 348 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 327 of file chan_dahdi.c.
| #define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 328 of file chan_dahdi.c.
| #define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 14241 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 205 of file chan_dahdi.c.
Referenced by mkintf().
| #define MAX_SLAVES 4 |
Definition at line 515 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 158 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
| #define NUM_CADENCE_MAX 25 |
Definition at line 1267 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 204 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 202 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), 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 471 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), ss_thread(), and unalloc_sub().
| #define POLARITY_REV 1 |
Definition at line 472 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 392 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PRI_EXPLICIT | ( | p | ) | (((p) >> 16) & 0x01) |
Definition at line 394 of file chan_dahdi.c.
Referenced by pri_find_principle().
| #define PRI_SPAN | ( | p | ) | (((p) >> 8) & 0xff) |
Definition at line 393 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 14295 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 14297 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 391 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), pri_check_restart(), pri_dchannel(), and ss_thread().
| #define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 325 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().
| #define sig2str dahdi_sig2str |
Definition at line 1821 of file chan_dahdi.c.
Referenced by action_dahdishowchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
Definition at line 187 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 176 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM DAHDI_SIG_EM |
Definition at line 171 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 195 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 172 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 175 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 173 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 174 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 177 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 178 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 179 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 184 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 185 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 183 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 181 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
| #define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 182 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), process_dahdi(), and ss_thread().
| #define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 180 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 196 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 197 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 186 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF DAHDI_SIG_SF |
Definition at line 190 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 194 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 192 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 193 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 191 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 189 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_sig2str(), handle_init_event(), 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 351 of file chan_dahdi.c.
Referenced by dahdi_call(), and process_dahdi().
| #define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 467 of file chan_dahdi.c.
Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), dahdi_show_channel(), and ss_thread().
| #define SUB_REAL 0 |
Active call
Definition at line 466 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), build_device(), bump_gains(), chandup(), check_for_conference(), close_call(), close_client(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_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 468 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), close_call(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), HandleCallOutgoing(), ss_thread(), TransferCallStep1(), unistim_answer(), and unistim_hangup().
| #define tdesc "DAHDI Telephony w/PRI & SS7" |
Definition at line 15531 of file chan_dahdi.c.
| #define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
| #define TRANSFER 0 |
Definition at line 13381 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 7941 of file chan_dahdi.c.
07941 { 07942 MWI_SEND_SA, 07943 MWI_SEND_SA_WAIT, 07944 MWI_SEND_PAUSE, 07945 MWI_SEND_SPILL, 07946 MWI_SEND_CLEANUP, 07947 MWI_SEND_DONE 07948 };
| static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5553 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().
05554 { 05555 struct dahdi_pvt *p = ast->tech_pvt; 05556 int res; 05557 int usedindex=-1; 05558 int idx; 05559 struct ast_frame *f; 05560 05561 05562 idx = dahdi_get_index(ast, p, 1); 05563 05564 p->subs[idx].f.frametype = AST_FRAME_NULL; 05565 p->subs[idx].f.datalen = 0; 05566 p->subs[idx].f.samples = 0; 05567 p->subs[idx].f.mallocd = 0; 05568 p->subs[idx].f.offset = 0; 05569 p->subs[idx].f.subclass = 0; 05570 p->subs[idx].f.delivery = ast_tv(0,0); 05571 p->subs[idx].f.src = "dahdi_exception"; 05572 p->subs[idx].f.data.ptr = NULL; 05573 05574 05575 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05576 /* If nobody owns us, absorb the event appropriately, otherwise 05577 we loop indefinitely. This occurs when, during call waiting, the 05578 other end hangs up our channel so that it no longer exists, but we 05579 have neither FLASH'd nor ONHOOK'd to signify our desire to 05580 change to the other channel. */ 05581 if (p->fake_event) { 05582 res = p->fake_event; 05583 p->fake_event = 0; 05584 } else 05585 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05586 /* Switch to real if there is one and this isn't something really silly... */ 05587 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05588 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05589 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 05590 p->owner = p->subs[SUB_REAL].owner; 05591 if (p->owner && ast_bridged_channel(p->owner)) 05592 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05593 p->subs[SUB_REAL].needunhold = 1; 05594 } 05595 switch (res) { 05596 case DAHDI_EVENT_ONHOOK: 05597 dahdi_disable_ec(p); 05598 if (p->owner) { 05599 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 05600 dahdi_ring_phone(p); 05601 p->callwaitingrepeat = 0; 05602 p->cidcwexpire = 0; 05603 } else 05604 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05605 update_conf(p); 05606 break; 05607 case DAHDI_EVENT_RINGOFFHOOK: 05608 dahdi_enable_ec(p); 05609 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05610 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05611 p->subs[SUB_REAL].needanswer = 1; 05612 p->dialing = 0; 05613 } 05614 break; 05615 case DAHDI_EVENT_HOOKCOMPLETE: 05616 case DAHDI_EVENT_RINGERON: 05617 case DAHDI_EVENT_RINGEROFF: 05618 /* Do nothing */ 05619 break; 05620 case DAHDI_EVENT_WINKFLASH: 05621 p->flashtime = ast_tvnow(); 05622 if (p->owner) { 05623 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05624 if (p->owner->_state != AST_STATE_UP) { 05625 /* Answer if necessary */ 05626 usedindex = dahdi_get_index(p->owner, p, 0); 05627 if (usedindex > -1) { 05628 p->subs[usedindex].needanswer = 1; 05629 } 05630 ast_setstate(p->owner, AST_STATE_UP); 05631 } 05632 p->callwaitingrepeat = 0; 05633 p->cidcwexpire = 0; 05634 if (ast_bridged_channel(p->owner)) 05635 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05636 p->subs[SUB_REAL].needunhold = 1; 05637 } else 05638 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05639 update_conf(p); 05640 break; 05641 default: 05642 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05643 } 05644 f = &p->subs[idx].f; 05645 return f; 05646 } 05647 if (!(p->radio || (p->oprmode < 0))) 05648 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05649 /* If it's not us, return NULL immediately */ 05650 if (ast != p->owner) { 05651 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05652 f = &p->subs[idx].f; 05653 return f; 05654 } 05655 f = dahdi_handle_event(ast); 05656 return f; 05657 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 15547 of file chan_dahdi.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 14058 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().
14059 { 14060 struct dahdi_pvt *p; 14061 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14062 int i, j; 14063 #endif 14064 14065 #ifdef HAVE_PRI 14066 for (i = 0; i < NUM_SPANS; i++) { 14067 if (pris[i].master != AST_PTHREADT_NULL) 14068 pthread_cancel(pris[i].master); 14069 } 14070 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 14071 ast_unregister_application(dahdi_send_keypad_facility_app); 14072 #endif 14073 #if defined(HAVE_SS7) 14074 for (i = 0; i < NUM_SPANS; i++) { 14075 if (linksets[i].master != AST_PTHREADT_NULL) 14076 pthread_cancel(linksets[i].master); 14077 } 14078 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry)); 14079 #endif 14080 14081 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 14082 ast_manager_unregister( "DAHDIDialOffhook" ); 14083 ast_manager_unregister( "DAHDIHangup" ); 14084 ast_manager_unregister( "DAHDITransfer" ); 14085 ast_manager_unregister( "DAHDIDNDoff" ); 14086 ast_manager_unregister( "DAHDIDNDon" ); 14087 ast_manager_unregister("DAHDIShowChannels"); 14088 ast_manager_unregister("DAHDIRestart"); 14089 ast_channel_unregister(&dahdi_tech); 14090 ast_mutex_lock(&iflock); 14091 /* Hangup all interfaces if they have an owner */ 14092 p = iflist; 14093 while (p) { 14094 if (p->owner) 14095 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 14096 p = p->next; 14097 } 14098 ast_mutex_unlock(&iflock); 14099 ast_mutex_lock(&monlock); 14100 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14101 pthread_cancel(monitor_thread); 14102 pthread_kill(monitor_thread, SIGURG); 14103 pthread_join(monitor_thread, NULL); 14104 } 14105 monitor_thread = AST_PTHREADT_STOP; 14106 ast_mutex_unlock(&monlock); 14107 14108 destroy_all_channels(); 14109 14110 #if defined(HAVE_PRI) 14111 for (i = 0; i < NUM_SPANS; i++) { 14112 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 14113 pthread_join(pris[i].master, NULL); 14114 for (j = 0; j < NUM_DCHANS; j++) { 14115 dahdi_close_pri_fd(&(pris[i]), j); 14116 } 14117 } 14118 #endif 14119 14120 #if defined(HAVE_SS7) 14121 for (i = 0; i < NUM_SPANS; i++) { 14122 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 14123 pthread_join(linksets[i].master, NULL); 14124 for (j = 0; j < NUM_DCHANS; j++) { 14125 dahdi_close_ss7_fd(&(linksets[i]), j); 14126 } 14127 } 14128 #endif 14129 14130 ast_cond_destroy(&mwi_thread_complete); 14131 ast_cond_destroy(&ss_thread_complete); 14132 return 0; 14133 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 15547 of file chan_dahdi.c.
| static int action_dahdidialoffhook | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13488 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().
13489 { 13490 struct dahdi_pvt *p = NULL; 13491 const char *channel = astman_get_header(m, "DAHDIChannel"); 13492 const char *number = astman_get_header(m, "Number"); 13493 int i; 13494 13495 if (ast_strlen_zero(channel)) { 13496 astman_send_error(s, m, "No channel specified"); 13497 return 0; 13498 } 13499 if (ast_strlen_zero(number)) { 13500 astman_send_error(s, m, "No number specified"); 13501 return 0; 13502 } 13503 p = find_channel(atoi(channel)); 13504 if (!p) { 13505 astman_send_error(s, m, "No such channel"); 13506 return 0; 13507 } 13508 if (!p->owner) { 13509 astman_send_error(s, m, "Channel does not have it's owner"); 13510 return 0; 13511 } 13512 for (i = 0; i < strlen(number); i++) { 13513 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 13514 dahdi_queue_frame(p, &f, NULL); 13515 } 13516 astman_send_ack(s, m, "DAHDIDialOffhook"); 13517 return 0; 13518 }
| static int action_dahdidndoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13431 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().
13432 { 13433 struct dahdi_pvt *p = NULL; 13434 const char *channel = astman_get_header(m, "DAHDIChannel"); 13435 13436 if (ast_strlen_zero(channel)) { 13437 astman_send_error(s, m, "No channel specified"); 13438 return 0; 13439 } 13440 p = find_channel(atoi(channel)); 13441 if (!p) { 13442 astman_send_error(s, m, "No such channel"); 13443 return 0; 13444 } 13445 p->dnd = 0; 13446 astman_send_ack(s, m, "DND Disabled"); 13447 return 0; 13448 }
| static int action_dahdidndon | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13412 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().
13413 { 13414 struct dahdi_pvt *p = NULL; 13415 const char *channel = astman_get_header(m, "DAHDIChannel"); 13416 13417 if (ast_strlen_zero(channel)) { 13418 astman_send_error(s, m, "No channel specified"); 13419 return 0; 13420 } 13421 p = find_channel(atoi(channel)); 13422 if (!p) { 13423 astman_send_error(s, m, "No such channel"); 13424 return 0; 13425 } 13426 p->dnd = 1; 13427 astman_send_ack(s, m, "DND Enabled"); 13428 return 0; 13429 }
| static int action_dahdirestart | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 12705 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
12706 { 12707 if (dahdi_restart() != 0) { 12708 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 12709 return 1; 12710 } 12711 astman_send_ack(s, m, "DAHDIRestart: Success"); 12712 return 0; 12713 }
| static int action_dahdishowchannels | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13520 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().
13521 { 13522 struct dahdi_pvt *tmp = NULL; 13523 const char *id = astman_get_header(m, "ActionID"); 13524 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 13525 char idText[256] = ""; 13526 int channels = 0; 13527 int dahdichanquery = -1; 13528 if (!ast_strlen_zero(dahdichannel)) { 13529 dahdichanquery = atoi(dahdichannel); 13530 } 13531 13532 astman_send_ack(s, m, "DAHDI channel status will follow"); 13533 if (!ast_strlen_zero(id)) 13534 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 13535 13536 ast_mutex_lock(&iflock); 13537 13538 tmp = iflist; 13539 while (tmp) { 13540 if (tmp->channel > 0) { 13541 int alm = get_alarms(tmp); 13542 13543 /* If a specific channel is queried for, only deliver status for that channel */ 13544 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 13545 continue; 13546 13547 channels++; 13548 if (tmp->owner) { 13549 /* Add data if we have a current call */ 13550 astman_append(s, 13551 "Event: DAHDIShowChannels\r\n" 13552 "DAHDIChannel: %d\r\n" 13553 "Channel: %s\r\n" 13554 "Uniqueid: %s\r\n" 13555 "AccountCode: %s\r\n" 13556 "Signalling: %s\r\n" 13557 "SignallingCode: %d\r\n" 13558 "Context: %s\r\n" 13559 "DND: %s\r\n" 13560 "Alarm: %s\r\n" 13561 "%s" 13562 "\r\n", 13563 tmp->channel, 13564 tmp->owner->name, 13565 tmp->owner->uniqueid, 13566 tmp->owner->accountcode, 13567 sig2str(tmp->sig), 13568 tmp->sig, 13569 tmp->context, 13570 tmp->dnd ? "Enabled" : "Disabled", 13571 alarm2str(alm), idText); 13572 } else { 13573 astman_append(s, 13574 "Event: DAHDIShowChannels\r\n" 13575 "DAHDIChannel: %d\r\n" 13576 "Signalling: %s\r\n" 13577 "SignallingCode: %d\r\n" 13578 "Context: %s\r\n" 13579 "DND: %s\r\n" 13580 "Alarm: %s\r\n" 13581 "%s" 13582 "\r\n", 13583 tmp->channel, sig2str(tmp->sig), tmp->sig, 13584 tmp->context, 13585 tmp->dnd ? "Enabled" : "Disabled", 13586 alarm2str(alm), idText); 13587 } 13588 } 13589 13590 tmp = tmp->next; 13591 } 13592 13593 ast_mutex_unlock(&iflock); 13594 13595 astman_append(s, 13596 "Event: DAHDIShowChannelsComplete\r\n" 13597 "%s" 13598 "Items: %d\r\n" 13599 "\r\n", 13600 idText, 13601 channels); 13602 return 0; 13603 }
| static int action_transfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13450 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().
13451 { 13452 struct dahdi_pvt *p = NULL; 13453 const char *channel = astman_get_header(m, "DAHDIChannel"); 13454 13455 if (ast_strlen_zero(channel)) { 13456 astman_send_error(s, m, "No channel specified"); 13457 return 0; 13458 } 13459 p = find_channel(atoi(channel)); 13460 if (!p) { 13461 astman_send_error(s, m, "No such channel"); 13462 return 0; 13463 } 13464 dahdi_fake_event(p,TRANSFER); 13465 astman_send_ack(s, m, "DAHDITransfer"); 13466 return 0; 13467 }
| static int action_transferhangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13469 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().
13470 { 13471 struct dahdi_pvt *p = NULL; 13472 const char *channel = astman_get_header(m, "DAHDIChannel"); 13473 13474 if (ast_strlen_zero(channel)) { 13475 astman_send_error(s, m, "No channel specified"); 13476 return 0; 13477 } 13478 p = find_channel(atoi(channel)); 13479 if (!p) { 13480 astman_send_error(s, m, "No such channel"); 13481 return 0; 13482 } 13483 dahdi_fake_event(p,HANGUP); 13484 astman_send_ack(s, m, "DAHDIHangup"); 13485 return 0; 13486 }
| static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 1726 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 1522 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), dahdi_open(), dahdi_subchannel::dfd, errno, LOG_WARNING, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().
01523 { 01524 struct dahdi_bufferinfo bi; 01525 int res; 01526 if (p->subs[x].dfd >= 0) { 01527 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01528 return -1; 01529 } 01530 01531 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 01532 if (p->subs[x].dfd <= -1) { 01533 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01534 return -1; 01535 } 01536 01537 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01538 if (!res) { 01539 bi.txbufpolicy = p->buf_policy; 01540 bi.rxbufpolicy = p->buf_policy; 01541 bi.numbufs = p->buf_no; 01542 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01543 if (res < 0) { 01544 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01545 } 01546 } else 01547 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01548 01549 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01550 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01551 dahdi_close_sub(p, x); 01552 p->subs[x].dfd = -1; 01553 return -1; 01554 } 01555 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01556 return 0; 01557 }
| static void apply_plan_to_number | ( | char * | buf, | |
| size_t | size, | |||
| const struct dahdi_pri * | pri, | |||
| const char * | number, | |||
| const int | plan | |||
| ) | [static] |
Definition at line 10885 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().
10886 { 10887 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */ 10888 snprintf(buf, size, "%s", number); 10889 return; 10890 } 10891 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10892 if (size) { 10893 *buf = '\0'; 10894 } 10895 return; 10896 } 10897 switch (plan) { 10898 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10899 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10900 break; 10901 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10902 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10903 break; 10904 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10905 snprintf(buf, size, "%s%s", pri->localprefix, number); 10906 break; 10907 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10908 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10909 break; 10910 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10911 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10912 break; 10913 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10914 snprintf(buf, size, "%s", number); 10915 break; 10916 } 10917 }
| static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4500 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().
04501 { 04502 /* In order to transfer, we need at least one of the channels to 04503 actually be in a call bridge. We can't conference two applications 04504 together (but then, why would we want to?) */ 04505 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04506 /* The three-way person we're about to transfer to could still be in MOH, so 04507 stop if now if appropriate */ 04508 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04509 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04510 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04511 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04512 } 04513 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04514 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04515 } 04516 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04517 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04518 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04519 return -1; 04520 } 04521 /* Orphan the channel after releasing the lock */ 04522 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04523 unalloc_sub(p, SUB_THREEWAY); 04524 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04525 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04526 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04527 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04528 } 04529 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04530 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04531 } 04532 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04533 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04534 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04535 return -1; 04536 } 04537 /* Three-way is now the REAL */ 04538 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04539 ast_channel_unlock(p->subs[SUB_REAL].owner); 04540 unalloc_sub(p, SUB_THREEWAY); 04541 /* Tell the caller not to hangup */ 04542 return 1; 04543 } else { 04544 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04545 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04546 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04547 return -1; 04548 } 04549 return 0; 04550 }
| static int available | ( | struct dahdi_pvt * | p, | |
| int | channelmatch, | |||
| ast_group_t | groupmatch, | |||
| int * | busy, | |||
| int * | channelmatched, | |||
| int * | groupmatched | |||
| ) | [inline, static] |
Definition at line 9316 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().
09317 { 09318 int res; 09319 struct dahdi_params par; 09320 09321 /* First, check group matching */ 09322 if (groupmatch) { 09323 if ((p->group & groupmatch) != groupmatch) 09324 return 0; 09325 *groupmatched = 1; 09326 } 09327 /* Check to see if we have a channel match */ 09328 if (channelmatch != -1) { 09329 if (p->channel != channelmatch) 09330 return 0; 09331 *channelmatched = 1; 09332 } 09333 /* We're at least busy at this point */ 09334 if (busy) { 09335 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09336 *busy = 1; 09337 } 09338 /* If do not disturb, definitely not */ 09339 if (p->dnd) 09340 return 0; 09341 /* If guard time, definitely not */ 09342 if (p->guardtime && (time(NULL) < p->guardtime)) 09343 return 0; 09344 09345 if (p->locallyblocked || p->remotelyblocked) 09346 return 0; 09347 09348 /* If no owner definitely available */ 09349 if (!p->owner) { 09350 #ifdef HAVE_PRI 09351 /* Trust PRI */ 09352 if (p->pri) { 09353 if (p->resetting || p->call) 09354 return 0; 09355 else 09356 return 1; 09357 } 09358 #endif 09359 #ifdef HAVE_SS7 09360 /* Trust SS7 */ 09361 if (p->ss7) { 09362 if (p->ss7call) 09363 return 0; 09364 else 09365 return 1; 09366 } 09367 #endif 09368 if (!(p->radio || (p->oprmode < 0))) 09369 { 09370 if (!p->sig || (p->sig == SIG_FXSLS)) 09371 return 1; 09372 /* Check hook state */ 09373 if (p->subs[SUB_REAL].dfd > -1) { 09374 memset(&par, 0, sizeof(par)); 09375 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09376 } else { 09377 /* Assume not off hook on CVRS */ 09378 res = 0; 09379 par.rxisoffhook = 0; 09380 } 09381 if (res) { 09382 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09383 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09384 /* When "onhook" that means no battery on the line, and thus 09385 it is out of service..., if it's on a TDM card... If it's a channel 09386 bank, there is no telling... */ 09387 if (par.rxbits > -1) 09388 return 1; 09389 if (par.rxisoffhook) 09390 return 1; 09391 else 09392 return 0; 09393 } else if (par.rxisoffhook) { 09394 ast_debug(1, "Channel %d off hook, can't use\n", p->channel); 09395 /* Not available when the other end is off hook */ 09396 #ifdef DAHDI_CHECK_HOOKSTATE 09397 return 0; 09398 #else 09399 return 1; 09400 #endif 09401 } 09402 } 09403 return 1; 09404 } 09405 09406 /* If it's not an FXO, forget about call wait */ 09407 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09408 return 0; 09409 09410 if (!p->callwaiting) { 09411 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09412 return 0; 09413 } 09414 09415 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09416 /* If there is already a call waiting call, then we can't take a second one */ 09417 return 0; 09418 } 09419 09420 if ((p->owner->_state != AST_STATE_UP) && 09421 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09422 /* If the current call is not up, then don't allow the call */ 09423 return 0; 09424 } 09425 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09426 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09427 return 0; 09428 } 09429 /* We're cool */ 09430 return 1; 09431 }
| 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 14151 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().
14152 { 14153 char *c, *chan; 14154 int x, start, finish; 14155 struct dahdi_pvt *tmp; 14156 #ifdef HAVE_PRI 14157 struct dahdi_pri *pri; 14158 int trunkgroup, y; 14159 #endif 14160 14161 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 14162 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 14163 return -1; 14164 } 14165 14166 c = ast_strdupa(value); 14167 14168 #ifdef HAVE_PRI 14169 pri = NULL; 14170 if (iscrv) { 14171 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 14172 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno); 14173 return -1; 14174 } 14175 if (trunkgroup < 1) { 14176 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno); 14177 return -1; 14178 } 14179 c += y; 14180 for (y = 0; y < NUM_SPANS; y++) { 14181 if (pris[y].trunkgroup == trunkgroup) { 14182 pri = pris + y; 14183 break; 14184 } 14185 } 14186 if (!pri) { 14187 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno); 14188 return -1; 14189 } 14190 } 14191 #endif 14192 14193 while ((chan = strsep(&c, ","))) { 14194 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 14195 /* Range */ 14196 } else if (sscanf(chan, "%30d", &start)) { 14197 /* Just one */ 14198 finish = start; 14199 } else if (!strcasecmp(chan, "pseudo")) { 14200 finish = start = CHAN_PSEUDO; 14201 if (found_pseudo) 14202 *found_pseudo = 1; 14203 } else { 14204 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 14205 return -1; 14206 } 14207 if (finish < start) { 14208 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 14209 x = finish; 14210 finish = start; 14211 start = x; 14212 } 14213 14214 for (x = start; x <= finish; x++) { 14215 #ifdef HAVE_PRI 14216 tmp = mkintf(x, conf, pri, reload); 14217 #else 14218 tmp = mkintf(x, conf, NULL, reload); 14219 #endif 14220 14221 if (tmp) { 14222 #ifdef HAVE_PRI 14223 if (pri) 14224 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 14225 else 14226 #endif 14227 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 14228 } else { 14229 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 14230 (reload == 1) ? "reconfigure" : "register", value); 14231 return -1; 14232 } 14233 } 14234 } 14235 14236 return 0; 14237 }
| static void build_status | ( | char * | s, | |
| size_t | len, | |||
| int | status, | |||
| int | active | |||
| ) | [static] |
Definition at line 12336 of file chan_dahdi.c.
References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
12337 { 12338 if (!s || len < 1) { 12339 return; 12340 } 12341 s[0] = '\0'; 12342 if (status & DCHAN_PROVISIONED) 12343 strncat(s, "Provisioned, ", len - strlen(s) - 1); 12344 if (!(status & DCHAN_NOTINALARM)) 12345 strncat(s, "In Alarm, ", len - strlen(s) - 1); 12346 if (status & DCHAN_UP) 12347 strncat(s, "Up", len - strlen(s) - 1); 12348 else 12349 strncat(s, "Down", len - strlen(s) - 1); 12350 if (active) 12351 strncat(s, ", Active", len - strlen(s) - 1); 12352 else 12353 strncat(s, ", Standby", len - strlen(s) - 1); 12354 s[len - 1] = '\0'; 12355 }
| static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2181 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::cid_rxgain, 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().
02182 { 02183 int res; 02184 02185 /* Bump receive gain by value stored in cid_rxgain */ 02186 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law); 02187 if (res) { 02188 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02189 return -1; 02190 } 02191 02192 return 0; 02193 }
| static int calc_energy | ( | const unsigned char * | buf, | |
| int | len, | |||
| int | law | |||
| ) | [static] |
Definition at line 7793 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by do_monitor(), and mwi_thread().
Definition at line 9433 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().
09434 { 09435 struct dahdi_pvt *p; 09436 struct dahdi_bufferinfo bi; 09437 int res; 09438 09439 if ((p = ast_malloc(sizeof(*p)))) { 09440 memcpy(p, src, sizeof(struct dahdi_pvt)); 09441 ast_mutex_init(&p->lock); 09442 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 09443 /* Allocate a dahdi structure */ 09444 if (p->subs[SUB_REAL].dfd < 0) { 09445 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09446 destroy_dahdi_pvt(&p); 09447 return NULL; 09448 } 09449 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09450 if (!res) { 09451 bi.txbufpolicy = src->buf_policy; 09452 bi.rxbufpolicy = src->buf_policy; 09453 bi.numbufs = src->buf_no; 09454 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09455 if (res < 0) { 09456 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09457 } 09458 } else 09459 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09460 } 09461 p->destroy = 1; 09462 p->next = iflist; 09463 p->prev = NULL; 09464 iflist = p; 09465 if (iflist->next) 09466 iflist->next->prev = p; 09467 return p; 09468 }
| static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4552 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().
04553 { 04554 struct dahdi_confinfo ci; 04555 /* Fine if we already have a master, etc */ 04556 if (p->master || (p->confno > -1)) 04557 return 0; 04558 memset(&ci, 0, sizeof(ci)); 04559 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04560 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04561 return 0; 04562 } 04563 /* If we have no master and don't have a confno, then 04564 if we're in a conference, it's probably a MeetMe room or 04565 some such, so don't let us 3-way out! */ 04566 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04567 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 04568 return 1; 04569 } 04570 return 0; 04571 }
| static unsigned char cid_pres2ss7pres | ( | int | cid_pres | ) | [static] |
Definition at line 2433 of file chan_dahdi.c.
Referenced by dahdi_call().
| static unsigned char cid_pres2ss7screen | ( | int | cid_pres | ) | [static] |
Definition at line 2438 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 12161 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
12162 { 12163 return complete_span_helper(line,word,pos,state,3); 12164 }
| static char* complete_span_5 | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 12166 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_no_debug(), and handle_pri_really_debug().
12167 { 12168 return complete_span_helper(line,word,pos,state,4); 12169 }
| static char* complete_span_helper | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state, | |||
| int | rpos | |||
| ) | [static] |
Definition at line 12142 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().
12143 { 12144 int which, span; 12145 char *ret = NULL; 12146 12147 if (pos != rpos) 12148 return ret; 12149 12150 for (which = span = 0; span < NUM_SPANS; span++) { 12151 if (pris[span].pri && ++which > state) { 12152 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 12153 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 12154 } 12155 break; 12156 } 12157 } 12158 return ret; 12159 }
| static int conf_add | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx, | |||
| int | slavechannel | |||
| ) | [static] |
Definition at line 1823 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, and LOG_WARNING.
Referenced by update_conf().
01824 { 01825 /* If the conference already exists, and we're already in it 01826 don't bother doing anything */ 01827 struct dahdi_confinfo zi; 01828 01829 memset(&zi, 0, sizeof(zi)); 01830 zi.chan = 0; 01831 01832 if (slavechannel > 0) { 01833 /* If we have only one slave, do a digital mon */ 01834 zi.confmode = DAHDI_CONF_DIGITALMON; 01835 zi.confno = slavechannel; 01836 } else { 01837 if (!idx) { 01838 /* Real-side and pseudo-side both participate in conference */ 01839 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01840 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01841 } else 01842 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01843 zi.confno = p->confno; 01844 } 01845 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01846 return 0; 01847 if (c->dfd < 0) 01848 return 0; 01849 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01850 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01851 return -1; 01852 } 01853 if (slavechannel < 1) { 01854 p->confno = zi.confno; 01855 } 01856 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01857 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01858 return 0; 01859 }
| static int conf_del | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx | |||
| ) | [static] |
Definition at line 1872 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), and LOG_WARNING.
Referenced by dahdi_unlink(), and update_conf().
01873 { 01874 struct dahdi_confinfo zi; 01875 if (/* Can't delete if there's no dfd */ 01876 (c->dfd < 0) || 01877 /* Don't delete from the conference if it's not our conference */ 01878 !isourconf(p, c) 01879 /* Don't delete if we don't think it's conferenced at all (implied) */ 01880 ) return 0; 01881 memset(&zi, 0, sizeof(zi)); 01882 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01883 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01884 return -1; 01885 } 01886 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01887 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01888 return 0; 01889 }
| static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3740 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.
03741 { 03742 struct dahdi_pvt *p = ast->tech_pvt; 03743 int res = 0; 03744 int idx; 03745 int oldstate = ast->_state; 03746 ast_setstate(ast, AST_STATE_UP); 03747 ast_mutex_lock(&p->lock); 03748 idx = dahdi_get_index(ast, p, 0); 03749 if (idx < 0) 03750 idx = SUB_REAL; 03751 /* nothing to do if a radio channel */ 03752 if ((p->radio || (p->oprmode < 0))) { 03753 ast_mutex_unlock(&p->lock); 03754 return 0; 03755 } 03756 switch (p->sig) { 03757 case SIG_FXSLS: 03758 case SIG_FXSGS: 03759 case SIG_FXSKS: 03760 p->ringt = 0; 03761 /* Fall through */ 03762 case SIG_EM: 03763 case SIG_EM_E1: 03764 case SIG_EMWINK: 03765 case SIG_FEATD: 03766 case SIG_FEATDMF: 03767 case SIG_FEATDMF_TA: 03768 case SIG_E911: 03769 case SIG_FGC_CAMA: 03770 case SIG_FGC_CAMAMF: 03771 case SIG_FEATB: 03772 case SIG_SF: 03773 case SIG_SFWINK: 03774 case SIG_SF_FEATD: 03775 case SIG_SF_FEATDMF: 03776 case SIG_SF_FEATB: 03777 case SIG_FXOLS: 03778 case SIG_FXOGS: 03779 case SIG_FXOKS: 03780 /* Pick up the line */ 03781 ast_debug(1, "Took %s off hook\n", ast->name); 03782 if (p->hanguponpolarityswitch) { 03783 p->polaritydelaytv = ast_tvnow(); 03784 } 03785 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03786 tone_zone_play_tone(p->subs[idx].dfd, -1); 03787 p->dialing = 0; 03788 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03789 if (oldstate == AST_STATE_RINGING) { 03790 ast_debug(1, "Finally swapping real and threeway\n"); 03791 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03792 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03793 p->owner = p->subs[SUB_REAL].owner; 03794 } 03795 } 03796 if (p->sig & __DAHDI_SIG_FXS) { 03797 dahdi_enable_ec(p); 03798 dahdi_train_ec(p); 03799 } 03800 break; 03801 #ifdef HAVE_PRI 03802 case SIG_BRI: 03803 case SIG_BRI_PTMP: 03804 case SIG_PRI: 03805 /* Send a pri acknowledge */ 03806 if (!pri_grab(p, p->pri)) { 03807 p->proceeding = 1; 03808 p->dialing = 0; 03809 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03810 pri_rel(p->pri); 03811 } else { 03812 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03813 res = -1; 03814 } 03815 break; 03816 #endif 03817 #ifdef HAVE_SS7 03818 case SIG_SS7: 03819 if (!ss7_grab(p, p->ss7)) { 03820 p->proceeding = 1; 03821 res = isup_anm(p->ss7->ss7, p->ss7call); 03822 ss7_rel(p->ss7); 03823 } else { 03824 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 03825 res = -1; 03826 } 03827 break; 03828 #endif 03829 case 0: 03830 ast_mutex_unlock(&p->lock); 03831 return 0; 03832 default: 03833 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03834 res = -1; 03835 } 03836 ast_mutex_unlock(&p->lock); 03837 return res; 03838 }
| 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 4152 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().
04153 { 04154 struct ast_channel *who; 04155 struct dahdi_pvt *p0, *p1, *op0, *op1; 04156 struct dahdi_pvt *master = NULL, *slave = NULL; 04157 struct ast_frame *f; 04158 int inconf = 0; 04159 int nothingok = 1; 04160 int ofd0, ofd1; 04161 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04162 int os0 = -1, os1 = -1; 04163 int priority = 0; 04164 struct ast_channel *oc0, *oc1; 04165 enum ast_bridge_result res; 04166 04167 #ifdef PRI_2BCT 04168 int triedtopribridge = 0; 04169 q931_call *q931c0 = NULL, *q931c1 = NULL; 04170 #endif 04171 04172 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04173 There is code below to handle it properly until DTMF is actually seen, 04174 but due to currently unresolved issues it's ignored... 04175 */ 04176 04177 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04178 return AST_BRIDGE_FAILED_NOWARN; 04179 04180 ast_channel_lock(c0); 04181 while (ast_channel_trylock(c1)) { 04182 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04183 } 04184 04185 p0 = c0->tech_pvt; 04186 p1 = c1->tech_pvt; 04187 /* cant do pseudo-channels here */ 04188 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04189 ast_channel_unlock(c0); 04190 ast_channel_unlock(c1); 04191 return AST_BRIDGE_FAILED_NOWARN; 04192 } 04193 04194 oi0 = dahdi_get_index(c0, p0, 0); 04195 oi1 = dahdi_get_index(c1, p1, 0); 04196 if ((oi0 < 0) || (oi1 < 0)) { 04197 ast_channel_unlock(c0); 04198 ast_channel_unlock(c1); 04199 return AST_BRIDGE_FAILED; 04200 } 04201 04202 op0 = p0 = c0->tech_pvt; 04203 op1 = p1 = c1->tech_pvt; 04204 ofd0 = c0->fds[0]; 04205 ofd1 = c1->fds[0]; 04206 oc0 = p0->owner; 04207 oc1 = p1->owner; 04208 04209 if (ast_mutex_trylock(&p0->lock)) { 04210 /* Don't block, due to potential for deadlock */ 04211 ast_channel_unlock(c0); 04212 ast_channel_unlock(c1); 04213 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04214 return AST_BRIDGE_RETRY; 04215 } 04216 if (ast_mutex_trylock(&p1->lock)) { 04217 /* Don't block, due to potential for deadlock */ 04218 ast_mutex_unlock(&p0->lock); 04219 ast_channel_unlock(c0); 04220 ast_channel_unlock(c1); 04221 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04222 return AST_BRIDGE_RETRY; 04223 } 04224 04225 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04226 if (p0->owner && p1->owner) { 04227 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04228 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04229 master = p0; 04230 slave = p1; 04231 inconf = 1; 04232 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04233 master = p1; 04234 slave = p0; 04235 inconf = 1; 04236 } else { 04237 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04238 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04239 p0->channel, 04240 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04241 p0->subs[SUB_REAL].inthreeway, p0->channel, 04242 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04243 p1->subs[SUB_REAL].inthreeway); 04244 } 04245 nothingok = 0; 04246 } 04247 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04248 if (p1->subs[SUB_THREEWAY].inthreeway) { 04249 master = p1; 04250 slave = p0; 04251 nothingok = 0; 04252 } 04253 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04254 if (p0->subs[SUB_THREEWAY].inthreeway) { 04255 master = p0; 04256 slave = p1; 04257 nothingok = 0; 04258 } 04259 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04260 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04261 don't put us in anything */ 04262 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04263 master = p1; 04264 slave = p0; 04265 nothingok = 0; 04266 } 04267 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04268 /* Same as previous */ 04269 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04270 master = p0; 04271 slave = p1; 04272 nothingok = 0; 04273 } 04274 } 04275 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 04276 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04277 if (master && slave) { 04278 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04279 in an active threeway call with a channel that is ringing, we should 04280 indicate ringing. */ 04281 if ((oi1 == SUB_THREEWAY) && 04282 p1->subs[SUB_THREEWAY].inthreeway && 04283 p1->subs[SUB_REAL].owner && 04284 p1->subs[SUB_REAL].inthreeway && 04285 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04286 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04287 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04288 os1 = p1->subs[SUB_REAL].owner->_state; 04289 } else { 04290 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04291 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04292 } 04293 if ((oi0 == SUB_THREEWAY) && 04294 p0->subs[SUB_THREEWAY].inthreeway && 04295 p0->subs[SUB_REAL].owner && 04296 p0->subs[SUB_REAL].inthreeway && 04297 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04298 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04299 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04300 os0 = p0->subs[SUB_REAL].owner->_state; 04301 } else { 04302 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04303 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04304 } 04305 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04306 if (!p0->echocanbridged || !p1->echocanbridged) { 04307 /* Disable echo cancellation if appropriate */ 04308 dahdi_disable_ec(p0); 04309 dahdi_disable_ec(p1); 04310 } 04311 } 04312 dahdi_link(slave, master); 04313 master->inconference = inconf; 04314 } else if (!nothingok) 04315 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04316 04317 update_conf(p0); 04318 update_conf(p1); 04319 t0 = p0->subs[SUB_REAL].inthreeway; 04320 t1 = p1->subs[SUB_REAL].inthreeway; 04321 04322 ast_mutex_unlock(&p0->lock); 04323 ast_mutex_unlock(&p1->lock); 04324 04325 ast_channel_unlock(c0); 04326 ast_channel_unlock(c1); 04327 04328 /* Native bridge failed */ 04329 if ((!master || !slave) && !nothingok) { 04330 dahdi_enable_ec(p0); 04331 dahdi_enable_ec(p1); 04332 return AST_BRIDGE_FAILED; 04333 } 04334 04335 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04336 04337 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04338 disable_dtmf_detect(op0); 04339 04340 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04341 disable_dtmf_detect(op1); 04342 04343 for (;;) { 04344 struct ast_channel *c0_priority[2] = {c0, c1}; 04345 struct ast_channel *c1_priority[2] = {c1, c0}; 04346 04347 /* Here's our main loop... Start by locking things, looking for private parts, 04348 and then balking if anything is wrong */ 04349 04350 ast_channel_lock(c0); 04351 while (ast_channel_trylock(c1)) { 04352 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04353 } 04354 04355 p0 = c0->tech_pvt; 04356 p1 = c1->tech_pvt; 04357 04358 if (op0 == p0) 04359 i0 = dahdi_get_index(c0, p0, 1); 04360 if (op1 == p1) 04361 i1 = dahdi_get_index(c1, p1, 1); 04362 04363 ast_channel_unlock(c0); 04364 ast_channel_unlock(c1); 04365 04366 if (!timeoutms || 04367 (op0 != p0) || 04368 (op1 != p1) || 04369 (ofd0 != c0->fds[0]) || 04370 (ofd1 != c1->fds[0]) || 04371 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04372 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04373 (oc0 != p0->owner) || 04374 (oc1 != p1->owner) || 04375 (t0 != p0->subs[SUB_REAL].inthreeway) || 04376 (t1 != p1->subs[SUB_REAL].inthreeway) || 04377 (oi0 != i0) || 04378 (oi1 != i1)) { 04379 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04380 op0->channel, oi0, op1->channel, oi1); 04381 res = AST_BRIDGE_RETRY; 04382 goto return_from_bridge; 04383 } 04384 04385 #ifdef PRI_2BCT 04386 q931c0 = p0->call; 04387 q931c1 = p1->call; 04388 if (p0->transfer && p1->transfer 04389 && q931c0 && q931c1 04390 && !triedtopribridge) { 04391 pri_channel_bridge(q931c0, q931c1); 04392 triedtopribridge = 1; 04393 } 04394 #endif 04395 04396 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04397 if (!who) { 04398 ast_debug(1, "Ooh, empty read...\n"); 04399 continue; 04400 } 04401 f = ast_read(who); 04402 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04403 *fo = f; 04404 *rc = who; 04405 res = AST_BRIDGE_COMPLETE; 04406 goto return_from_bridge; 04407 } 04408 if (f->frametype == AST_FRAME_DTMF) { 04409 if ((who == c0) && p0->pulsedial) { 04410 ast_write(c1, f); 04411 } else if ((who == c1) && p1->pulsedial) { 04412 ast_write(c0, f); 04413 } else { 04414 *fo = f; 04415 *rc = who; 04416 res = AST_BRIDGE_COMPLETE; 04417 goto return_from_bridge; 04418 } 04419 } 04420 ast_frfree(f); 04421 04422 /* Swap who gets priority */ 04423 priority = !priority; 04424 } 04425 04426 return_from_bridge: 04427 if (op0 == p0) 04428 dahdi_enable_ec(p0); 04429 04430 if (op1 == p1) 04431 dahdi_enable_ec(p1); 04432 04433 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04434 enable_dtmf_detect(op0); 04435 04436 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04437 enable_dtmf_detect(op1); 04438 04439 dahdi_unlink(slave, master, 1); 04440 04441 return res; 04442 }
| static int dahdi_call | ( | struct ast_channel * | ast, | |
| char * | rdest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 2444 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.
02445 { 02446 struct dahdi_pvt *p = ast->tech_pvt; 02447 int x, res, idx,mysig; 02448 char *c, *n, *l; 02449 #ifdef HAVE_PRI 02450 char *s = NULL; 02451 #endif 02452 char dest[256]; /* must be same length as p->dialdest */ 02453 ast_mutex_lock(&p->lock); 02454 ast_copy_string(dest, rdest, sizeof(dest)); 02455 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02456 if ((ast->_state == AST_STATE_BUSY)) { 02457 p->subs[SUB_REAL].needbusy = 1; 02458 ast_mutex_unlock(&p->lock); 02459 return 0; 02460 } 02461 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02462 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02463 ast_mutex_unlock(&p->lock); 02464 return -1; 02465 } 02466 p->dialednone = 0; 02467 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02468 { 02469 /* Special pseudo -- automatically up */ 02470 ast_setstate(ast, AST_STATE_UP); 02471 ast_mutex_unlock(&p->lock); 02472 return 0; 02473 } 02474 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02476 if (res) 02477 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02478 p->outgoing = 1; 02479 02480 if (IS_DIGITAL(ast->transfercapability)){ 02481 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 02482 } else { 02483 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02484 } 02485 02486 mysig = p->sig; 02487 if (p->outsigmod > -1) 02488 mysig = p->outsigmod; 02489 02490 switch (mysig) { 02491 case SIG_FXOLS: 02492 case SIG_FXOGS: 02493 case SIG_FXOKS: 02494 if (p->owner == ast) { 02495 /* Normal ring, on hook */ 02496 02497 /* Don't send audio while on hook, until the call is answered */ 02498 p->dialing = 1; 02499 if (p->use_callerid) { 02500 /* Generate the Caller-ID spill if desired */ 02501 if (p->cidspill) { 02502 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02503 ast_free(p->cidspill); 02504 } 02505 p->callwaitcas = 0; 02506 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02507 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02508 p->cidpos = 0; 02509 send_callerid(p); 02510 } 02511 } 02512 /* Choose proper cadence */ 02513 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02514 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02515 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02516 p->cidrings = cidrings[p->distinctivering - 1]; 02517 } else { 02518 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02519 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02520 p->cidrings = p->sendcalleridafter; 02521 } 02522 02523 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02524 c = strchr(dest, '/'); 02525 if (c) 02526 c++; 02527 if (c && (strlen(c) < p->stripmsd)) { 02528 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02529 c = NULL; 02530 } 02531 if (c) { 02532 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02533 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02534 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c); 02535 } else { 02536 p->dop.dialstr[0] = '\0'; 02537 } 02538 x = DAHDI_RING; 02539 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02540 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02541 ast_mutex_unlock(&p->lock); 02542 return -1; 02543 } 02544 p->dialing = 1; 02545 } else { 02546 /* Call waiting call */ 02547 p->callwaitrings = 0; 02548 if (ast->cid.cid_num) 02549 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02550 else 02551 p->callwait_num[0] = '\0'; 02552 if (ast->cid.cid_name) 02553 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02554 else 02555 p->callwait_name[0] = '\0'; 02556 /* Call waiting tone instead */ 02557 if (dahdi_callwait(ast)) { 02558 ast_mutex_unlock(&p->lock); 02559 return -1; 02560 } 02561 /* Make ring-back */ 02562 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02563 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02564 02565 } 02566 n = ast->cid.cid_name; 02567 l = ast->cid.cid_num; 02568 if (l) 02569 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02570 else 02571 p->lastcid_num[0] = '\0'; 02572 if (n) 02573 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02574 else 02575 p->lastcid_name[0] = '\0'; 02576 ast_setstate(ast, AST_STATE_RINGING); 02577 idx = dahdi_get_index(ast, p, 0); 02578 if (idx > -1) { 02579 p->subs[idx].needringing = 1; 02580 } 02581 break; 02582 case SIG_FXSLS: 02583 case SIG_FXSGS: 02584 case SIG_FXSKS: 02585 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 02586 ast_debug(1, "Ignore possible polarity reversal on line seizure\n"); 02587 p->polaritydelaytv = ast_tvnow(); 02588 } 02589 /* fall through */ 02590 case SIG_EMWINK: 02591 case SIG_EM: 02592 case SIG_EM_E1: 02593 case SIG_FEATD: 02594 case SIG_FEATDMF: 02595 case SIG_E911: 02596 case SIG_FGC_CAMA: 02597 case SIG_FGC_CAMAMF: 02598 case SIG_FEATB: 02599 case SIG_SFWINK: 02600 case SIG_SF: 02601 case SIG_SF_FEATD: 02602 case SIG_SF_FEATDMF: 02603 case SIG_FEATDMF_TA: 02604 case SIG_SF_FEATB: 02605 c = strchr(dest, '/'); 02606 if (c) 02607 c++; 02608 else 02609 c = ""; 02610 if (strlen(c) < p->stripmsd) { 02611 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02612 ast_mutex_unlock(&p->lock); 02613 return -1; 02614 } 02615 #ifdef HAVE_PRI 02616 /* Start the trunk, if not GR-303 */ 02617 if (!p->pri) { 02618 #endif 02619 x = DAHDI_START; 02620 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02621 if (res < 0) { 02622 if (errno != EINPROGRESS) { 02623 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02624 ast_mutex_unlock(&p->lock); 02625 return -1; 02626 } 02627 } 02628 #ifdef HAVE_PRI 02629 } 02630 #endif 02631 ast_debug(1, "Dialing '%s'\n", c); 02632 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02633 02634 c += p->stripmsd; 02635 02636 switch (mysig) { 02637 case SIG_FEATD: 02638 l = ast->cid.cid_num; 02639 if (l) 02640 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02641 else 02642 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02643 break; 02644 case SIG_FEATDMF: 02645 l = ast->cid.cid_num; 02646 if (l) 02647 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02648 else 02649 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02650 break; 02651 case SIG_FEATDMF_TA: 02652 { 02653 const char *cic, *ozz; 02654 02655 /* If you have to go through a Tandem Access point you need to use this */ 02656 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02657 if (!ozz) 02658 ozz = defaultozz; 02659 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02660 if (!cic) 02661 cic = defaultcic; 02662 if (!ozz || !cic) { 02663 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02664 ast_mutex_unlock(&p->lock); 02665 return -1; 02666 } 02667 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02668 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02669 p->whichwink = 0; 02670 } 02671 break; 02672 case SIG_E911: 02673 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02674 break; 02675 case SIG_FGC_CAMA: 02676 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02677 break; 02678 case SIG_FGC_CAMAMF: 02679 case SIG_FEATB: 02680 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02681 break; 02682 default: 02683 if (p->pulse) 02684 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02685 else 02686 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02687 break; 02688 } 02689 02690 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02691 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02692 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02693 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02694 p->echobreak = 1; 02695 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02696 } else 02697 p->echobreak = 0; 02698 if (!res) { 02699 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02700 int saveerr = errno; 02701 02702 x = DAHDI_ONHOOK; 02703 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02704 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02705 ast_mutex_unlock(&p->lock); 02706 return -1; 02707 } 02708 } else 02709 ast_debug(1, "Deferring dialing...\n"); 02710 02711 p->dialing = 1; 02712 if (ast_strlen_zero(c)) 02713 p->dialednone = 1; 02714 ast_setstate(ast, AST_STATE_DIALING); 02715 break; 02716 case 0: 02717 /* Special pseudo -- automatically up*/ 02718 ast_setstate(ast, AST_STATE_UP); 02719 break; 02720 case SIG_PRI: 02721 case SIG_BRI: 02722 case SIG_BRI_PTMP: 02723 case SIG_SS7: 02724 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02725 p->dialdest[0] = '\0'; 02726 p->dialing = 1; 02727 break; 02728 default: 02729 ast_debug(1, "not yet implemented\n"); 02730 ast_mutex_unlock(&p->lock); 02731 return -1; 02732 } 02733 #ifdef HAVE_SS7 02734 if (p->ss7) { 02735 char ss7_called_nai; 02736 int called_nai_strip; 02737 char ss7_calling_nai; 02738 int calling_nai_strip; 02739 const char *charge_str = NULL; 02740 const char *gen_address = NULL; 02741 const char *gen_digits = NULL; 02742 const char *gen_dig_type = NULL; 02743 const char *gen_dig_scheme = NULL; 02744 const char *gen_name = NULL; 02745 const char *jip_digits = NULL; 02746 const char *lspi_ident = NULL; 02747 const char *rlt_flag = NULL; 02748 const char *call_ref_id = NULL; 02749 const char *call_ref_pc = NULL; 02750 const char *send_far = NULL; 02751 02752 c = strchr(dest, '/'); 02753 if (c) { 02754 c++; 02755 } else { 02756 c = ""; 02757 } 02758 if (strlen(c) < p->stripmsd) { 02759 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02760 ast_mutex_unlock(&p->lock); 02761 return -1; 02762 } 02763 02764 if (!p->hidecallerid) { 02765 l = ast->cid.cid_num; 02766 } else { 02767 l = NULL; 02768 } 02769 02770 if (ss7_grab(p, p->ss7)) { 02771 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 02772 ast_mutex_unlock(&p->lock); 02773 return -1; 02774 } 02775 p->digital = IS_DIGITAL(ast->transfercapability); 02776 p->ss7call = isup_new_call(p->ss7->ss7); 02777 02778 if (!p->ss7call) { 02779 ss7_rel(p->ss7); 02780 ast_mutex_unlock(&p->lock); 02781 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 02782 return -1; 02783 } 02784 02785 called_nai_strip = 0; 02786 ss7_called_nai = p->ss7->called_nai; 02787 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 02788 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02789 called_nai_strip = strlen(p->ss7->internationalprefix); 02790 ss7_called_nai = SS7_NAI_INTERNATIONAL; 02791 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02792 called_nai_strip = strlen(p->ss7->nationalprefix); 02793 ss7_called_nai = SS7_NAI_NATIONAL; 02794 } else { 02795 ss7_called_nai = SS7_NAI_SUBSCRIBER; 02796 } 02797 } 02798 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 02799 02800 calling_nai_strip = 0; 02801 ss7_calling_nai = p->ss7->calling_nai; 02802 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 02803 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02804 calling_nai_strip = strlen(p->ss7->internationalprefix); 02805 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 02806 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02807 calling_nai_strip = strlen(p->ss7->nationalprefix); 02808 ss7_calling_nai = SS7_NAI_NATIONAL; 02809 } else { 02810 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 02811 } 02812 } 02813 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 02814 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 02815 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED ); 02816 02817 isup_set_oli(p->ss7call, ast->cid.cid_ani2); 02818 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 02819 02820 ast_channel_lock(ast); 02821 /* Set the charge number if it is set */ 02822 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 02823 if (charge_str) 02824 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 02825 02826 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 02827 if (gen_address) 02828 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 */ 02829 02830 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 02831 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 02832 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 02833 if (gen_digits) 02834 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 02835 02836 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 02837 if (gen_name) 02838 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 02839 02840 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 02841 if (jip_digits) 02842 isup_set_jip_digits(p->ss7call, jip_digits); 02843 02844 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 02845 if (lspi_ident) 02846 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 02847 02848 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 02849 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 02850 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 02851 } 02852 02853 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 02854 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 02855 if (call_ref_id && call_ref_pc) { 02856 isup_set_callref(p->ss7call, atoi(call_ref_id), 02857 call_ref_pc ? atoi(call_ref_pc) : 0); 02858 } 02859 02860 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 02861 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 02862 (isup_far(p->ss7->ss7, p->ss7call)); 02863 02864 ast_channel_unlock(ast); 02865 02866 isup_iam(p->ss7->ss7, p->ss7call); 02867 ast_setstate(ast, AST_STATE_DIALING); 02868 ss7_rel(p->ss7); 02869 } 02870 #endif /* HAVE_SS7 */ 02871 #ifdef HAVE_PRI 02872 if (p->pri) { 02873 struct pri_sr *sr; 02874 #ifdef SUPPORT_USERUSER 02875 const char *useruser; 02876 #endif 02877 int pridialplan; 02878 int dp_strip; 02879 int prilocaldialplan; 02880 int ldp_strip; 02881 int exclusive; 02882 const char *rr_str; 02883 int redirect_reason; 02884 02885 c = strchr(dest, '/'); 02886 if (c) { 02887 c++; 02888 } else { 02889 c = ""; 02890 } 02891 02892 l = NULL; 02893 n = NULL; 02894 if (!p->hidecallerid) { 02895 l = ast->cid.cid_num; 02896 if (!p->hidecalleridname) { 02897 n = ast->cid.cid_name; 02898 } 02899 } 02900 02901 if (strlen(c) < p->stripmsd) { 02902 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02903 ast_mutex_unlock(&p->lock); 02904 return -1; 02905 } 02906 if (mysig != SIG_FXSKS) { 02907 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02908 s = strchr(c + p->stripmsd, 'w'); 02909 if (s) { 02910 if (strlen(s) > 1) 02911 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02912 else 02913 p->dop.dialstr[0] = '\0'; 02914 *s = '\0'; 02915 } else { 02916 p->dop.dialstr[0] = '\0'; 02917 } 02918 } 02919 if (pri_grab(p, p->pri)) { 02920 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02921 ast_mutex_unlock(&p->lock); 02922 return -1; 02923 } 02924 if (!(p->call = pri_new_call(p->pri->pri))) { 02925 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02926 pri_rel(p->pri); 02927 ast_mutex_unlock(&p->lock); 02928 return -1; 02929 } 02930 if (!(sr = pri_sr_new())) { 02931 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02932 pri_rel(p->pri); 02933 ast_mutex_unlock(&p->lock); 02934 } 02935 if (p->bearer || (mysig == SIG_FXSKS)) { 02936 if (p->bearer) { 02937 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 02938 p->bearer->call = p->call; 02939 } else 02940 ast_debug(1, "I'm being setup with no bearer right now...\n"); 02941 02942 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02943 } 02944 p->digital = IS_DIGITAL(ast->transfercapability); 02945 02946 /* Should the picked channel be used exclusively? */ 02947 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 02948 exclusive = 1; 02949 } else { 02950 exclusive = 0; 02951 } 02952 02953 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02954 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02955 (p->digital ? -1 : 02956 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02957 if (p->pri->facilityenable) 02958 pri_facility_enable(p->pri->pri); 02959 02960 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02961 dp_strip = 0; 02962 pridialplan = p->pri->dialplan - 1; 02963 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */ 02964 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02965 if (pridialplan == -2) { 02966 dp_strip = strlen(p->pri->internationalprefix); 02967 } 02968 pridialplan = PRI_INTERNATIONAL_ISDN; 02969 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02970 if (pridialplan == -2) { 02971 dp_strip = strlen(p->pri->nationalprefix); 02972 } 02973 pridialplan = PRI_NATIONAL_ISDN; 02974 } else { 02975 pridialplan = PRI_LOCAL_ISDN; 02976 } 02977 } 02978 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') { 02979 switch (c[p->stripmsd]) { 02980 case 'U': 02981 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf); 02982 break; 02983 case 'I': 02984 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf); 02985 break; 02986 case 'N': 02987 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf); 02988 break; 02989 case 'L': 02990 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf); 02991 break; 02992 case 'S': 02993 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf); 02994 break; 02995 case 'V': 02996 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf); 02997 break; 02998 case 'R': 02999 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf); 03000 break; 03001 case 'u': 03002 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0); 03003 break; 03004 case 'e': 03005 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0); 03006 break; 03007 case 'x': 03008 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0); 03009 break; 03010 case 'f': 03011 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0); 03012 break; 03013 case 'n': 03014 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0); 03015 break; 03016 case 'p': 03017 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0); 03018 break; 03019 case 'r': 03020 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0); 03021 break; 03022 default: 03023 if (isalpha(c[p->stripmsd])) { 03024 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", 03025 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]); 03026 } 03027 break; 03028 } 03029 c++; 03030 } 03031 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03032 03033 ldp_strip = 0; 03034 prilocaldialplan = p->pri->localdialplan - 1; 03035 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */ 03036 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03037 if (prilocaldialplan == -2) { 03038 ldp_strip = strlen(p->pri->internationalprefix); 03039 } 03040 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03041 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03042 if (prilocaldialplan == -2) { 03043 ldp_strip = strlen(p->pri->nationalprefix); 03044 } 03045 prilocaldialplan = PRI_NATIONAL_ISDN; 03046 } else { 03047 prilocaldialplan = PRI_LOCAL_ISDN; 03048 } 03049 } 03050 if (l != NULL) { 03051 while (*l > '9' && *l != '*' && *l != '#') { 03052 switch (*l) { 03053 case 'U': 03054 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf); 03055 break; 03056 case 'I': 03057 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf); 03058 break; 03059 case 'N': 03060 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf); 03061 break; 03062 case 'L': 03063 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf); 03064 break; 03065 case 'S': 03066 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf); 03067 break; 03068 case 'V': 03069 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf); 03070 break; 03071 case 'R': 03072 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf); 03073 break; 03074 case 'u': 03075 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0); 03076 break; 03077 case 'e': 03078 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0); 03079 break; 03080 case 'x': 03081 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0); 03082 break; 03083 case 'f': 03084 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0); 03085 break; 03086 case 'n': 03087 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0); 03088 break; 03089 case 'p': 03090 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0); 03091 break; 03092 case 'r': 03093 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0); 03094 break; 03095 default: 03096 if (isalpha(*l)) { 03097 ast_log(LOG_WARNING, 03098 "Unrecognized prilocaldialplan %s modifier: %c\n", 03099 *l > 'Z' ? "NPI" : "TON", *l); 03100 } 03101 break; 03102 } 03103 l++; 03104 } 03105 } 03106 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03107 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03108 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03109 if (!strcasecmp(rr_str, "UNKNOWN")) 03110 redirect_reason = 0; 03111 else if (!strcasecmp(rr_str, "BUSY")) 03112 redirect_reason = 1; 03113 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER")) 03114 /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */ 03115 redirect_reason = 2; 03116 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03117 redirect_reason = 15; 03118 else 03119 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03120 } else 03121 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03122 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03123 03124 #ifdef SUPPORT_USERUSER 03125 /* User-user info */ 03126 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03127 03128 if (useruser) 03129 pri_sr_set_useruser(sr, useruser); 03130 #endif 03131 03132 if (pri_setup(p->pri->pri, p->call, sr)) { 03133 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03134 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03135 pri_rel(p->pri); 03136 ast_mutex_unlock(&p->lock); 03137 pri_sr_free(sr); 03138 return -1; 03139 } 03140 pri_sr_free(sr); 03141 ast_setstate(ast, AST_STATE_DIALING); 03142 pri_rel(p->pri); 03143 } 03144 #endif 03145 ast_mutex_unlock(&p->lock); 03146 return 0; 03147 }
| static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2404 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().
02405 { 02406 struct dahdi_pvt *p = ast->tech_pvt; 02407 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02408 if (p->cidspill) { 02409 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02410 ast_free(p->cidspill); 02411 } 02412 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02413 return -1; 02414 save_conference(p); 02415 /* Silence */ 02416 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02417 if (!p->callwaitrings && p->callwaitingcallerid) { 02418 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02419 p->callwaitcas = 1; 02420 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02421 } else { 02422 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02423 p->callwaitcas = 0; 02424 p->cidlen = 2400 + READ_SIZE * 4; 02425 } 02426 p->cidpos = 0; 02427 send_callerid(p); 02428 02429 return 0; 02430 }
| 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 1094 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().
01094 { 01095 /* recall that if a field is not included here it is initialized 01096 * to 0 or equivalent 01097 */ 01098 struct dahdi_chan_conf conf = { 01099 #ifdef HAVE_PRI 01100 .pri = { 01101 .nsf = PRI_NSF_NONE, 01102 .switchtype = PRI_SWITCH_NI2, 01103 .dialplan = PRI_UNKNOWN + 1, 01104 .localdialplan = PRI_NATIONAL_ISDN + 1, 01105 .nodetype = PRI_CPE, 01106 01107 .minunused = 2, 01108 .idleext = "", 01109 .idledial = "", 01110 .internationalprefix = "", 01111 .nationalprefix = "", 01112 .localprefix = "", 01113 .privateprefix = "", 01114 .unknownprefix = "", 01115 .resetinterval = -1, 01116 }, 01117 #endif 01118 #ifdef HAVE_SS7 01119 .ss7 = { 01120 .called_nai = SS7_NAI_NATIONAL, 01121 .calling_nai = SS7_NAI_NATIONAL, 01122 .internationalprefix = "", 01123 .nationalprefix = "", 01124 .subscriberprefix = "", 01125 .unknownprefix = "" 01126 }, 01127 #endif 01128 .chan = { 01129 .context = "default", 01130 .cid_num = "", 01131 .cid_name = "", 01132 .mohinterpret = "default", 01133 .mohsuggest = "", 01134 .parkinglot = "", 01135 .transfertobusy = 1, 01136 01137 .cid_signalling = CID_SIG_BELL, 01138 .cid_start = CID_START_RING, 01139 .dahditrcallerid = 0, 01140 .use_callerid = 1, 01141 .sig = -1, 01142 .outsigmod = -1, 01143 01144 .cid_rxgain = +5.0, 01145 01146 .tonezone = -1, 01147 01148 .echocancel.head.tap_length = 1, 01149 01150 .busycount = 3, 01151 01152 .accountcode = "", 01153 01154 .mailbox = "", 01155 01156 01157 .polarityonanswerdelay = 600, 01158 01159 .sendcalleridafter = DEFAULT_CIDRINGS, 01160 01161 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01162 .buf_no = numbufs 01163 }, 01164 .timing = { 01165 .prewinktime = -1, 01166 .preflashtime = -1, 01167 .winktime = -1, 01168 .flashtime = -1, 01169 .starttime = -1, 01170 .rxwinktime = -1, 01171 .rxflashtime = -1, 01172 .debouncetime = -1 01173 }, 01174 .is_sig_auto = 1, 01175 .smdi_port = "/dev/ttyS0", 01176 }; 01177 01178 return conf; 01179 }
| static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1484 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 1497 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01498 { 01499 dahdi_close(pri->fds[fd_num]); 01500 pri->fds[fd_num] = -1; 01501 }
| static void dahdi_close_ss7_fd | ( | struct dahdi_ss7 * | ss7, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 1505 of file chan_dahdi.c.
References dahdi_close(), and dahdi_ss7::fds.
Referenced by __unload_module(), dahdi_restart(), and linkset_addsigchan().
01506 { 01507 dahdi_close(ss7->fds[fd_num]); 01508 ss7->fds[fd_num] = -1; 01509 }
| static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
| int | sub_num | |||
| ) | [static] |
Definition at line 1490 of file chan_dahdi.c.
References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by alloc_sub(), destroy_dahdi_pvt(), pri_fixup_principle(), and unalloc_sub().
01491 { 01492 dahdi_close(chan_pvt->subs[sub_num].dfd); 01493 chan_pvt->subs[sub_num].dfd = -1; 01494 }
| static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
| int | muted | |||
| ) | [inline, static] |
Definition at line 2225 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, 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().
02226 { 02227 int x, y, res; 02228 x = muted; 02229 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 02230 y = 1; 02231 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02232 if (res) 02233 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02234 } 02235 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02236 if (res < 0) 02237 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02238 return res; 02239 }
| static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12513 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.
12514 { 12515 int channel; 12516 int ret; 12517 switch (cmd) { 12518 case CLI_INIT: 12519 e->command = "dahdi destroy channel"; 12520 e->usage = 12521 "Usage: dahdi destroy channel <chan num>\n" 12522 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 12523 return NULL; 12524 case CLI_GENERATE: 12525 return NULL; 12526 } 12527 if (a->argc != 4) 12528 return CLI_SHOWUSAGE; 12529 12530 channel = atoi(a->argv[3]); 12531 ret = dahdi_destroy_channel_bynum(channel); 12532 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 12533 }
| static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 8103 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 do_monitor().
08104 { 08105 struct dahdi_pvt *tmp = NULL; 08106 struct dahdi_pvt *prev = NULL; 08107 08108 tmp = iflist; 08109 while (tmp) { 08110 if (tmp->channel == channel) { 08111 int x = DAHDI_FLASH; 08112 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 */ 08113 destroy_channel(prev, tmp, 1); 08114 ast_module_unref(ast_module_info->self); 08115 return RESULT_SUCCESS; 08116 } 08117 prev = tmp; 08118 tmp = tmp->next; 08119 } 08120 return RESULT_FAILURE; 08121 }
| static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1592 of file chan_dahdi.c.
References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, 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.
01593 { 01594 struct dahdi_pvt *pvt; 01595 int idx; 01596 int dtmf = -1; 01597 01598 pvt = chan->tech_pvt; 01599 01600 ast_mutex_lock(&pvt->lock); 01601 01602 idx = dahdi_get_index(chan, pvt, 0); 01603 01604 if ((idx != SUB_REAL) || !pvt->owner) 01605 goto out; 01606 01607 #ifdef HAVE_PRI 01608 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01609 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01610 if (pvt->setup_ack) { 01611 if (!pri_grab(pvt, pvt->pri)) { 01612 pri_information(pvt->pri->pri, pvt->call, digit); 01613 pri_rel(pvt->pri); 01614 } else 01615 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01616 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01617 int res; 01618 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01619 res = strlen(pvt->dialdest); 01620 pvt->dialdest[res++] = digit; 01621 pvt->dialdest[res] = '\0'; 01622 } 01623 goto out; 01624 } 01625 #endif 01626 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01627 goto out; 01628 01629 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01630 int res; 01631 struct dahdi_dialoperation zo = { 01632 .op = DAHDI_DIAL_OP_APPEND, 01633 }; 01634 01635 zo.dialstr[0] = 'T'; 01636 zo.dialstr[1] = digit; 01637 zo.dialstr[2] = '\0'; 01638 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01639 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01640 else 01641 pvt->dialing = 1; 01642 } else { 01643 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 01644 pvt->dialing = 1; 01645 pvt->begindigit = digit; 01646 } 01647 01648 out: 01649 ast_mutex_unlock(&pvt->lock); 01650 01651 return 0; 01652 }
| static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1654 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, 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.
01655 { 01656 struct dahdi_pvt *pvt; 01657 int res = 0; 01658 int idx; 01659 int x; 01660 01661 pvt = chan->tech_pvt; 01662 01663 ast_mutex_lock(&pvt->lock); 01664 01665 idx = dahdi_get_index(chan, pvt, 0); 01666 01667 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 01668 goto out; 01669 01670 #ifdef HAVE_PRI 01671 /* This means that the digit was already sent via PRI signalling */ 01672 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01673 && !pvt->begindigit) 01674 goto out; 01675 #endif 01676 01677 if (pvt->begindigit) { 01678 x = -1; 01679 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 01680 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01681 pvt->dialing = 0; 01682 pvt->begindigit = 0; 01683 } 01684 01685 out: 01686 ast_mutex_unlock(&pvt->lock); 01687 01688 return res; 01689 }
| static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2054 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_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().
02055 { 02056 int res; 02057 02058 if (p->echocanon) { 02059 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 02060 02061 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 02062 02063 if (res) 02064 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02065 else 02066 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 02067 } 02068 02069 p->echocanon = 0; 02070 }
| static void dahdi_dnd | ( | struct dahdi_pvt * | dahdichan, | |
| int | on | |||
| ) | [static] |
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
| dahdichan | "Physical" DAHDI channel (e.g: DAHDI/5) | |
| on | 1 to enable, 0 to disable |
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 6541 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().
06542 { 06543 /* Do not disturb */ 06544 dahdichan->dnd = on; 06545 ast_verb(3, "%s DND on channel %d\n", 06546 on? "Enabled" : "Disabled", 06547 dahdichan->channel); 06548 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06549 "Channel: DAHDI/%d\r\n" 06550 "Status: %s\r\n", dahdichan->channel, 06551 on? "enabled" : "disabled"); 06552 }
| static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2005 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_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().
02006 { 02007 int x; 02008 int res; 02009 if (!p) 02010 return; 02011 if (p->echocanon) { 02012 ast_debug(1, "Echo cancellation already on\n"); 02013 return; 02014 } 02015 if (p->digital) { 02016 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 02017 return; 02018 } 02019 if (p->echocancel.head.tap_length) { 02020 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) { 02021 x = 1; 02022 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02023 if (res) 02024 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02025 } 02026 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 02027 if (res) { 02028 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02029 } else { 02030 p->echocanon = 1; 02031 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 02032 } 02033 } else 02034 ast_debug(1, "No echo cancellation requested\n"); 02035 }
| static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5659 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05660 { 05661 struct dahdi_pvt *p = ast->tech_pvt; 05662 struct ast_frame *f; 05663 ast_mutex_lock(&p->lock); 05664 f = __dahdi_exception(ast); 05665 ast_mutex_unlock(&p->lock); 05666 return f; 05667 }
| static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
| int | mode | |||
| ) | [static] |
Definition at line 13384 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().
13385 { 13386 if (p) { 13387 switch (mode) { 13388 case TRANSFER: 13389 p->fake_event = DAHDI_EVENT_WINKFLASH; 13390 break; 13391 case HANGUP: 13392 p->fake_event = DAHDI_EVENT_ONHOOK; 13393 break; 13394 default: 13395 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 13396 } 13397 } 13398 return 0; 13399 }
| static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 4444 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().
04445 { 04446 struct dahdi_pvt *p = newchan->tech_pvt; 04447 int x; 04448 ast_mutex_lock(&p->lock); 04449 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 04450 if (p->owner == oldchan) { 04451 p->owner = newchan; 04452 } 04453 for (x = 0; x < 3; x++) 04454 if (p->subs[x].owner == oldchan) { 04455 if (!x) 04456 dahdi_unlink(NULL, p, 0); 04457 p->subs[x].owner = newchan; 04458 } 04459 if (newchan->_state == AST_STATE_RINGING) 04460 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04461 update_conf(p); 04462 ast_mutex_unlock(&p->lock); 04463 return 0; 04464 }
| static int dahdi_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 4021 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.
04022 { 04023 struct dahdi_pvt *p = chan->tech_pvt; 04024 04025 if (!strcasecmp(data, "rxgain")) { 04026 ast_mutex_lock(&p->lock); 04027 snprintf(buf, len, "%f", p->rxgain); 04028 ast_mutex_unlock(&p->lock); 04029 } else if (!strcasecmp(data, "txgain")) { 04030 ast_mutex_lock(&p->lock); 04031 snprintf(buf, len, "%f", p->txgain); 04032 ast_mutex_unlock(&p->lock); 04033 } else { 04034 ast_copy_string(buf, "", len); 04035 } 04036 return 0; 04037 }
| static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 304 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), 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 1298 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().
01299 { 01300 int res; 01301 if (p->subs[SUB_REAL].owner == ast) 01302 res = 0; 01303 else if (p->subs[SUB_CALLWAIT].owner == ast) 01304 res = 1; 01305 else if (p->subs[SUB_THREEWAY].owner == ast) 01306 res = 2; 01307 else { 01308 res = -1; 01309 if (!nullok) 01310 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01311 } 01312 return res; 01313 }
| static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
| int | idx, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 4605 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().
04606 { 04607 struct dahdi_pvt *p = ast->tech_pvt; 04608 struct ast_frame *f = *dest; 04609 04610 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04611 04612 if (p->confirmanswer) { 04613 ast_debug(1, "Confirm answer on %s!\n", ast->name); 04614 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04615 of a DTMF digit */ 04616 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04617 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04618 *dest = &p->subs[idx].f; 04619 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04620 p->confirmanswer = 0; 04621 } else if (p->callwaitcas) { 04622 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04623 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 04624 if (p->cidspill) 04625 ast_free(p->cidspill); 04626 send_cwcidspill(p); 04627 } 04628 p->callwaitcas = 0; 04629 p->subs[idx].f.frametype = AST_FRAME_NULL; 04630 p->subs[idx].f.subclass = 0; 04631 *dest = &p->subs[idx].f; 04632 } else if (f->subclass == 'f') { 04633 /* Fax tone -- Handle and return NULL */ 04634 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 04635 p->faxhandled = 1; 04636 if (strcmp(ast->exten, "fax")) { 04637 const char *target_context = S_OR(ast->macrocontext, ast->context); 04638 04639 /* We need to unlock 'ast' here because ast_exists_extension has the 04640 * potential to start autoservice on the channel. Such action is prone 04641 * to deadlock. 04642 */ 04643 ast_mutex_unlock(&p->lock); 04644 ast_channel_unlock(ast); 04645 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04646 ast_channel_lock(ast); 04647 ast_mutex_lock(&p->lock); 04648 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 04649 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04650 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04651 if (ast_async_goto(ast, target_context, "fax", 1)) 04652 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04653 } else { 04654 ast_channel_lock(ast); 04655 ast_mutex_lock(&p->lock); 04656 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04657 } 04658 } else { 04659 ast_debug(1, "Already in a fax extension, not redirecting\n"); 04660 } 04661 } else { 04662 ast_debug(1, "Fax already handled\n"); 04663 } 04664 dahdi_confmute(p, 0); 04665 p->subs[idx].f.frametype = AST_FRAME_NULL; 04666 p->subs[idx].f.subclass = 0; 04667 *dest = &p->subs[idx].f; 04668 } 04669 }
| 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 4682 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().
04683 { 04684 int res, x; 04685 int idx, mysig; 04686 char *c; 04687 struct dahdi_pvt *p = ast->tech_pvt; 04688 pthread_t threadid; 04689 struct ast_channel *chan; 04690 struct ast_frame *f; 04691 04692 idx = dahdi_get_index(ast, p, 0); 04693 mysig = p->sig; 04694 if (p->outsigmod > -1) 04695 mysig = p->outsigmod; 04696 p->subs[idx].f.frametype = AST_FRAME_NULL; 04697 p->subs[idx].f.subclass = 0; 04698 p->subs[idx].f.datalen = 0; 04699 p->subs[idx].f.samples = 0; 04700 p->subs[idx].f.mallocd = 0; 04701 p->subs[idx].f.offset = 0; 04702 p->subs[idx].f.src = "dahdi_handle_event"; 04703 p->subs[idx].f.data.ptr = NULL; 04704 f = &p->subs[idx].f; 04705 04706 if (idx < 0) 04707 return &p->subs[idx].f; 04708 if (p->fake_event) { 04709 res = p->fake_event; 04710 p->fake_event = 0; 04711 } else 04712 res = dahdi_get_event(p->subs[idx].dfd); 04713 04714 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 04715 04716 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04717 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04718 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04719 #ifdef HAVE_PRI 04720 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04721 /* absorb event */ 04722 } else { 04723 #endif 04724 dahdi_confmute(p, 0); 04725 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 04726 p->subs[idx].f.subclass = res & 0xff; 04727 #ifdef HAVE_PRI 04728 } 04729 #endif 04730 dahdi_handle_dtmfup(ast, idx, &f); 04731 return f; 04732 } 04733 04734 if (res & DAHDI_EVENT_DTMFDOWN) { 04735 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 04736 /* Mute conference */ 04737 dahdi_confmute(p, 1); 04738 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 04739 p->subs[idx].f.subclass = res & 0xff; 04740 return &p->subs[idx].f; 04741 } 04742 04743 switch (res) { 04744 case DAHDI_EVENT_EC_DISABLED: 04745 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04746 p->echocanon = 0; 04747 break; 04748 case DAHDI_EVENT_BITSCHANGED: 04749 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 04750 case DAHDI_EVENT_PULSE_START: 04751 /* Stop tone if there's a pulse start and the PBX isn't started */ 04752 if (!ast->pbx) 04753 tone_zone_play_tone(p->subs[idx].dfd, -1); 04754 break; 04755 case DAHDI_EVENT_DIALCOMPLETE: 04756 if (p->inalarm) break; 04757 if ((p->radio || (p->oprmode < 0))) break; 04758 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 04759 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04760 return NULL; 04761 } 04762 if (!x) { /* if not still dialing in driver */ 04763 dahdi_enable_ec(p); 04764 if (p->echobreak) { 04765 dahdi_train_ec(p); 04766 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04767 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04768 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04769 p->echobreak = 0; 04770 } else { 04771 p->dialing = 0; 04772 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04773 /* if thru with dialing after offhook */ 04774 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04775 ast_setstate(ast, AST_STATE_UP); 04776 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04777 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04778 break; 04779 } else { /* if to state wait for offhook to dial rest */ 04780 /* we now wait for off hook */ 04781 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04782 } 04783 } 04784 if (ast->_state == AST_STATE_DIALING) { 04785 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04786 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 04787 } 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)))) { 04788 ast_setstate(ast, AST_STATE_RINGING); 04789 } else if (!p->answeronpolarityswitch) { 04790 ast_setstate(ast, AST_STATE_UP); 04791 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04792 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04793 /* If aops=0 and hops=1, this is necessary */ 04794 p->polarity = POLARITY_REV; 04795 } else { 04796 /* Start clean, so we can catch the change to REV polarity when party answers */ 04797 p->polarity = POLARITY_IDLE; 04798 } 04799 } 04800 } 04801 } 04802 break; 04803 case DAHDI_EVENT_ALARM: 04804 #ifdef HAVE_PRI 04805 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04806 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04807 /* T309 is not enabled : hangup calls when alarm occurs */ 04808 if (p->call) { 04809 if (p->pri && p->pri->pri) { 04810 if (!pri_grab(p, p->pri)) { 04811 pri_hangup(p->pri->pri, p->call, -1); 04812 pri_destroycall(p->pri->pri, p->call); 04813 p->call = NULL; 04814 pri_rel(p->pri); 04815 } else 04816 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04817 } else 04818 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04819 } 04820 if (p->owner) 04821 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04822 } 04823 } 04824 if (p->bearer) 04825 p->bearer->inalarm = 1; 04826 else 04827 #endif 04828 p->inalarm = 1; 04829 res = get_alarms(p); 04830 handle_alarms(p, res); 04831 #ifdef HAVE_PRI 04832 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04833 /* fall through intentionally */ 04834 } else { 04835 break; 04836 } 04837 #endif 04838 #ifdef HAVE_SS7 04839 if (p->sig == SIG_SS7) 04840 break; 04841 #endif 04842 case DAHDI_EVENT_ONHOOK: 04843 if (p->radio) { 04844 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04845 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 04846 break; 04847 } 04848 if (p->oprmode < 0) 04849 { 04850 if (p->oprmode != -1) break; 04851 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04852 { 04853 /* Make sure it starts ringing */ 04854 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04855 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04856 save_conference(p->oprpeer); 04857 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04858 } 04859 break; 04860 } 04861 switch (p->sig) { 04862 case SIG_FXOLS: 04863 case SIG_FXOGS: 04864 case SIG_FXOKS: 04865 p->onhooktime = time(NULL); 04866 p->msgstate = -1; 04867 /* Check for some special conditions regarding call waiting */ 04868 if (idx == SUB_REAL) { 04869 /* The normal line was hung up */ 04870 if (p->subs[SUB_CALLWAIT].owner) { 04871 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04872 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04873 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04874 unalloc_sub(p, SUB_CALLWAIT); 04875 #if 0 04876 p->subs[idx].needanswer = 0; 04877 p->subs[idx].needringing = 0; 04878 #endif 04879 p->callwaitingrepeat = 0; 04880 p->cidcwexpire = 0; 04881 p->owner = NULL; 04882 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04883 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04884 p->dialing = 1; 04885 dahdi_ring_phone(p); 04886 } else if (p->subs[SUB_THREEWAY].owner) { 04887 unsigned int mssinceflash; 04888 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04889 the private structure -- not especially easy or clean */ 04890 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 04891 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04892 DLA_UNLOCK(&p->lock); 04893 CHANNEL_DEADLOCK_AVOIDANCE(ast); 04894 /* We can grab ast and p in that order, without worry. We should make sure 04895 nothing seriously bad has happened though like some sort of bizarre double 04896 masquerade! */ 04897 DLA_LOCK(&p->lock); 04898 if (p->owner != ast) { 04899 ast_log(LOG_WARNING, "This isn't good...\n"); 04900 return NULL; 04901 } 04902 } 04903 if (!p->subs[SUB_THREEWAY].owner) { 04904 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04905 return NULL; 04906 } 04907 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04908 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 04909 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04910 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04911 hanging up. Hangup both channels now */ 04912 if (p->subs[SUB_THREEWAY].owner) 04913 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 04914 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04915 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04916 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04917 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04918 if (p->transfer) { 04919 /* In any case this isn't a threeway call anymore */ 04920 p->subs[SUB_REAL].inthreeway = 0; 04921 p->subs[SUB_THREEWAY].inthreeway = 0; 04922 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04923 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04924 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04925 /* Swap subs and dis-own channel */ 04926 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04927 p->owner = NULL; 04928 /* Ring the phone */ 04929 dahdi_ring_phone(p); 04930 } else { 04931 if ((res = attempt_transfer(p)) < 0) { 04932 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04933 if (p->subs[SUB_THREEWAY].owner) 04934 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04935 } else if (res) { 04936 /* Don't actually hang up at this point */ 04937 if (p->subs[SUB_THREEWAY].owner) 04938 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04939 break; 04940 } 04941 } 04942 } else { 04943 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04944 if (p->subs[SUB_THREEWAY].owner) 04945 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04946 } 04947 } else { 04948 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04949 /* Swap subs and dis-own channel */ 04950 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04951 p->owner = NULL; 04952 /* Ring the phone */ 04953 dahdi_ring_phone(p); 04954 } 04955 } 04956 } else { 04957 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 04958 } 04959 /* Fall through */ 04960 default: 04961 dahdi_disable_ec(p); 04962 return NULL; 04963 } 04964 break; 04965 case DAHDI_EVENT_RINGOFFHOOK: 04966 if (p->inalarm) break; 04967 if (p->oprmode < 0) 04968 { 04969 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04970 { 04971 /* Make sure it stops ringing */ 04972 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04973 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04974 restore_conference(p->oprpeer); 04975 } 04976 break; 04977 } 04978 if (p->radio) 04979 { 04980 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04981 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 04982 break; 04983 } 04984 /* for E911, its supposed to wait for offhook then dial 04985 the second half of the dial string */ 04986 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04987 c = strchr(p->dialdest, '/'); 04988 if (c) 04989 c++; 04990 else 04991 c = p->dialdest; 04992 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 04993 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 04994 if (strlen(p->dop.dialstr) > 4) { 04995 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 04996 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 04997 p->echorest[sizeof(p->echorest) - 1] = '\0'; 04998 p->echobreak = 1; 04999 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 05000 } else 05001 p->echobreak = 0; 05002 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05003 int saveerr = errno; 05004 05005 x = DAHDI_ONHOOK; 05006 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05007 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05008 return NULL; 05009 } 05010 p->dialing = 1; 05011 return &p->subs[idx].f; 05012 } 05013 switch (p->sig) { 05014 case SIG_FXOLS: 05015 case SIG_FXOGS: 05016 case SIG_FXOKS: 05017 switch (ast->_state) { 05018 case AST_STATE_RINGING: 05019 dahdi_enable_ec(p); 05020 dahdi_train_ec(p); 05021 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05022 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05023 /* Make sure it stops ringing */ 05024 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05025 ast_debug(1, "channel %d answered\n", p->channel); 05026 if (p->cidspill) { 05027 /* Cancel any running CallerID spill */ 05028 ast_free(p->cidspill); 05029 p->cidspill = NULL; 05030 } 05031 p->dialing = 0; 05032 p->callwaitcas = 0; 05033 if (p->confirmanswer) { 05034 /* Ignore answer if "confirm answer" is enabled */ 05035 p->subs[idx].f.frametype = AST_FRAME_NULL; 05036 p->subs[idx].f.subclass = 0; 05037 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05038 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05039 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05040 if (res < 0) { 05041 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05042 p->dop.dialstr[0] = '\0'; 05043 return NULL; 05044 } else { 05045 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05046 p->subs[idx].f.frametype = AST_FRAME_NULL; 05047 p->subs[idx].f.subclass = 0; 05048 p->dialing = 1; 05049 } 05050 p->dop.dialstr[0] = '\0'; 05051 ast_setstate(ast, AST_STATE_DIALING); 05052 } else 05053 ast_setstate(ast, AST_STATE_UP); 05054 return &p->subs[idx].f; 05055 case AST_STATE_DOWN: 05056 ast_setstate(ast, AST_STATE_RING); 05057 ast->rings = 1; 05058 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05059 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK; 05060 ast_debug(1, "channel %d picked up\n", p->channel); 05061 return &p->subs[idx].f; 05062 case AST_STATE_UP: 05063 /* Make sure it stops ringing */ 05064 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05065 /* Okay -- probably call waiting*/ 05066 if (ast_bridged_channel(p->owner)) 05067 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05068 p->subs[idx].needunhold = 1; 05069 break; 05070 case AST_STATE_RESERVED: 05071 /* Start up dialtone */ 05072 if (has_voicemail(p)) 05073 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05074 else 05075 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05076 break; 05077 default: 05078 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05079 } 05080 break; 05081 case SIG_FXSLS: 05082 case SIG_FXSGS: 05083 case SIG_FXSKS: 05084 if (ast->_state == AST_STATE_RING) { 05085 p->ringt = p->ringt_base; 05086 } 05087 05088 /* If we get a ring then we cannot be in 05089 * reversed polarity. So we reset to idle */ 05090 ast_debug(1, "Setting IDLE polarity due " 05091 "to ring. Old polarity was %d\n", 05092 p->polarity); 05093 p->polarity = POLARITY_IDLE; 05094 05095 /* Fall through */ 05096 case SIG_EM: 05097 case SIG_EM_E1: 05098 case SIG_EMWINK: 05099 case SIG_FEATD: 05100 case SIG_FEATDMF: 05101 case SIG_FEATDMF_TA: 05102 case SIG_E911: 05103 case SIG_FGC_CAMA: 05104 case SIG_FGC_CAMAMF: 05105 case SIG_FEATB: 05106 case SIG_SF: 05107 case SIG_SFWINK: 05108 case SIG_SF_FEATD: 05109 case SIG_SF_FEATDMF: 05110 case SIG_SF_FEATB: 05111 if (ast->_state == AST_STATE_PRERING) 05112 ast_setstate(ast, AST_STATE_RING); 05113 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05114 ast_debug(1, "Ring detected\n"); 05115 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05116 p->subs[idx].f.subclass = AST_CONTROL_RING; 05117 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05118 ast_debug(1, "Line answered\n"); 05119 if (p->confirmanswer) { 05120 p->subs[idx].f.frametype = AST_FRAME_NULL; 05121 p->subs[idx].f.subclass = 0; 05122 } else { 05123 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05124 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05125 ast_setstate(ast, AST_STATE_UP); 05126 } 05127 } else if (ast->_state != AST_STATE_RING) 05128 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05129 break; 05130 default: 05131 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05132 } 05133 break; 05134 case DAHDI_EVENT_RINGBEGIN: 05135 switch (p->sig) { 05136 case SIG_FXSLS: 05137 case SIG_FXSGS: 05138 case SIG_FXSKS: 05139 if (ast->_state == AST_STATE_RING) { 05140 p->ringt = p->ringt_base; 05141 } 05142 break; 05143 } 05144 break; 05145 case DAHDI_EVENT_RINGEROFF: 05146 if (p->inalarm) break; 05147 if ((p->radio || (p->oprmode < 0))) break; 05148 ast->rings++; 05149 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05150 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05151 ast_free(p->cidspill); 05152 p->cidspill = NULL; 05153 p->callwaitcas = 0; 05154 } 05155 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05156 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05157 break; 05158 case DAHDI_EVENT_RINGERON: 05159 break; 05160 case DAHDI_EVENT_NOALARM: 05161 p->inalarm = 0; 05162 #ifdef HAVE_PRI 05163 /* Extremely unlikely but just in case */ 05164 if (p->bearer) 05165 p->bearer->inalarm = 0; 05166 #endif 05167 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05168 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05169 "Channel: %d\r\n", p->channel); 05170 break; 05171 case DAHDI_EVENT_WINKFLASH: 05172 if (p->inalarm) break; 05173 if (p->radio) break; 05174 if (p->oprmode < 0) break; 05175 if (p->oprmode > 1) 05176 { 05177 struct dahdi_params par; 05178 05179 memset(&par, 0, sizeof(par)); 05180 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05181 { 05182 if (!par.rxisoffhook) 05183 { 05184 /* Make sure it stops ringing */ 05185 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05186 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05187 save_conference(p); 05188 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05189 } 05190 } 05191 break; 05192 } 05193 /* Remember last time we got a flash-hook */ 05194 p->flashtime = ast_tvnow(); 05195 switch (mysig) { 05196 case SIG_FXOLS: 05197 case SIG_FXOGS: 05198 case SIG_FXOKS: 05199 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05200 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05201 p->callwaitcas = 0; 05202 05203 if (idx != SUB_REAL) { 05204 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 05205 goto winkflashdone; 05206 } 05207 05208 if (p->subs[SUB_CALLWAIT].owner) { 05209 /* Swap to call-wait */ 05210 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05211 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05212 p->owner = p->subs[SUB_REAL].owner; 05213 ast_debug(1, "Making %s the new owner\n", p->owner->name); 05214 if (p->owner->_state == AST_STATE_RINGING) { 05215 ast_setstate(p->owner, AST_STATE_UP); 05216 p->subs[SUB_REAL].needanswer = 1; 05217 } 05218 p->callwaitingrepeat = 0; 05219 p->cidcwexpire = 0; 05220 /* Start music on hold if appropriate */ 05221 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05222 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05223 S_OR(p->mohsuggest, NULL), 05224 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05225 } 05226 p->subs[SUB_CALLWAIT].needhold = 1; 05227 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05228 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05229 S_OR(p->mohsuggest, NULL), 05230 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05231 } 05232 p->subs[SUB_REAL].needunhold = 1; 05233 } else if (!p->subs[SUB_THREEWAY].owner) { 05234 if (!p->threewaycalling) { 05235 /* Just send a flash if no 3-way calling */ 05236 p->subs[SUB_REAL].needflash = 1; 05237 goto winkflashdone; 05238 } else if (!check_for_conference(p)) { 05239 char cid_num[256]; 05240 char cid_name[256]; 05241 05242 cid_num[0] = 0; 05243 cid_name[0] = 0; 05244 if (p->dahditrcallerid && p->owner) { 05245 if (p->owner->cid.cid_num) 05246 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05247 if (p->owner->cid.cid_name) 05248 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05249 } 05250 /* XXX This section needs much more error checking!!! XXX */ 05251 /* Start a 3-way call if feasible */ 05252 if (!((ast->pbx) || 05253 (ast->_state == AST_STATE_UP) || 05254 (ast->_state == AST_STATE_RING))) { 05255 ast_debug(1, "Flash when call not up or ringing\n"); 05256 goto winkflashdone; 05257 } 05258 if (alloc_sub(p, SUB_THREEWAY)) { 05259 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05260 goto winkflashdone; 05261 } 05262 /* Make new channel */ 05263 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05264 if (p->dahditrcallerid) { 05265 if (!p->origcid_num) 05266 p->origcid_num = ast_strdup(p->cid_num); 05267 if (!p->origcid_name) 05268 p->origcid_name = ast_strdup(p->cid_name); 05269 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05270 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05271 } 05272 /* Swap things around between the three-way and real call */ 05273 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05274 /* Disable echo canceller for better dialing */ 05275 dahdi_disable_ec(p); 05276 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05277 if (res) 05278 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05279 p->owner = chan; 05280 if (!chan) { 05281 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05282 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 05283 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05284 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05285 dahdi_enable_ec(p); 05286 ast_hangup(chan); 05287 } else { 05288 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05289 int way3bridge = 0, cdr3way = 0; 05290 05291 if (!other) { 05292 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05293 } else 05294 way3bridge = 1; 05295 05296 if (p->subs[SUB_THREEWAY].owner->cdr) 05297 cdr3way = 1; 05298 05299 ast_verb(3, "Started three way call on channel %d\n", p->channel); 05300 05301 /* Start music on hold if appropriate */ 05302 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05303 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05304 S_OR(p->mohsuggest, NULL), 05305 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05306 } 05307 p->subs[SUB_THREEWAY].needhold = 1; 05308 } 05309 } 05310 } else { 05311 /* Already have a 3 way call */ 05312 if (p->subs[SUB_THREEWAY].inthreeway) { 05313 /* Call is already up, drop the last person */ 05314 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05315 /* If the primary call isn't answered yet, use it */ 05316 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05317 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05318 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05319 p->owner = p->subs[SUB_REAL].owner; 05320 } 05321 /* Drop the last call and stop the conference */ 05322 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05323 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05324 p->subs[SUB_REAL].inthreeway = 0; 05325 p->subs[SUB_THREEWAY].inthreeway = 0; 05326 } else { 05327 /* Lets see what we're up to */ 05328 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05329 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05330 int otherindex = SUB_THREEWAY; 05331 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05332 int way3bridge = 0, cdr3way = 0; 05333 05334 if (!other) { 05335 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05336 } else 05337 way3bridge = 1; 05338 05339 if (p->subs[SUB_THREEWAY].owner->cdr) 05340 cdr3way = 1; 05341 05342 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05343 /* Put them in the threeway, and flip */ 05344 p->subs[SUB_THREEWAY].inthreeway = 1; 05345 p->subs[SUB_REAL].inthreeway = 1; 05346 if (ast->_state == AST_STATE_UP) { 05347 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05348 otherindex = SUB_REAL; 05349 } 05350 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05351 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05352 p->subs[otherindex].needunhold = 1; 05353 p->owner = p->subs[SUB_REAL].owner; 05354 if (ast->_state == AST_STATE_RINGING) { 05355 ast_debug(1, "Enabling ringtone on real and threeway\n"); 05356 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05357 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05358 } 05359 } else { 05360 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05361 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05362 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05363 p->owner = p->subs[SUB_REAL].owner; 05364 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05365 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05366 p->subs[SUB_REAL].needunhold = 1; 05367 dahdi_enable_ec(p); 05368 } 05369 05370 } 05371 } 05372 winkflashdone: 05373 update_conf(p); 05374 break; 05375 case SIG_EM: 05376 case SIG_EM_E1: 05377 case SIG_FEATD: 05378 case SIG_SF: 05379 case SIG_SFWINK: 05380 case SIG_SF_FEATD: 05381 case SIG_FXSLS: 05382 case SIG_FXSGS: 05383 if (option_debug) { 05384 if (p->dialing) 05385 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 05386 else 05387 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05388 } 05389 break; 05390 case SIG_FEATDMF_TA: 05391 switch (p->whichwink) { 05392 case 0: 05393 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05394 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05395 break; 05396 case 1: 05397 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05398 break; 05399 case 2: 05400 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05401 return NULL; 05402 } 05403 p->whichwink++; 05404 /* Fall through */ 05405 case SIG_FEATDMF: 05406 case SIG_E911: 05407 case SIG_FGC_CAMAMF: 05408 case SIG_FGC_CAMA: 05409 case SIG_FEATB: 05410 case SIG_SF_FEATDMF: 05411 case SIG_SF_FEATB: 05412 case SIG_EMWINK: 05413 /* FGD MF and EMWINK *Must* wait for wink */ 05414 if (!ast_strlen_zero(p->dop.dialstr)) { 05415 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05416 if (res < 0) { 05417 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05418 p->dop.dialstr[0] = '\0'; 05419 return NULL; 05420 } else 05421 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05422 } 05423 p->dop.dialstr[0] = '\0'; 05424 break; 05425 default: 05426 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05427 } 05428 break; 05429 case DAHDI_EVENT_HOOKCOMPLETE: 05430 if (p->inalarm) break; 05431 if ((p->radio || (p->oprmode < 0))) break; 05432 switch (mysig) { 05433 case SIG_FXSLS: /* only interesting for FXS */ 05434 case SIG_FXSGS: 05435 case SIG_FXSKS: 05436 case SIG_EM: 05437 case SIG_EM_E1: 05438 case SIG_EMWINK: 05439 case SIG_FEATD: 05440 case SIG_SF: 05441 case SIG_SFWINK: 05442 case SIG_SF_FEATD: 05443 if (!ast_strlen_zero(p->dop.dialstr)) { 05444 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05445 if (res < 0) { 05446 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05447 p->dop.dialstr[0] = '\0'; 05448 return NULL; 05449 } else 05450 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05451 } 05452 p->dop.dialstr[0] = '\0'; 05453 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05454 break; 05455 case SIG_FEATDMF: 05456 case SIG_FEATDMF_TA: 05457 case SIG_E911: 05458 case SIG_FGC_CAMA: 05459 case SIG_FGC_CAMAMF: 05460 case SIG_FEATB: 05461 case SIG_SF_FEATDMF: 05462 case SIG_SF_FEATB: 05463 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05464 break; 05465 default: 05466 break; 05467 } 05468 break; 05469 case DAHDI_EVENT_POLARITY: 05470 /* 05471 * If we get a Polarity Switch event, this could be 05472 * due to line seizure, remote end connect or remote end disconnect. 05473 * 05474 * Check to see if we should change the polarity state and 05475 * mark the channel as UP or if this is an indication 05476 * of remote end disconnect. 05477 */ 05478 05479 if (p->polarityonanswerdelay > 0) { 05480 /* check if event is not too soon after OffHook or Answer */ 05481 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05482 switch (ast->_state) { 05483 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05484 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05485 if (p->answeronpolarityswitch) { 05486 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel); 05487 ast_setstate(p->owner, AST_STATE_UP); 05488 p->polarity = POLARITY_REV; 05489 if (p->hanguponpolarityswitch) { 05490 p->polaritydelaytv = ast_tvnow(); 05491 } 05492 } else { 05493 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel); 05494 } 05495 break; 05496 case AST_STATE_UP: /*!< Line is up */ 05497 case AST_STATE_RING: /*!< Line is ringing */ 05498 if (p->hanguponpolarityswitch) { 05499 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel); 05500 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05501 p->polarity = POLARITY_IDLE; 05502 } else { 05503 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel); 05504 } 05505 break; 05506 05507 case AST_STATE_DOWN: /*!< Channel is down and available */ 05508 case AST_STATE_RESERVED: /*!< Channel is down, but reserved */ 05509 case AST_STATE_OFFHOOK: /*!< Channel is off hook */ 05510 case AST_STATE_BUSY: /*!< Line is busy */ 05511 case AST_STATE_DIALING_OFFHOOK: /*!< Digits (or equivalent) have been dialed while offhook */ 05512 case AST_STATE_PRERING: /*!< Channel has detected an incoming call and is waiting for ring */ 05513 default: 05514 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05515 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state); 05516 } 05517 05518 } 05519 05520 } else { 05521 /* event is too soon after OffHook or Answer */ 05522 switch (ast->_state) { 05523 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05524 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05525 if (p->answeronpolarityswitch) { 05526 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state); 05527 } 05528 break; 05529 05530 case AST_STATE_UP: /*!< Line is up */ 05531 case AST_STATE_RING: /*!< Line is ringing */ 05532 if (p->hanguponpolarityswitch) { 05533 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); 05534 } 05535 break; 05536 05537 default: 05538 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05539 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state); 05540 } 05541 } 05542 } 05543 } 05544 /* Added more log_debug information below to provide a better indication of what is going on */ 05545 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) ); 05546 break; 05547 default: 05548 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05549 } 05550 return &p->subs[idx].f; 05551 }
| static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3380 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().
03381 { 03382 int res; 03383 int idx,x, law; 03384 /*static int restore_gains(struct dahdi_pvt *p);*/ 03385 struct dahdi_pvt *p = ast->tech_pvt; 03386 struct dahdi_pvt *tmp = NULL; 03387 struct dahdi_pvt *prev = NULL; 03388 struct dahdi_params par; 03389 03390 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 03391 if (!ast->tech_pvt) { 03392 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03393 return 0; 03394 } 03395 03396 ast_mutex_lock(&p->lock); 03397 03398 idx = dahdi_get_index(ast, p, 1); 03399 03400 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03401 x = 1; 03402 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03403 p->cid_num[0] = '\0'; 03404 p->cid_name[0] = '\0'; 03405 } 03406 03407 x = 0; 03408 dahdi_confmute(p, 0); 03409 p->muting = 0; 03410 restore_gains(p); 03411 if (p->origcid_num) { 03412 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03413 ast_free(p->origcid_num); 03414 p->origcid_num = NULL; 03415 } 03416 if (p->origcid_name) { 03417 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03418 ast_free(p->origcid_name); 03419 p->origcid_name = NULL; 03420 } 03421 if (p->dsp) 03422 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03423 p->exten[0] = '\0'; 03424 03425 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03426 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03427 p->ignoredtmf = 0; 03428 03429 if (idx > -1) { 03430 /* Real channel, do some fixup */ 03431 p->subs[idx].owner = NULL; 03432 p->subs[idx].needanswer = 0; 03433 p->subs[idx].needflash = 0; 03434 p->subs[idx].needringing = 0; 03435 p->subs[idx].needbusy = 0; 03436 p->subs[idx].needcongestion = 0; 03437 p->subs[idx].linear = 0; 03438 p->subs[idx].needcallerid = 0; 03439 p->polarity = POLARITY_IDLE; 03440 dahdi_setlinear(p->subs[idx].dfd, 0); 03441 if (idx == SUB_REAL) { 03442 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03443 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03444 if (p->subs[SUB_CALLWAIT].inthreeway) { 03445 /* We had flipped over to answer a callwait and now it's gone */ 03446 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 03447 /* Move to the call-wait, but un-own us until they flip back. */ 03448 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03449 unalloc_sub(p, SUB_CALLWAIT); 03450 p->owner = NULL; 03451 } else { 03452 /* The three way hung up, but we still have a call wait */ 03453 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03454 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03455 unalloc_sub(p, SUB_THREEWAY); 03456 if (p->subs[SUB_REAL].inthreeway) { 03457 /* This was part of a three way call. Immediately make way for 03458 another call */ 03459 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03460 p->owner = p->subs[SUB_REAL].owner; 03461 } else { 03462 /* This call hasn't been completed yet... Set owner to NULL */ 03463 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03464 p->owner = NULL; 03465 } 03466 p->subs[SUB_REAL].inthreeway = 0; 03467 } 03468 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03469 /* Move to the call-wait and switch back to them. */ 03470 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03471 unalloc_sub(p, SUB_CALLWAIT); 03472 p->owner = p->subs[SUB_REAL].owner; 03473 if (p->owner->_state != AST_STATE_UP) 03474 p->subs[SUB_REAL].needanswer = 1; 03475 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03476 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03477 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03478 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03479 unalloc_sub(p, SUB_THREEWAY); 03480 if (p->subs[SUB_REAL].inthreeway) { 03481 /* This was part of a three way call. Immediately make way for 03482 another call */ 03483 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03484 p->owner = p->subs[SUB_REAL].owner; 03485 } else { 03486 /* This call hasn't been completed yet... Set owner to NULL */ 03487 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03488 p->owner = NULL; 03489 } 03490 p->subs[SUB_REAL].inthreeway = 0; 03491 } 03492 } else if (idx == SUB_CALLWAIT) { 03493 /* Ditch the holding callwait call, and immediately make it availabe */ 03494 if (p->subs[SUB_CALLWAIT].inthreeway) { 03495 /* This is actually part of a three way, placed on hold. Place the third part 03496 on music on hold now */ 03497 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03498 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03499 S_OR(p->mohsuggest, NULL), 03500 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03501 } 03502 p->subs[SUB_THREEWAY].inthreeway = 0; 03503 /* Make it the call wait now */ 03504 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03505 unalloc_sub(p, SUB_THREEWAY); 03506 } else 03507 unalloc_sub(p, SUB_CALLWAIT); 03508 } else if (idx == SUB_THREEWAY) { 03509 if (p->subs[SUB_CALLWAIT].inthreeway) { 03510 /* The other party of the three way call is currently in a call-wait state. 03511 Start music on hold for them, and take the main guy out of the third call */ 03512 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03513 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03514 S_OR(p->mohsuggest, NULL), 03515 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03516 } 03517 p->subs[SUB_CALLWAIT].inthreeway = 0; 03518 } 03519 p->subs[SUB_REAL].inthreeway = 0; 03520 /* If this was part of a three way call index, let us make 03521 another three way call */ 03522 unalloc_sub(p, SUB_THREEWAY); 03523 } else { 03524 /* This wasn't any sort of call, but how are we an index? */ 03525 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03526 } 03527 } 03528 03529 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03530 p->owner = NULL; 03531 p->ringt = 0; 03532 p->distinctivering = 0; 03533 p->confirmanswer = 0; 03534 p->cidrings = 1; 03535 p->outgoing = 0; 03536 p->digital = 0; 03537 p->faxhandled = 0; 03538 p->pulsedial = 0; 03539 p->onhooktime = time(NULL); 03540 #if defined(HAVE_PRI) || defined(HAVE_SS7) 03541 p->proceeding = 0; 03542 p->dialing = 0; 03543 p->progress = 0; 03544 p->alerting = 0; 03545 p->setup_ack = 0; 03546 p->rlt = 0; 03547 #endif 03548 if (p->dsp) { 03549 ast_dsp_free(p->dsp); 03550 p->dsp = NULL; 03551 } 03552 03553 law = DAHDI_LAW_DEFAULT; 03554 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03555 if (res < 0) 03556 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03557 /* Perform low level hangup if no owner left */ 03558 #ifdef HAVE_SS7 03559 if (p->ss7) { 03560 if (p->ss7call) { 03561 if (!ss7_grab(p, p->ss7)) { 03562 if (!p->alreadyhungup) { 03563 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 03564 int icause = ast->hangupcause ? ast->hangupcause : -1; 03565 03566 if (cause) { 03567 if (atoi(cause)) 03568 icause = atoi(cause); 03569 } 03570 isup_rel(p->ss7->ss7, p->ss7call, icause); 03571 ss7_rel(p->ss7); 03572 p->alreadyhungup = 1; 03573 } else 03574 ast_log(LOG_WARNING, "Trying to hangup twice!\n"); 03575 } else { 03576 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic); 03577 res = -1; 03578 } 03579 } 03580 } 03581 #endif 03582 #ifdef HAVE_PRI 03583 if (p->pri) { 03584 #ifdef SUPPORT_USERUSER 03585 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03586 #endif 03587 03588 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03589 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03590 if (!pri_grab(p, p->pri)) { 03591 if (p->alreadyhungup) { 03592 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n"); 03593 03594 #ifdef SUPPORT_USERUSER 03595 pri_call_set_useruser(p->call, useruser); 03596 #endif 03597 03598 pri_hangup(p->pri->pri, p->call, -1); 03599 p->call = NULL; 03600 if (p->bearer) 03601 p->bearer->call = NULL; 03602 } else { 03603 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03604 int icause = ast->hangupcause ? ast->hangupcause : -1; 03605 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03606 03607 #ifdef SUPPORT_USERUSER 03608 pri_call_set_useruser(p->call, useruser); 03609 #endif 03610 03611 p->alreadyhungup = 1; 03612 if (p->bearer) 03613 p->bearer->alreadyhungup = 1; 03614 if (cause) { 03615 if (atoi(cause)) 03616 icause = atoi(cause); 03617 } 03618 pri_hangup(p->pri->pri, p->call, icause); 03619 } 03620 if (res < 0) 03621 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03622 pri_rel(p->pri); 03623 } else { 03624 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03625 res = -1; 03626 } 03627 } else { 03628 if (p->bearer) 03629 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03630 p->call = NULL; 03631 res = 0; 03632 } 03633 } 03634 #endif 03635 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP))) 03636 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03637 if (res < 0) { 03638 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03639 } 03640 switch (p->sig) { 03641 case SIG_FXOGS: 03642 case SIG_FXOLS: 03643 case SIG_FXOKS: 03644 memset(&par, 0, sizeof(par)); 03645 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03646 if (!res) { 03647 #if 0 03648 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03649 #endif 03650 /* If they're off hook, try playing congestion */ 03651 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03652 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03653 else 03654 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03655 } 03656 break; 03657 case SIG_FXSGS: 03658 case SIG_FXSLS: 03659 case SIG_FXSKS: 03660 /* Make sure we're not made available for at least two seconds assuming 03661 we were actually used for an inbound or outbound call. */ 03662 if (ast->_state != AST_STATE_RESERVED) { 03663 time(&p->guardtime); 03664 p->guardtime += 2; 03665 } 03666 break; 03667 default: 03668 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03669 } 03670 if (p->cidspill) 03671 ast_free(p->cidspill); 03672 if (p->sig) 03673 dahdi_disable_ec(p); 03674 x = 0; 03675 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03676 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03677 p->didtdd = 0; 03678 p->cidspill = NULL; 03679 p->callwaitcas = 0; 03680 p->callwaiting = p->permcallwaiting; 03681 p->hidecallerid = p->permhidecallerid; 03682 p->dialing = 0; 03683 p->rdnis[0] = '\0'; 03684 update_conf(p); 03685 reset_conf(p); 03686 /* Restore data mode */ 03687 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03688 x = 0; 03689 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03690 } 03691 #ifdef HAVE_PRI 03692 if (p->bearer) { 03693 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel); 03694 /* Free up the bearer channel as well, and 03695 don't use its file descriptor anymore */ 03696 update_conf(p->bearer); 03697 reset_conf(p->bearer); 03698 p->bearer->owner = NULL; 03699 p->bearer->realcall = NULL; 03700 p->bearer = NULL; 03701 p->subs[SUB_REAL].dfd = -1; 03702 p->pri = NULL; 03703 } 03704 #endif 03705 if (num_restart_pending == 0) 03706 restart_monitor(); 03707 } 03708 03709 p->callwaitingrepeat = 0; 03710 p->cidcwexpire = 0; 03711 p->oprmode = 0; 03712 ast->tech_pvt = NULL; 03713 ast_mutex_unlock(&p->lock); 03714 ast_module_unref(ast_module_info->self); 03715 ast_verb(3, "Hungup '%s'\n", ast->name); 03716 03717 ast_mutex_lock(&iflock); 03718 03719 if (p->restartpending) { 03720 num_restart_pending--; 03721 } 03722 03723 tmp = iflist; 03724 prev = NULL; 03725 if (p->destroy) { 03726 while (tmp) { 03727 if (tmp == p) { 03728 destroy_channel(prev, tmp, 0); 03729 break; 03730 } else { 03731 prev = tmp; 03732 tmp = tmp->next; 03733 } 03734 } 03735 } 03736 ast_mutex_unlock(&iflock); 03737 return 0; 03738 }
| static int dahdi_indicate | ( | struct ast_channel * | chan, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 6076 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().
06077 { 06078 struct dahdi_pvt *p = chan->tech_pvt; 06079 int res=-1; 06080 int idx; 06081 int func = DAHDI_FLASH; 06082 ast_mutex_lock(&p->lock); 06083 idx = dahdi_get_index(chan, p, 0); 06084 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 06085 if (idx == SUB_REAL) { 06086 switch (condition) { 06087 case AST_CONTROL_BUSY: 06088 #ifdef HAVE_PRI 06089 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06090 chan->hangupcause = AST_CAUSE_USER_BUSY; 06091 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06092 res = 0; 06093 } else if (!p->progress && 06094 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06095 && p->pri && !p->outgoing) { 06096 if (p->pri->pri) { 06097 if (!pri_grab(p, p->pri)) { 06098 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06099 pri_rel(p->pri); 06100 } 06101 else 06102 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06103 } 06104 p->progress = 1; 06105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06106 } else 06107 #endif 06108 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06109 break; 06110 case AST_CONTROL_RINGING: 06111 #ifdef HAVE_PRI 06112 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06113 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06114 if (p->pri->pri) { 06115 if (!pri_grab(p, p->pri)) { 06116 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06117 pri_rel(p->pri); 06118 } 06119 else 06120 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06121 } 06122 p->alerting = 1; 06123 } 06124 06125 #endif 06126 #ifdef HAVE_SS7 06127 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06128 if (p->ss7->ss7) { 06129 ss7_grab(p, p->ss7); 06130 06131 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06132 p->rlt = 1; 06133 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ 06134 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 06135 p->alerting = 1; 06136 ss7_rel(p->ss7); 06137 } 06138 } 06139 #endif 06140 06141 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 06142 06143 if (chan->_state != AST_STATE_UP) { 06144 if ((chan->_state != AST_STATE_RING) || 06145 ((p->sig != SIG_FXSKS) && 06146 (p->sig != SIG_FXSLS) && 06147 (p->sig != SIG_FXSGS))) 06148 ast_setstate(chan, AST_STATE_RINGING); 06149 } 06150 break; 06151 case AST_CONTROL_PROCEEDING: 06152 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06153 #ifdef HAVE_PRI 06154 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06155 && p->pri && !p->outgoing) { 06156 if (p->pri->pri) { 06157 if (!pri_grab(p, p->pri)) { 06158 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06159 pri_rel(p->pri); 06160 } 06161 else 06162 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06163 } 06164 p->proceeding = 1; 06165 p->dialing = 0; 06166 } 06167 #endif 06168 #ifdef HAVE_SS7 06169 /* This IF sends the FAR for an answered ALEG call */ 06170 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){ 06171 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06172 p->rlt = 1; 06173 } 06174 06175 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) { 06176 if (p->ss7->ss7) { 06177 ss7_grab(p, p->ss7); 06178 isup_acm(p->ss7->ss7, p->ss7call); 06179 p->proceeding = 1; 06180 ss7_rel(p->ss7); 06181 06182 } 06183 } 06184 #endif 06185 /* don't continue in ast_indicate */ 06186 res = 0; 06187 break; 06188 case AST_CONTROL_PROGRESS: 06189 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06190 #ifdef HAVE_PRI 06191 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06192 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06193 && p->pri && !p->outgoing) { 06194 if (p->pri->pri) { 06195 if (!pri_grab(p, p->pri)) { 06196 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06197 pri_rel(p->pri); 06198 } 06199 else 06200 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06201 } 06202 p->progress = 1; 06203 } 06204 #endif 06205 #ifdef HAVE_SS7 06206 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) { 06207 if (p->ss7->ss7) { 06208 ss7_grab(p, p->ss7); 06209 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 06210 p->progress = 1; 06211 ss7_rel(p->ss7); 06212 /* enable echo canceler here on SS7 calls */ 06213 dahdi_enable_ec(p); 06214 06215 } 06216 } 06217 #endif 06218 /* don't continue in ast_indicate */ 06219 res = 0; 06220 break; 06221 case AST_CONTROL_CONGESTION: 06222 chan->hangupcause = AST_CAUSE_CONGESTION; 06223 #ifdef HAVE_PRI 06224 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06225 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06226 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06227 res = 0; 06228 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06229 && p->pri && !p->outgoing) { 06230 if (p->pri) { 06231 if (!pri_grab(p, p->pri)) { 06232 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06233 pri_rel(p->pri); 06234 } else 06235 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06236 } 06237 p->progress = 1; 06238 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06239 } else 06240 #endif 06241 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06242 break; 06243 case AST_CONTROL_HOLD: 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_HOLD); 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_start(chan, data, p->mohinterpret); 06254 break; 06255 case AST_CONTROL_UNHOLD: 06256 #ifdef HAVE_PRI 06257 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06258 if (!pri_grab(p, p->pri)) { 06259 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06260 pri_rel(p->pri); 06261 } else 06262 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06263 } else 06264 #endif 06265 ast_moh_stop(chan); 06266 break; 06267 case AST_CONTROL_RADIO_KEY: 06268 if (p->radio) 06269 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 06270 res = 0; 06271 break; 06272 case AST_CONTROL_RADIO_UNKEY: 06273 if (p->radio) 06274 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 06275 res = 0; 06276 break; 06277 case AST_CONTROL_FLASH: 06278 /* flash hookswitch */ 06279 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06280 /* Clear out the dial buffer */ 06281 p->dop.dialstr[0] = '\0'; 06282 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06283 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06284 chan->name, strerror(errno)); 06285 } else 06286 res = 0; 06287 } else 06288 res = 0; 06289 break; 06290 case AST_CONTROL_SRCUPDATE: 06291 res = 0; 06292 break; 06293 case -1: 06294 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06295 break; 06296 } 06297 } else 06298 res = 0; 06299 ast_mutex_unlock(&p->lock); 06300 return res; 06301 }
Definition at line 4096 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().
04096 { 04097 int x; 04098 if (!slave || !master) { 04099 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04100 return; 04101 } 04102 for (x = 0; x < MAX_SLAVES; x++) { 04103 if (!master->slaves[x]) { 04104 master->slaves[x] = slave; 04105 break; 04106 } 04107 } 04108 if (x >= MAX_SLAVES) { 04109 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04110 master->slaves[MAX_SLAVES - 1] = slave; 04111 } 04112 if (slave->master) 04113 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04114 slave->master = master; 04115 04116 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04117 }
| static void dahdi_loopback | ( | struct dahdi_pvt * | p, | |
| int | enable | |||
| ) | [static] |
Definition at line 9848 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().
09849 { 09850 if (p->loopedback != enable) { 09851 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) { 09852 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno)); 09853 return; 09854 } 09855 p->loopedback = enable; 09856 } 09857 }
| 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 6303 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().
06304 { 06305 struct ast_channel *tmp; 06306 int deflaw; 06307 int res; 06308 int x,y; 06309 int features; 06310 struct ast_str *chan_name; 06311 struct ast_variable *v; 06312 struct dahdi_params ps; 06313 if (i->subs[idx].owner) { 06314 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 06315 return NULL; 06316 } 06317 y = 1; 06318 chan_name = ast_str_alloca(32); 06319 do { 06320 #ifdef HAVE_PRI 06321 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06322 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06323 else 06324 #endif 06325 if (i->channel == CHAN_PSEUDO) 06326 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 06327 else 06328 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 06329 for (x = 0; x < 3; x++) { 06330 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6)) 06331 break; 06332 } 06333 y++; 06334 } while (x < 3); 06335 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); 06336 if (!tmp) 06337 return NULL; 06338 tmp->tech = &dahdi_tech; 06339 memset(&ps, 0, sizeof(ps)); 06340 ps.channo = i->channel; 06341 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06342 if (res) { 06343 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06344 ps.curlaw = DAHDI_LAW_MULAW; 06345 } 06346 if (ps.curlaw == DAHDI_LAW_ALAW) 06347 deflaw = AST_FORMAT_ALAW; 06348 else 06349 deflaw = AST_FORMAT_ULAW; 06350 if (law) { 06351 if (law == DAHDI_LAW_ALAW) 06352 deflaw = AST_FORMAT_ALAW; 06353 else 06354 deflaw = AST_FORMAT_ULAW; 06355 } 06356 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 06357 tmp->nativeformats = deflaw; 06358 /* Start out assuming ulaw since it's smaller :) */ 06359 tmp->rawreadformat = deflaw; 06360 tmp->readformat = deflaw; 06361 tmp->rawwriteformat = deflaw; 06362 tmp->writeformat = deflaw; 06363 i->subs[idx].linear = 0; 06364 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 06365 features = 0; 06366 if (idx == SUB_REAL) { 06367 if (i->busydetect && CANBUSYDETECT(i)) 06368 features |= DSP_FEATURE_BUSY_DETECT; 06369 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 06370 features |= DSP_FEATURE_CALL_PROGRESS; 06371 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 06372 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 06373 features |= DSP_FEATURE_FAX_DETECT; 06374 } 06375 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06376 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 06377 i->hardwaredtmf = 0; 06378 features |= DSP_FEATURE_DIGIT_DETECT; 06379 } else if (NEED_MFDETECT(i)) { 06380 i->hardwaredtmf = 1; 06381 features |= DSP_FEATURE_DIGIT_DETECT; 06382 } 06383 } 06384 if (features) { 06385 if (i->dsp) { 06386 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 06387 } else { 06388 if (i->channel != CHAN_PSEUDO) 06389 i->dsp = ast_dsp_new(); 06390 else 06391 i->dsp = NULL; 06392 if (i->dsp) { 06393 i->dsp_features = features; 06394 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06395 /* We cannot do progress detection until receives PROGRESS message */ 06396 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) { 06397 /* Remember requested DSP features, don't treat 06398 talking as ANSWER */ 06399 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06400 features = 0; 06401 } 06402 #endif 06403 ast_dsp_set_features(i->dsp, features); 06404 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06405 if (!ast_strlen_zero(progzone)) 06406 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06407 if (i->busydetect && CANBUSYDETECT(i)) { 06408 ast_dsp_set_busy_count(i->dsp, i->busycount); 06409 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength); 06410 } 06411 } 06412 } 06413 } 06414 06415 if (state == AST_STATE_RING) 06416 tmp->rings = 1; 06417 tmp->tech_pvt = i; 06418 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06419 /* Only FXO signalled stuff can be picked up */ 06420 tmp->callgroup = i->callgroup; 06421 tmp->pickupgroup = i->pickupgroup; 06422 } 06423 if (!ast_strlen_zero(i->parkinglot)) 06424 ast_string_field_set(tmp, parkinglot, i->parkinglot); 06425 if (!ast_strlen_zero(i->language)) 06426 ast_string_field_set(tmp, language, i->language); 06427 if (!i->owner) 06428 i->owner = tmp; 06429 if (!ast_strlen_zero(i->accountcode)) 06430 ast_string_field_set(tmp, accountcode, i->accountcode); 06431 if (i->amaflags) 06432 tmp->amaflags = i->amaflags; 06433 i->subs[idx].owner = tmp; 06434 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06435 ast_string_field_set(tmp, call_forward, i->call_forward); 06436 /* If we've been told "no ADSI" then enforce it */ 06437 if (!i->adsi) 06438 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06439 if (!ast_strlen_zero(i->exten)) 06440 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06441 if (!ast_strlen_zero(i->rdnis)) 06442 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06443 if (!ast_strlen_zero(i->dnid)) 06444 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06445 06446 /* Don't use ast_set_callerid() here because it will 06447 * generate a needless NewCallerID event */ 06448 #ifdef PRI_ANI 06449 if (!ast_strlen_zero(i->cid_ani)) 06450 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06451 else 06452 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06453 #else 06454 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06455 #endif 06456 tmp->cid.cid_pres = i->callingpres; 06457 tmp->cid.cid_ton = i->cid_ton; 06458 tmp->cid.cid_ani2 = i->cid_ani2; 06459 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06460 tmp->transfercapability = transfercapability; 06461 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06462 if (transfercapability & AST_TRANS_CAP_DIGITAL) 06463 i->digital = 1; 06464 /* Assume calls are not idle calls unless we're told differently */ 06465 i->isidlecall = 0; 06466 i->alreadyhungup = 0; 06467 #endif 06468 /* clear the fake event in case we posted one before we had ast_channel */ 06469 i->fake_event = 0; 06470 /* Assure there is no confmute on this channel */ 06471 dahdi_confmute(i, 0); 06472 i->muting = 0; 06473 /* Configure the new channel jb */ 06474 ast_jb_configure(tmp, &global_jbconf); 06475 06476 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name); 06477 06478 for (v = i->vars ; v ; v = v->next) 06479 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06480 06481 if (startpbx) { 06482 if (ast_pbx_start(tmp)) { 06483 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06484 ast_hangup(tmp); 06485 i->owner = NULL; 06486 return NULL; 06487 } 06488 } 06489 06490 ast_module_ref(ast_module_info->self); 06491 return tmp; 06492 }
| static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1437 of file chan_dahdi.c.
References ast_log(), chan, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01438 { 01439 int fd; 01440 int isnum; 01441 int chan = 0; 01442 int bs; 01443 int x; 01444 isnum = 1; 01445 for (x = 0; x < strlen(fn); x++) { 01446 if (!isdigit(fn[x])) { 01447 isnum = 0; 01448 break; 01449 } 01450 } 01451 if (isnum) { 01452 chan = atoi(fn); 01453 if (chan < 1) { 01454 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01455 return -1; 01456 } 01457 fn = "/dev/dahdi/channel"; 01458 } 01459 fd = open(fn, O_RDWR | O_NONBLOCK); 01460 if (fd < 0) { 01461 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01462 return -1; 01463 } 01464 if (chan) { 01465 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01466 x = errno; 01467 close(fd); 01468 errno = x; 01469 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01470 return -1; 01471 } 01472 } 01473 bs = READ_SIZE; 01474 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01475 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01476 x = errno; 01477 close(fd); 01478 errno = x; 01479 return -1; 01480 } 01481 return fd; 01482 }
| static void dahdi_pri_error | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 10787 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().
10788 { 10789 int x, y; 10790 int dchan = -1, span = -1; 10791 int dchancount = 0; 10792 10793 if (pri) { 10794 for (x = 0; x < NUM_SPANS; x++) { 10795 for (y = 0; y < NUM_DCHANS; y++) { 10796 if (pris[x].dchans[y]) 10797 dchancount++; 10798 10799 if (pris[x].dchans[y] == pri) 10800 dchan = y; 10801 } 10802 if (dchan >= 0) { 10803 span = x; 10804 break; 10805 } 10806 dchancount = 0; 10807 } 10808 if ((dchancount > 1) && (span > -1)) 10809 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 10810 else 10811 ast_log(LOG_ERROR, "%s", s); 10812 } else 10813 ast_log(LOG_ERROR, "%s", s); 10814 10815 ast_mutex_lock(&pridebugfdlock); 10816 10817 if (pridebugfd >= 0) { 10818 if (write(pridebugfd, s, strlen(s)) < 0) { 10819 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10820 } 10821 } 10822 10823 ast_mutex_unlock(&pridebugfdlock); 10824 }
| static void dahdi_pri_message | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 10748 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().
10749 { 10750 int x, y; 10751 int dchan = -1, span = -1; 10752 int dchancount = 0; 10753 10754 if (pri) { 10755 for (x = 0; x < NUM_SPANS; x++) { 10756 for (y = 0; y < NUM_DCHANS; y++) { 10757 if (pris[x].dchans[y]) 10758 dchancount++; 10759 10760 if (pris[x].dchans[y] == pri) 10761 dchan = y; 10762 } 10763 if (dchan >= 0) { 10764 span = x; 10765 break; 10766 } 10767 dchancount = 0; 10768 } 10769 if (dchancount > 1 && (span > -1)) 10770 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 10771 else 10772 ast_verbose("%s", s); 10773 } else 10774 ast_verbose("%s", s); 10775 10776 ast_mutex_lock(&pridebugfdlock); 10777 10778 if (pridebugfd >= 0) { 10779 if (write(pridebugfd, s, strlen(s)) < 0) { 10780 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10781 } 10782 } 10783 10784 ast_mutex_unlock(&pridebugfdlock); 10785 }
Definition at line 1343 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().
01344 { 01345 #ifdef HAVE_PRI 01346 struct dahdi_pri *pri = (struct dahdi_pri*) data; 01347 #endif 01348 #ifdef HAVE_SS7 01349 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data; 01350 #endif 01351 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01352 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01353 if (data) { 01354 switch (p->sig) { 01355 #ifdef HAVE_PRI 01356 case SIG_BRI: 01357 case SIG_BRI_PTMP: 01358 case SIG_PRI: 01359 ast_mutex_unlock(&pri->lock); 01360 break; 01361 #endif 01362 #ifdef HAVE_SS7 01363 case SIG_SS7: 01364 ast_mutex_unlock(&ss7->lock); 01365 break; 01366 #endif 01367 default: 01368 break; 01369 } 01370 } 01371 #endif 01372 for (;;) { 01373 if (p->owner) { 01374 if (ast_channel_trylock(p->owner)) { 01375 DEADLOCK_AVOIDANCE(&p->lock); 01376 } else { 01377 ast_queue_frame(p->owner, f); 01378 ast_channel_unlock(p->owner); 01379 break; 01380 } 01381 } else 01382 break; 01383 } 01384 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01385 if (data) { 01386 switch (p->sig) { 01387 #ifdef HAVE_PRI 01388 case SIG_BRI: 01389 case SIG_BRI_PTMP: 01390 case SIG_PRI: 01391 ast_mutex_lock(&pri->lock); 01392 break; 01393 #endif 01394 #ifdef HAVE_SS7 01395 case SIG_SS7: 01396 ast_mutex_lock(&ss7->lock); 01397 break; 01398 #endif 01399 default: 01400 break; 01401 } 01402 } 01403 01404 #endif 01405 }
| static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5669 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.
05670 { 05671 struct dahdi_pvt *p = ast->tech_pvt; 05672 int res; 05673 int idx; 05674 void *readbuf; 05675 struct ast_frame *f; 05676 05677 while (ast_mutex_trylock(&p->lock)) { 05678 CHANNEL_DEADLOCK_AVOIDANCE(ast); 05679 } 05680 05681 idx = dahdi_get_index(ast, p, 0); 05682 05683 /* Hang up if we don't really exist */ 05684 if (idx < 0) { 05685 ast_log(LOG_WARNING, "We dont exist?\n"); 05686 ast_mutex_unlock(&p->lock); 05687 return NULL; 05688 } 05689 05690 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 05691 ast_mutex_unlock(&p->lock); 05692 return NULL; 05693 } 05694 05695 p->subs[idx].f.frametype = AST_FRAME_NULL; 05696 p->subs[idx].f.datalen = 0; 05697 p->subs[idx].f.samples = 0; 05698 p->subs[idx].f.mallocd = 0; 05699 p->subs[idx].f.offset = 0; 05700 p->subs[idx].f.subclass = 0; 05701 p->subs[idx].f.delivery = ast_tv(0,0); 05702 p->subs[idx].f.src = "dahdi_read"; 05703 p->subs[idx].f.data.ptr = NULL; 05704 05705 /* make sure it sends initial key state as first frame */ 05706 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05707 { 05708 struct dahdi_params ps; 05709 05710 memset(&ps, 0, sizeof(ps)); 05711 ps.channo = p->channel; 05712 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05713 ast_mutex_unlock(&p->lock); 05714 return NULL; 05715 } 05716 p->firstradio = 1; 05717 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05718 if (ps.rxisoffhook) 05719 { 05720 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 05721 } 05722 else 05723 { 05724 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 05725 } 05726 ast_mutex_unlock(&p->lock); 05727 return &p->subs[idx].f; 05728 } 05729 if (p->ringt == 1) { 05730 ast_mutex_unlock(&p->lock); 05731 return NULL; 05732 } 05733 else if (p->ringt > 0) 05734 p->ringt--; 05735 05736 if (p->subs[idx].needringing) { 05737 /* Send ringing frame if requested */ 05738 p->subs[idx].needringing = 0; 05739 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05740 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05741 ast_setstate(ast, AST_STATE_RINGING); 05742 ast_mutex_unlock(&p->lock); 05743 return &p->subs[idx].f; 05744 } 05745 05746 if (p->subs[idx].needbusy) { 05747 /* Send busy frame if requested */ 05748 p->subs[idx].needbusy = 0; 05749 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05750 p->subs[idx].f.subclass = AST_CONTROL_BUSY; 05751 ast_mutex_unlock(&p->lock); 05752 return &p->subs[idx].f; 05753 } 05754 05755 if (p->subs[idx].needcongestion) { 05756 /* Send congestion frame if requested */ 05757 p->subs[idx].needcongestion = 0; 05758 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05759 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION; 05760 ast_mutex_unlock(&p->lock); 05761 return &p->subs[idx].f; 05762 } 05763 05764 if (p->subs[idx].needcallerid) { 05765 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05766 S_OR(p->lastcid_name, NULL), 05767 S_OR(p->lastcid_num, NULL) 05768 ); 05769 p->subs[idx].needcallerid = 0; 05770 } 05771 05772 if (p->subs[idx].needanswer) { 05773 /* Send answer frame if requested */ 05774 p->subs[idx].needanswer = 0; 05775 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05776 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05777 ast_mutex_unlock(&p->lock); 05778 return &p->subs[idx].f; 05779 } 05780 05781 if (p->subs[idx].needflash) { 05782 /* Send answer frame if requested */ 05783 p->subs[idx].needflash = 0; 05784 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05785 p->subs[idx].f.subclass = AST_CONTROL_FLASH; 05786 ast_mutex_unlock(&p->lock); 05787 return &p->subs[idx].f; 05788 } 05789 05790 if (p->subs[idx].needhold) { 05791 /* Send answer frame if requested */ 05792 p->subs[idx].needhold = 0; 05793 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05794 p->subs[idx].f.subclass = AST_CONTROL_HOLD; 05795 ast_mutex_unlock(&p->lock); 05796 ast_debug(1, "Sending hold on '%s'\n", ast->name); 05797 return &p->subs[idx].f; 05798 } 05799 05800 if (p->subs[idx].needunhold) { 05801 /* Send answer frame if requested */ 05802 p->subs[idx].needunhold = 0; 05803 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05804 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD; 05805 ast_mutex_unlock(&p->lock); 05806 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 05807 return &p->subs[idx].f; 05808 } 05809 05810 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05811 if (!p->subs[idx].linear) { 05812 p->subs[idx].linear = 1; 05813 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05814 if (res) 05815 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 05816 } 05817 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05818 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05819 if (p->subs[idx].linear) { 05820 p->subs[idx].linear = 0; 05821 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05822 if (res) 05823 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 05824 } 05825 } else { 05826 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05827 ast_mutex_unlock(&p->lock); 05828 return NULL; 05829 } 05830 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 05831 CHECK_BLOCKING(ast); 05832 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05833 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05834 /* Check for hangup */ 05835 if (res < 0) { 05836 f = NULL; 05837 if (res == -1) { 05838 if (errno == EAGAIN) { 05839 /* Return "NULL" frame if there is nobody there */ 05840 ast_mutex_unlock(&p->lock); 05841 return &p->subs[idx].f; 05842 } else if (errno == ELAST) { 05843 f = __dahdi_exception(ast); 05844 } else 05845 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05846 } 05847 ast_mutex_unlock(&p->lock); 05848 return f; 05849 } 05850 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 05851 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05852 f = __dahdi_exception(ast); 05853 ast_mutex_unlock(&p->lock); 05854 return f; 05855 } 05856 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05857 int c; 05858 05859 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05860 if (c < 0) { 05861 ast_debug(1,"tdd_feed failed\n"); 05862 ast_mutex_unlock(&p->lock); 05863 return NULL; 05864 } 05865 if (c) { /* if a char to return */ 05866 p->subs[idx].f.subclass = 0; 05867 p->subs[idx].f.frametype = AST_FRAME_TEXT; 05868 p->subs[idx].f.mallocd = 0; 05869 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05870 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 05871 p->subs[idx].f.datalen = 1; 05872 *((char *) p->subs[idx].f.data.ptr) = c; 05873 ast_mutex_unlock(&p->lock); 05874 return &p->subs[idx].f; 05875 } 05876 } 05877 /* Ensure the CW timer decrements only on a single subchannel */ 05878 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05879 p->callwaitingrepeat--; 05880 } 05881 if (p->cidcwexpire) 05882 p->cidcwexpire--; 05883 /* Repeat callwaiting */ 05884 if (p->callwaitingrepeat == 1) { 05885 p->callwaitrings++; 05886 dahdi_callwait(ast); 05887 } 05888 /* Expire CID/CW */ 05889 if (p->cidcwexpire == 1) { 05890 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 05891 restore_conference(p); 05892 } 05893 if (p->subs[idx].linear) { 05894 p->subs[idx].f.datalen = READ_SIZE * 2; 05895 } else 05896 p->subs[idx].f.datalen = READ_SIZE; 05897 05898 /* Handle CallerID Transmission */ 05899 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05900 send_callerid(p); 05901 } 05902 05903 p->subs[idx].f.frametype = AST_FRAME_VOICE; 05904 p->subs[idx].f.subclass = ast->rawreadformat; 05905 p->subs[idx].f.samples = READ_SIZE; 05906 p->subs[idx].f.mallocd = 0; 05907 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05908 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 05909 #if 0 05910 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 05911 #endif 05912 if (p->dialing || /* Transmitting something */ 05913 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05914 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05915 ) { 05916 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05917 don't send anything */ 05918 p->subs[idx].f.frametype = AST_FRAME_NULL; 05919 p->subs[idx].f.subclass = 0; 05920 p->subs[idx].f.samples = 0; 05921 p->subs[idx].f.mallocd = 0; 05922 p->subs[idx].f.offset = 0; 05923 p->subs[idx].f.data.ptr = NULL; 05924 p->subs[idx].f.datalen= 0; 05925 } 05926 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) { 05927 /* Perform busy detection. etc on the dahdi line */ 05928 int mute; 05929 05930 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 05931 05932 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 05933 mute = ast_dsp_was_muted(p->dsp); 05934 if (p->muting != mute) { 05935 p->muting = mute; 05936 dahdi_confmute(p, mute); 05937 } 05938 05939 if (f) { 05940 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05941 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05942 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05943 a busy */ 05944 f = NULL; 05945 } 05946 } else if (f->frametype == AST_FRAME_DTMF) { 05947 #ifdef HAVE_PRI 05948 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 05949 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 05950 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 05951 /* Don't accept in-band DTMF when in overlap dial mode */ 05952 f->frametype = AST_FRAME_NULL; 05953 f->subclass = 0; 05954 } 05955 #endif 05956 /* DSP clears us of being pulse */ 05957 p->pulsedial = 0; 05958 } 05959 } 05960 } else 05961 f = &p->subs[idx].f; 05962 05963 if (f && (f->frametype == AST_FRAME_DTMF)) 05964 dahdi_handle_dtmfup(ast, idx, &f); 05965 05966 /* If we have a fake_event, trigger exception to handle it */ 05967 if (p->fake_event) 05968 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05969 05970 ast_mutex_unlock(&p->lock); 05971 return f; 05972 }
| static struct ast_channel * dahdi_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 9498 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().
09499 { 09500 ast_group_t groupmatch = 0; 09501 int channelmatch = -1; 09502 int roundrobin = 0; 09503 int callwait = 0; 09504 int busy = 0; 09505 struct dahdi_pvt *p; 09506 struct ast_channel *tmp = NULL; 09507 char *dest=NULL; 09508 int x; 09509 char *s; 09510 char opt=0; 09511 int res=0, y=0; 09512 int backwards = 0; 09513 #ifdef HAVE_PRI 09514 int crv; 09515 int bearer = -1; 09516 int trunkgroup; 09517 struct dahdi_pri *pri=NULL; 09518 #endif 09519 struct dahdi_pvt *exitpvt, *start, *end; 09520 ast_mutex_t *lock; 09521 int channelmatched = 0; 09522 int groupmatched = 0; 09523 09524 /* 09525 * data is ---v 09526 * Dial(DAHDI/pseudo[/extension]) 09527 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09528 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09529 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09530 * 09531 * g - channel group allocation search forward 09532 * G - channel group allocation search backward 09533 * r - channel group allocation round robin search forward 09534 * R - channel group allocation round robin search backward 09535 * 09536 * c - Wait for DTMF digit to confirm answer 09537 * r<cadance#> - Set distintive ring cadance number 09538 * d - Force bearer capability for ISDN/SS7 call to digital. 09539 */ 09540 09541 /* Assume we're locking the iflock */ 09542 lock = &iflock; 09543 start = iflist; 09544 end = ifend; 09545 if (data) { 09546 dest = ast_strdupa((char *)data); 09547 } else { 09548 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09549 return NULL; 09550 } 09551 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09552 /* Retrieve the group number */ 09553 char *stringp; 09554 09555 stringp = dest + 1; 09556 s = strsep(&stringp, "/"); 09557 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09558 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09559 return NULL; 09560 } 09561 groupmatch = ((ast_group_t) 1 << x); 09562 if (toupper(dest[0]) == 'G') { 09563 if (dest[0] == 'G') { 09564 backwards = 1; 09565 p = ifend; 09566 } else 09567 p = iflist; 09568 } else { 09569 if (dest[0] == 'R') { 09570 backwards = 1; 09571 p = round_robin[x]?round_robin[x]->prev:ifend; 09572 if (!p) 09573 p = ifend; 09574 } else { 09575 p = round_robin[x]?round_robin[x]->next:iflist; 09576 if (!p) 09577 p = iflist; 09578 } 09579 roundrobin = 1; 09580 } 09581 } else { 09582 char *stringp; 09583 09584 stringp = dest; 09585 s = strsep(&stringp, "/"); 09586 p = iflist; 09587 if (!strcasecmp(s, "pseudo")) { 09588 /* Special case for pseudo */ 09589 x = CHAN_PSEUDO; 09590 channelmatch = x; 09591 } 09592 #ifdef HAVE_PRI 09593 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09594 if ((trunkgroup < 1) || (crv < 1)) { 09595 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09596 return NULL; 09597 } 09598 res--; 09599 for (x = 0; x < NUM_SPANS; x++) { 09600 if (pris[x].trunkgroup == trunkgroup) { 09601 pri = pris + x; 09602 lock = &pri->lock; 09603 start = pri->crvs; 09604 end = pri->crvend; 09605 break; 09606 } 09607 } 09608 if (!pri) { 09609 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09610 return NULL; 09611 } 09612 channelmatch = crv; 09613 p = pris[x].crvs; 09614 } 09615 #endif 09616 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09617 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09618 return NULL; 09619 } else { 09620 channelmatch = x; 09621 } 09622 } 09623 /* Search for an unowned channel */ 09624 ast_mutex_lock(lock); 09625 exitpvt = p; 09626 while (p && !tmp) { 09627 if (roundrobin) 09628 round_robin[x] = p; 09629 #if 0 09630 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09631 #endif 09632 09633 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09634 ast_debug(1, "Using channel %d\n", p->channel); 09635 if (p->inalarm) 09636 goto next; 09637 09638 callwait = (p->owner != NULL); 09639 #ifdef HAVE_PRI 09640 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09641 if (p->sig != SIG_FXSKS) { 09642 /* Gotta find an actual channel to use for this 09643 CRV if this isn't a callwait */ 09644 bearer = pri_find_empty_chan(pri, 0); 09645 if (bearer < 0) { 09646 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09647 p = NULL; 09648 break; 09649 } 09650 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09651 } else { 09652 if (alloc_sub(p, 0)) { 09653 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09654 p = NULL; 09655 break; 09656 } else 09657 ast_debug(1, "Allocated placeholder pseudo channel\n"); 09658 09659 p->pri = pri; 09660 } 09661 } 09662 #endif 09663 if (p->channel == CHAN_PSEUDO) { 09664 p = chandup(p); 09665 if (!p) { 09666 break; 09667 } 09668 } 09669 if (p->owner) { 09670 if (alloc_sub(p, SUB_CALLWAIT)) { 09671 p = NULL; 09672 break; 09673 } 09674 } 09675 p->outgoing = 1; 09676 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09677 if (!tmp) { 09678 p->outgoing = 0; 09679 } 09680 #ifdef HAVE_PRI 09681 if (p->bearer) { 09682 /* Log owner to bearer channel, too */ 09683 p->bearer->owner = tmp; 09684 } 09685 #endif 09686 /* Make special notes */ 09687 if (res > 1) { 09688 if (opt == 'c') { 09689 /* Confirm answer */ 09690 p->confirmanswer = 1; 09691 } else if (opt == 'r') { 09692 /* Distinctive ring */ 09693 if (res < 3) 09694 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09695 else 09696 p->distinctivering = y; 09697 } else if (opt == 'd') { 09698 /* If this is an ISDN call, make it digital */ 09699 p->digital = 1; 09700 if (tmp) 09701 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09702 } else { 09703 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09704 } 09705 } 09706 /* Note if the call is a call waiting call */ 09707 if (tmp && callwait) 09708 tmp->cdrflags |= AST_CDR_CALLWAIT; 09709 break; 09710 } 09711 next: 09712 if (backwards) { 09713 p = p->prev; 09714 if (!p) 09715 p = end; 09716 } else { 09717 p = p->next; 09718 if (!p) 09719 p = start; 09720 } 09721 /* stop when you roll to the one that we started from */ 09722 if (p == exitpvt) 09723 break; 09724 } 09725 ast_mutex_unlock(lock); 09726 restart_monitor(); 09727 if (callwait) 09728 *cause = AST_CAUSE_BUSY; 09729 else if (!tmp) { 09730 if (channelmatched) { 09731 if (busy) 09732 *cause = AST_CAUSE_BUSY; 09733 } else if (groupmatched) { 09734 *cause = AST_CAUSE_CONGESTION; 09735 } 09736 } 09737 09738 return tmp; 09739 }
| static int dahdi_restart | ( | void | ) | [static] |
Definition at line 12564 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().
12565 { 12566 #if defined(HAVE_PRI) || defined(HAVE_SS7) 12567 int i, j; 12568 #endif 12569 int cancel_code; 12570 struct dahdi_pvt *p; 12571 12572 ast_mutex_lock(&restart_lock); 12573 12574 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 12575 dahdi_softhangup_all(); 12576 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 12577 12578 #if defined(HAVE_PRI) 12579 for (i = 0; i < NUM_SPANS; i++) { 12580 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 12581 cancel_code = pthread_cancel(pris[i].master); 12582 pthread_kill(pris[i].master, SIGURG); 12583 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12584 pthread_join(pris[i].master, NULL); 12585 ast_debug(4, "Joined thread of span %d\n", i); 12586 } 12587 } 12588 #endif 12589 12590 #if defined(HAVE_SS7) 12591 for (i = 0; i < NUM_SPANS; i++) { 12592 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) { 12593 cancel_code = pthread_cancel(linksets[i].master); 12594 pthread_kill(linksets[i].master, SIGURG); 12595 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code); 12596 pthread_join(linksets[i].master, NULL); 12597 ast_debug(4, "Joined thread of span %d\n", i); 12598 } 12599 } 12600 #endif 12601 12602 ast_mutex_lock(&monlock); 12603 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12604 cancel_code = pthread_cancel(monitor_thread); 12605 pthread_kill(monitor_thread, SIGURG); 12606 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12607 pthread_join(monitor_thread, NULL); 12608 ast_debug(4, "Joined monitor thread\n"); 12609 } 12610 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12611 12612 ast_mutex_lock(&mwi_thread_lock); 12613 while (mwi_thread_count > 0) { 12614 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count); 12615 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock); 12616 } 12617 ast_mutex_unlock(&mwi_thread_lock); 12618 ast_mutex_lock(&ss_thread_lock); 12619 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12620 int x = DAHDI_FLASH; 12621 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12622 12623 for (p = iflist; p; p = p->next) { 12624 if (p->owner) 12625 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 */ 12626 } 12627 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12628 } 12629 12630 /* ensure any created channels before monitor threads were stopped are hungup */ 12631 dahdi_softhangup_all(); 12632 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 12633 destroy_all_channels(); 12634 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12635 12636 ast_mutex_unlock(&monlock); 12637 12638 #ifdef HAVE_PRI 12639 for (i = 0; i < NUM_SPANS; i++) { 12640 for (j = 0; j < NUM_DCHANS; j++) 12641 dahdi_close_pri_fd(&(pris[i]), j); 12642 } 12643 12644 memset(pris, 0, sizeof(pris)); 12645 for (i = 0; i < NUM_SPANS; i++) { 12646 ast_mutex_init(&pris[i].lock); 12647 pris[i].offset = -1; 12648 pris[i].master = AST_PTHREADT_NULL; 12649 for (j = 0; j < NUM_DCHANS; j++) 12650 pris[i].fds[j] = -1; 12651 } 12652 pri_set_error(dahdi_pri_error); 12653 pri_set_message(dahdi_pri_message); 12654 #endif 12655 #ifdef HAVE_SS7 12656 for (i = 0; i < NUM_SPANS; i++) { 12657 for (j = 0; j < NUM_DCHANS; j++) 12658 dahdi_close_ss7_fd(&(linksets[i]), j); 12659 } 12660 12661 memset(linksets, 0, sizeof(linksets)); 12662 for (i = 0; i < NUM_SPANS; i++) { 12663 ast_mutex_init(&linksets[i].lock); 12664 linksets[i].master = AST_PTHREADT_NULL; 12665 for (j = 0; j < NUM_DCHANS; j++) 12666 linksets[i].fds[j] = -1; 12667 } 12668 ss7_set_error(dahdi_ss7_error); 12669 ss7_set_message(dahdi_ss7_message); 12670 #endif 12671 12672 if (setup_dahdi(2) != 0) { 12673 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12674 ast_mutex_unlock(&ss_thread_lock); 12675 return 1; 12676 } 12677 ast_mutex_unlock(&ss_thread_lock); 12678 ast_mutex_unlock(&restart_lock); 12679 return 0; 12680 }
| static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12682 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.
12683 { 12684 switch (cmd) { 12685 case CLI_INIT: 12686 e->command = "dahdi restart"; 12687 e->usage = 12688 "Usage: dahdi restart\n" 12689 " Restarts the DAHDI channels: destroys them all and then\n" 12690 " re-reads them from chan_dahdi.conf.\n" 12691 " Note that this will STOP any running CALL on DAHDI channels.\n" 12692 ""; 12693 return NULL; 12694 case CLI_GENERATE: 12695 return NULL; 12696 } 12697 if (a->argc != 2) 12698 return CLI_SHOWUSAGE; 12699 12700 if (dahdi_restart() != 0) 12701 return CLI_FAILURE; 12702 return CLI_SUCCESS; 12703 }
| static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4466 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().
04467 { 04468 int x; 04469 int res; 04470 /* Make sure our transmit state is on hook */ 04471 x = 0; 04472 x = DAHDI_ONHOOK; 04473 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04474 do { 04475 x = DAHDI_RING; 04476 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04477 if (res) { 04478 switch (errno) { 04479 case EBUSY: 04480 case EINTR: 04481 /* Wait just in case */ 04482 usleep(10000); 04483 continue; 04484 case EINPROGRESS: 04485 res = 0; 04486 break; 04487 default: 04488 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04489 res = 0; 04490 } 04491 } 04492 } while (res); 04493 return res; 04494 }
| static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3261 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().
03262 { 03263 /* Data will be our digit string */ 03264 struct dahdi_pvt *p; 03265 char *digits = (char *) data; 03266 03267 if (ast_strlen_zero(digits)) { 03268 ast_debug(1, "No digit string sent to application!\n"); 03269 return -1; 03270 } 03271 03272 p = (struct dahdi_pvt *)chan->tech_pvt; 03273 03274 if (!p) { 03275 ast_debug(1, "Unable to find technology private\n"); 03276 return -1; 03277 } 03278 03279 ast_mutex_lock(&p->lock); 03280 03281 if (!p->pri || !p->call) { 03282 ast_debug(1, "Unable to find pri or call on channel!\n"); 03283 ast_mutex_unlock(&p->lock); 03284 return -1; 03285 } 03286 03287 if (!pri_grab(p, p->pri)) { 03288 pri_keypad_facility(p->pri->pri, p->call, digits); 03289 pri_rel(p->pri); 03290 } else { 03291 ast_debug(1, "Unable to grab pri to send keypad facility!\n"); 03292 ast_mutex_unlock(&p->lock); 03293 return -1; 03294 } 03295 03296 ast_mutex_unlock(&p->lock); 03297 03298 return 0; 03299 }
| static int dahdi_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 15413 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.
15414 { 15415 #define END_SILENCE_LEN 400 15416 #define HEADER_MS 50 15417 #define TRAILER_MS 5 15418 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 15419 #define ASCII_BYTES_PER_CHAR 80 15420 15421 unsigned char *buf,*mybuf; 15422 struct dahdi_pvt *p = c->tech_pvt; 15423 struct pollfd fds[1]; 15424 int size,res,fd,len,x; 15425 int bytes=0; 15426 /* Initial carrier (imaginary) */ 15427 float cr = 1.0; 15428 float ci = 0.0; 15429 float scont = 0.0; 15430 int idx; 15431 15432 idx = dahdi_get_index(c, p, 0); 15433 if (idx < 0) { 15434 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 15435 return -1; 15436 } 15437 if (!text[0]) return(0); /* if nothing to send, dont */ 15438 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 15439 if (p->mate) 15440 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 15441 else 15442 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 15443 if (!buf) 15444 return -1; 15445 mybuf = buf; 15446 if (p->mate) { 15447 int codec = AST_LAW(p); 15448 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 15449 PUT_CLID_MARKMS; 15450 } 15451 /* Put actual message */ 15452 for (x = 0; text[x]; x++) { 15453 PUT_CLID(text[x]); 15454 } 15455 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 15456 PUT_CLID_MARKMS; 15457 } 15458 len = bytes; 15459 buf = mybuf; 15460 } else { 15461 len = tdd_generate(p->tdd, buf, text); 15462 if (len < 1) { 15463 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 15464 ast_free(mybuf); 15465 return -1; 15466 } 15467 } 15468 memset(buf + len, 0x7f, END_SILENCE_LEN); 15469 len += END_SILENCE_LEN; 15470 fd = p->subs[idx].dfd; 15471 while (len) { 15472 if (ast_check_hangup(c)) { 15473 ast_free(mybuf); 15474 return -1; 15475 } 15476 size = len; 15477 if (size > READ_SIZE) 15478 size = READ_SIZE; 15479 fds[0].fd = fd; 15480 fds[0].events = POLLOUT | POLLPRI; 15481 fds[0].revents = 0; 15482 res = poll(fds, 1, -1); 15483 if (!res) { 15484 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 15485 continue; 15486 } 15487 /* if got exception */ 15488 if (fds[0].revents & POLLPRI) { 15489 ast_free(mybuf); 15490 return -1; 15491 } 15492 if (!(fds[0].revents & POLLOUT)) { 15493 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 15494 continue; 15495 } 15496 res = write(fd, buf, size); 15497 if (res != size) { 15498 if (res == -1) { 15499 ast_free(mybuf); 15500 return -1; 15501 } 15502 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 15503 break; 15504 } 15505 len -= size; 15506 buf += size; 15507 } 15508 ast_free(mybuf); 15509 return(0); 15510 }
| static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13311 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.
13312 { 13313 int channel; 13314 int on; 13315 struct dahdi_pvt *dahdi_chan = NULL; 13316 13317 switch (cmd) { 13318 case CLI_INIT: 13319 e->command = "dahdi set dnd"; 13320 e->usage = 13321 "Usage: dahdi set dnd <chan#> <on|off>\n" 13322 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 13323 " Changes take effect immediately.\n" 13324 " <chan num> is the channel number\n" 13325 " <on|off> Enable or disable DND mode?\n" 13326 ; 13327 return NULL; 13328 case CLI_GENERATE: 13329 return NULL; 13330 } 13331 13332 if (a->argc != 5) 13333 return CLI_SHOWUSAGE; 13334 13335 if ((channel = atoi(a->argv[3])) <= 0) { 13336 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 13337 return CLI_SHOWUSAGE; 13338 } 13339 13340 if (ast_true(a->argv[4])) 13341 on = 1; 13342 else if (ast_false(a->argv[4])) 13343 on = 0; 13344 else { 13345 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 13346 return CLI_SHOWUSAGE; 13347 } 13348 13349 ast_mutex_lock(&iflock); 13350 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 13351 if (dahdi_chan->channel != channel) 13352 continue; 13353 13354 /* Found the channel. Actually set it */ 13355 dahdi_dnd(dahdi_chan, on); 13356 break; 13357 } 13358 ast_mutex_unlock(&iflock); 13359 13360 if (!dahdi_chan) { 13361 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13362 return CLI_FAILURE; 13363 } 13364 13365 return CLI_SUCCESS; 13366 }
| static int dahdi_set_hook | ( | int | fd, | |
| int | hs | |||
| ) | [inline, static] |
Definition at line 2208 of file chan_dahdi.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mkintf(), mwi_send_thread(), and ss_thread().
02209 { 02210 int x, res; 02211 02212 x = hs; 02213 res = ioctl(fd, DAHDI_HOOK, &x); 02214 02215 if (res < 0) { 02216 if (errno == EINPROGRESS) 02217 return 0; 02218 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02219 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02220 } 02221 02222 return res; 02223 }
| static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13168 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.
13169 { 13170 int channel; 13171 int gain; 13172 int tx; 13173 struct dahdi_hwgain hwgain; 13174 struct dahdi_pvt *tmp = NULL; 13175 13176 switch (cmd) { 13177 case CLI_INIT: 13178 e->command = "dahdi set hwgain"; 13179 e->usage = 13180 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 13181 " Sets the hardware gain on a a given channel, overriding the\n" 13182 " value provided at module loadtime, whether the channel is in\n" 13183 " use or not. Changes take effect immediately.\n" 13184 " <rx|tx> which direction do you want to change (relative to our module)\n" 13185 " <chan num> is the channel number relative to the device\n" 13186 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13187 return NULL; 13188 case CLI_GENERATE: 13189 return NULL; 13190 } 13191 13192 if (a->argc != 6) 13193 return CLI_SHOWUSAGE; 13194 13195 if (!strcasecmp("rx", a->argv[3])) 13196 tx = 0; /* rx */ 13197 else if (!strcasecmp("tx", a->argv[3])) 13198 tx = 1; /* tx */ 13199 else 13200 return CLI_SHOWUSAGE; 13201 13202 channel = atoi(a->argv[4]); 13203 gain = atof(a->argv[5])*10.0; 13204 13205 ast_mutex_lock(&iflock); 13206 13207 for (tmp = iflist; tmp; tmp = tmp->next) { 13208 13209 if (tmp->channel != channel) 13210 continue; 13211 13212 if (tmp->subs[SUB_REAL].dfd == -1) 13213 break; 13214 13215 hwgain.newgain = gain; 13216 hwgain.tx = tx; 13217 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 13218 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 13219 ast_mutex_unlock(&iflock); 13220 return CLI_FAILURE; 13221 } 13222 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 13223 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 13224 break; 13225 } 13226 13227 ast_mutex_unlock(&iflock); 13228 13229 if (tmp) 13230 return CLI_SUCCESS; 13231 13232 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13233 return CLI_FAILURE; 13234 13235 }
| static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13237 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.
13238 { 13239 int channel; 13240 float gain; 13241 int tx; 13242 int res; 13243 ast_mutex_t *lock; 13244 struct dahdi_pvt *tmp = NULL; 13245 13246 switch (cmd) { 13247 case CLI_INIT: 13248 e->command = "dahdi set swgain"; 13249 e->usage = 13250 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 13251 " Sets the software gain on a a given channel, overriding the\n" 13252 " value provided at module loadtime, whether the channel is in\n" 13253 " use or not. Changes take effect immediately.\n" 13254 " <rx|tx> which direction do you want to change (relative to our module)\n" 13255 " <chan num> is the channel number relative to the device\n" 13256 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13257 return NULL; 13258 case CLI_GENERATE: 13259 return NULL; 13260 } 13261 13262 lock = &iflock; 13263 13264 if (a->argc != 6) 13265 return CLI_SHOWUSAGE; 13266 13267 if (!strcasecmp("rx", a->argv[3])) 13268 tx = 0; /* rx */ 13269 else if (!strcasecmp("tx", a->argv[3])) 13270 tx = 1; /* tx */ 13271 else 13272 return CLI_SHOWUSAGE; 13273 13274 channel = atoi(a->argv[4]); 13275 gain = atof(a->argv[5]); 13276 13277 ast_mutex_lock(lock); 13278 for (tmp = iflist; tmp; tmp = tmp->next) { 13279 13280 if (tmp->channel != channel) 13281 continue; 13282 13283 if (tmp->subs[SUB_REAL].dfd == -1) 13284 break; 13285 13286 if (tx) 13287 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13288 else 13289 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13290 13291 if (res) { 13292 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 13293 ast_mutex_unlock(lock); 13294 return CLI_FAILURE; 13295 } 13296 13297 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 13298 tx ? "tx" : "rx", gain, channel); 13299 break; 13300 } 13301 ast_mutex_unlock(lock); 13302 13303 if (tmp) 13304 return CLI_SUCCESS; 13305 13306 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13307 return CLI_FAILURE; 13308 13309 }
| static int dahdi_setlaw | ( | int | dfd, | |
| int | law | |||
| ) | [static] |
Definition at line 9742 of file chan_dahdi.c.
Referenced by pri_dchannel(), and ss7_start_call().
09743 { 09744 return ioctl(dfd, DAHDI_SETLAW, &law); 09745 }
| static int dahdi_setlinear | ( | int | dfd, | |
| int | linear | |||
| ) | [static] |
Definition at line 1512 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
| static int dahdi_setoption | ( | struct ast_channel * | chan, | |
| int | option, | |||
| void * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 3840 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.
03841 { 03842 char *cp; 03843 signed char *scp; 03844 int x; 03845 int idx; 03846 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03847 struct oprmode *oprmode; 03848 03849 03850 /* all supported options require data */ 03851 if (!data || (datalen < 1)) { 03852 errno = EINVAL; 03853 return -1; 03854 } 03855 03856 switch (option) { 03857 case AST_OPTION_TXGAIN: 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 TXGAIN?\n"); 03862 return -1; 03863 } 03864 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03865 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law); 03866 case AST_OPTION_RXGAIN: 03867 scp = (signed char *) data; 03868 idx = dahdi_get_index(chan, p, 0); 03869 if (idx < 0) { 03870 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03871 return -1; 03872 } 03873 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03874 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law); 03875 case AST_OPTION_TONE_VERIFY: 03876 if (!p->dsp) 03877 break; 03878 cp = (char *) data; 03879 switch (*cp) { 03880 case 1: 03881 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03882 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03883 break; 03884 case 2: 03885 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03886 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03887 break; 03888 default: 03889 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03890 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03891 break; 03892 } 03893 break; 03894 case AST_OPTION_TDD: 03895 /* turn on or off TDD */ 03896 cp = (char *) data; 03897 p->mate = 0; 03898 if (!*cp) { /* turn it off */ 03899 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03900 if (p->tdd) 03901 tdd_free(p->tdd); 03902 p->tdd = 0; 03903 break; 03904 } 03905 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 03906 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03907 dahdi_disable_ec(p); 03908 /* otherwise, turn it on */ 03909 if (!p->didtdd) { /* if havent done it yet */ 03910 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03911 unsigned char *buf; 03912 int size, res, fd, len; 03913 struct pollfd fds[1]; 03914 03915 buf = mybuf; 03916 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03917 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03918 len = 40000; 03919 idx = dahdi_get_index(chan, p, 0); 03920 if (idx < 0) { 03921 ast_log(LOG_WARNING, "No index in TDD?\n"); 03922 return -1; 03923 } 03924 fd = p->subs[idx].dfd; 03925 while (len) { 03926 if (ast_check_hangup(chan)) 03927 return -1; 03928 size = len; 03929 if (size > READ_SIZE) 03930 size = READ_SIZE; 03931 fds[0].fd = fd; 03932 fds[0].events = POLLPRI | POLLOUT; 03933 fds[0].revents = 0; 03934 res = poll(fds, 1, -1); 03935 if (!res) { 03936 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 03937 continue; 03938 } 03939 /* if got exception */ 03940 if (fds[0].revents & POLLPRI) 03941 return -1; 03942 if (!(fds[0].revents & POLLOUT)) { 03943 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 03944 continue; 03945 } 03946 res = write(fd, buf, size); 03947 if (res != size) { 03948 if (res == -1) return -1; 03949 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03950 break; 03951 } 03952 len -= size; 03953 buf += size; 03954 } 03955 p->didtdd = 1; /* set to have done it now */ 03956 } 03957 if (*cp == 2) { /* Mate mode */ 03958 if (p->tdd) 03959 tdd_free(p->tdd); 03960 p->tdd = 0; 03961 p->mate = 1; 03962 break; 03963 } 03964 if (!p->tdd) { /* if we dont have one yet */ 03965 p->tdd = tdd_new(); /* allocate one */ 03966 } 03967 break; 03968 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03969 if (!p->dsp) 03970 break; 03971 cp = (char *) data; 03972 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03973 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03974 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 03975 break; 03976 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03977 cp = (char *) data; 03978 if (!*cp) { 03979 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03980 x = 0; 03981 dahdi_disable_ec(p); 03982 } else { 03983 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03984 x = 1; 03985 } 03986 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03987 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03988 break; 03989 case AST_OPTION_OPRMODE: /* Operator services mode */ 03990 oprmode = (struct oprmode *) data; 03991 pp = oprmode->peer->tech_pvt; 03992 p->oprmode = pp->oprmode = 0; 03993 /* setup peers */ 03994 p->oprpeer = pp; 03995 pp->oprpeer = p; 03996 /* setup modes, if any */ 03997 if (oprmode->mode) 03998 { 03999 pp->oprmode = oprmode->mode; 04000 p->oprmode = -oprmode->mode; 04001 } 04002 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 04003 oprmode->mode, chan->name,oprmode->peer->name); 04004 break; 04005 case AST_OPTION_ECHOCAN: 04006 cp = (char *) data; 04007 if (*cp) { 04008 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name); 04009 dahdi_enable_ec(p); 04010 } else { 04011 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name); 04012 dahdi_disable_ec(p); 04013 } 04014 break; 04015 } 04016 errno = 0; 04017 04018 return 0; 04019 }
| static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12839 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.
12840 { 12841 int channel; 12842 struct dahdi_pvt *tmp = NULL; 12843 struct dahdi_confinfo ci; 12844 struct dahdi_params ps; 12845 int x; 12846 ast_mutex_t *lock; 12847 struct dahdi_pvt *start; 12848 #ifdef HAVE_PRI 12849 char *c; 12850 int trunkgroup; 12851 struct dahdi_pri *pri=NULL; 12852 #endif 12853 switch (cmd) { 12854 case CLI_INIT: 12855 e->command = "dahdi show channel"; 12856 e->usage = 12857 "Usage: dahdi show channel <chan num>\n" 12858 " Detailed information about a given channel\n"; 12859 return NULL; 12860 case CLI_GENERATE: 12861 return NULL; 12862 } 12863 12864 lock = &iflock; 12865 start = iflist; 12866 12867 if (a->argc != 4) 12868 return CLI_SHOWUSAGE; 12869 #ifdef HAVE_PRI 12870 if ((c = strchr(a->argv[3], ':'))) { 12871 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12872 return CLI_SHOWUSAGE; 12873 if ((trunkgroup < 1) || (channel < 1)) 12874 return CLI_SHOWUSAGE; 12875 for (x = 0; x < NUM_SPANS; x++) { 12876 if (pris[x].trunkgroup == trunkgroup) { 12877 pri = pris + x; 12878 break; 12879 } 12880 } 12881 if (pri) { 12882 start = pri->crvs; 12883 lock = &pri->lock; 12884 } else { 12885 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12886 return CLI_FAILURE; 12887 } 12888 } else 12889 #endif 12890 channel = atoi(a->argv[3]); 12891 12892 ast_mutex_lock(lock); 12893 tmp = start; 12894 while (tmp) { 12895 if (tmp->channel == channel) { 12896 #ifdef HAVE_PRI 12897 if (pri) 12898 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12899 else 12900 #endif 12901 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 12902 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12903 ast_cli(a->fd, "Span: %d\n", tmp->span); 12904 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 12905 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12906 ast_cli(a->fd, "Context: %s\n", tmp->context); 12907 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 12908 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 12909 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 12910 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 12911 if (tmp->vars) { 12912 struct ast_variable *v; 12913 ast_cli(a->fd, "Variables:\n"); 12914 for (v = tmp->vars ; v ; v = v->next) 12915 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 12916 } 12917 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 12918 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 12919 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12920 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 12921 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12922 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)" : ""); 12923 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)" : ""); 12924 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)" : ""); 12925 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 12926 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 12927 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 12928 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12929 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 12930 if (tmp->busydetect) { 12931 #if defined(BUSYDETECT_TONEONLY) 12932 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 12933 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 12934 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 12935 #endif 12936 #ifdef BUSYDETECT_DEBUG 12937 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 12938 #endif 12939 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 12940 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength); 12941 } 12942 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 12943 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12944 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12945 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12946 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12947 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12948 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no"); 12949 ast_cli(a->fd, "Echo Cancellation:\n"); 12950 12951 if (tmp->echocancel.head.tap_length) { 12952 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 12953 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 12954 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 12955 } 12956 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 12957 } else { 12958 ast_cli(a->fd, "\tnone\n"); 12959 } 12960 if (tmp->master) 12961 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 12962 for (x = 0; x < MAX_SLAVES; x++) { 12963 if (tmp->slaves[x]) 12964 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12965 } 12966 #ifdef HAVE_SS7 12967 if (tmp->ss7) { 12968 ast_cli(a->fd, "CIC: %d\n", tmp->cic); 12969 } 12970 #endif 12971 #ifdef HAVE_PRI 12972 if (tmp->pri) { 12973 ast_cli(a->fd, "PRI Flags: "); 12974 if (tmp->resetting) 12975 ast_cli(a->fd, "Resetting "); 12976 if (tmp->call) 12977 ast_cli(a->fd, "Call "); 12978 if (tmp->bearer) 12979 ast_cli(a->fd, "Bearer "); 12980 ast_cli(a->fd, "\n"); 12981 if (tmp->logicalspan) 12982 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12983 else 12984 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 12985 } 12986 12987 #endif 12988 memset(&ci, 0, sizeof(ci)); 12989 ps.channo = tmp->channel; 12990 if (tmp->subs[SUB_REAL].dfd > -1) { 12991 memset(&ci, 0, sizeof(ci)); 12992 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12993 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12994 } 12995 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12996 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12997 } 12998 memset(&ps, 0, sizeof(ps)); 12999 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 13000 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 13001 } else { 13002 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 13003 } 13004 } 13005 ast_mutex_unlock(lock); 13006 return CLI_SUCCESS; 13007 } 13008 tmp = tmp->next; 13009 } 13010 13011 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13012 ast_mutex_unlock(lock); 13013 return CLI_FAILURE; 13014 }
| static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12715 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.
12716 { 12717 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12718 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12719 unsigned int targetnum = 0; 12720 int filtertype = 0; 12721 struct dahdi_pvt *tmp = NULL; 12722 char tmps[20] = ""; 12723 char statestr[20] = ""; 12724 char blockstr[20] = ""; 12725 ast_mutex_t *lock; 12726 struct dahdi_pvt *start; 12727 #ifdef HAVE_PRI 12728 int trunkgroup; 12729 struct dahdi_pri *pri = NULL; 12730 int x; 12731 #endif 12732 switch (cmd) { 12733 case CLI_INIT: 12734 e->command = "dahdi show channels [trunkgroup|group|context]"; 12735 e->usage = 12736 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n" 12737 " Shows a list of available channels with optional filtering\n" 12738 " <group> must be a number between 0 and 63\n"; 12739 return NULL; 12740 case CLI_GENERATE: 12741 return NULL; 12742 } 12743 12744 lock = &iflock; 12745 start = iflist; 12746 12747 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */ 12748 12749 if (!((a->argc == 3) || (a->argc == 5))) 12750 return CLI_SHOWUSAGE; 12751 12752 if (a->argc == 5) { 12753 #ifdef HAVE_PRI 12754 if (!strcasecmp(a->argv[3], "trunkgroup")) { 12755 /* this option requires no special handling, so leave filtertype to zero */ 12756 if ((trunkgroup = atoi(a->argv[4])) < 1) 12757 return CLI_SHOWUSAGE; 12758 for (x = 0; x < NUM_SPANS; x++) { 12759 if (pris[x].trunkgroup == trunkgroup) { 12760 pri = pris + x; 12761 break; 12762 } 12763 } 12764 if (pri) { 12765 start = pri->crvs; 12766 lock = &pri->lock; 12767 } else { 12768 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12769 return CLI_FAILURE; 12770 } 12771 } else 12772 #endif 12773 if (!strcasecmp(a->argv[3], "group")) { 12774 targetnum = atoi(a->argv[4]); 12775 if ((targetnum < 0) || (targetnum > 63)) 12776 return CLI_SHOWUSAGE; 12777 targetnum = 1 << targetnum; 12778 filtertype = 1; 12779 } else if (!strcasecmp(a->argv[3], "context")) { 12780 filtertype = 2; 12781 } 12782 } 12783 12784 ast_mutex_lock(lock); 12785 #ifdef HAVE_PRI 12786 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12787 #else 12788 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12789 #endif 12790 12791 tmp = start; 12792 while (tmp) { 12793 if (filtertype) { 12794 switch(filtertype) { 12795 case 1: /* dahdi show channels group <group> */ 12796 if (!(tmp->group & targetnum)) { 12797 tmp = tmp->next; 12798 continue; 12799 } 12800 break; 12801 case 2: /* dahdi show channels context <context> */ 12802 if (strcasecmp(tmp->context, a->argv[4])) { 12803 tmp = tmp->next; 12804 continue; 12805 } 12806 break; 12807 default: 12808 ; 12809 } 12810 } 12811 if (tmp->channel > 0) { 12812 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12813 } else 12814 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12815 12816 if (tmp->locallyblocked) 12817 blockstr[0] = 'L'; 12818 else 12819 blockstr[0] = ' '; 12820 12821 if (tmp->remotelyblocked) 12822 blockstr[1] = 'R'; 12823 else 12824 blockstr[1] = ' '; 12825 12826 blockstr[2] = '\0'; 12827 12828 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 12829 12830 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 12831 tmp = tmp->next; 12832 } 12833 ast_mutex_unlock(lock); 12834 return CLI_SUCCESS; 12835 #undef FORMAT 12836 #undef FORMAT2 12837 }
| static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13053 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.
13054 { 13055 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 13056 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 13057 int span; 13058 int res; 13059 char alarmstr[50]; 13060 13061 int ctl; 13062 struct dahdi_spaninfo s; 13063 13064 switch (cmd) { 13065 case CLI_INIT: 13066 e->command = "dahdi show status"; 13067 e->usage = 13068 "Usage: dahdi show status\n" 13069 " Shows a list of DAHDI cards with status\n"; 13070 return NULL; 13071 case CLI_GENERATE: 13072 return NULL; 13073 } 13074 ctl = open("/dev/dahdi/ctl", O_RDWR); 13075 if (ctl < 0) { 13076 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 13077 return CLI_FAILURE; 13078 } 13079 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 13080 13081 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 13082 s.spanno = span; 13083 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 13084 if (res) { 13085 continue; 13086 } 13087 alarmstr[0] = '\0'; 13088 if (s.alarms > 0) { 13089 if (s.alarms & DAHDI_ALARM_BLUE) 13090 strcat(alarmstr, "BLU/"); 13091 if (s.alarms & DAHDI_ALARM_YELLOW) 13092 strcat(alarmstr, "YEL/"); 13093 if (s.alarms & DAHDI_ALARM_RED) 13094 strcat(alarmstr, "RED/"); 13095 if (s.alarms & DAHDI_ALARM_LOOPBACK) 13096 strcat(alarmstr, "LB/"); 13097 if (s.alarms & DAHDI_ALARM_RECOVER) 13098 strcat(alarmstr, "REC/"); 13099 if (s.alarms & DAHDI_ALARM_NOTOPEN) 13100 strcat(alarmstr, "NOP/"); 13101 if (!strlen(alarmstr)) 13102 strcat(alarmstr, "UUU/"); 13103 if (strlen(alarmstr)) { 13104 /* Strip trailing / */ 13105 alarmstr[strlen(alarmstr) - 1] = '\0'; 13106 } 13107 } else { 13108 if (s.numchans) 13109 strcpy(alarmstr, "OK"); 13110 else 13111 strcpy(alarmstr, "UNCONFIGURED"); 13112 } 13113 13114 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count 13115 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 13116 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 13117 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 13118 "CAS" 13119 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 13120 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 13121 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 13122 "Unk" 13123 , s.lineconfig & DAHDI_CONFIG_CRC4 ? 13124 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL" 13125 , lbostr[s.lbo] 13126 ); 13127 } 13128 close(ctl); 13129 13130 return CLI_SUCCESS; 13131 #undef FORMAT 13132 #undef FORMAT2 13133 }
| static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13135 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.
13136 { 13137 int pseudo_fd = -1; 13138 struct dahdi_versioninfo vi; 13139 13140 switch (cmd) { 13141 case CLI_INIT: 13142 e->command = "dahdi show version"; 13143 e->usage = 13144 "Usage: dahdi show version\n" 13145 " Shows the DAHDI version in use\n"; 13146 return NULL; 13147 case CLI_GENERATE: 13148 return NULL; 13149 } 13150 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 13151 ast_cli(a->fd, "Failed to open control file to get version.\n"); 13152 return CLI_SUCCESS; 13153 } 13154 13155 strcpy(vi.version, "Unknown"); 13156 strcpy(vi.echo_canceller, "Unknown"); 13157 13158 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 13159 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 13160 else 13161 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 13162 13163 close(pseudo_fd); 13164 13165 return CLI_SUCCESS; 13166 }
| static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1755 of file chan_dahdi.c.
References buf, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, and SIG_SS7.
01756 { 01757 static char buf[256]; 01758 switch (sig) { 01759 case SIG_EM: 01760 return "E & M Immediate"; 01761 case SIG_EMWINK: 01762 return "E & M Wink"; 01763 case SIG_EM_E1: 01764 return "E & M E1"; 01765 case SIG_FEATD: 01766 return "Feature Group D (DTMF)"; 01767 case SIG_FEATDMF: 01768 return "Feature Group D (MF)"; 01769 case SIG_FEATDMF_TA: 01770 return "Feature Groud D (MF) Tandem Access"; 01771 case SIG_FEATB: 01772 return "Feature Group B (MF)"; 01773 case SIG_E911: 01774 return "E911 (MF)"; 01775 case SIG_FGC_CAMA: 01776 return "FGC/CAMA (Dialpulse)"; 01777 case SIG_FGC_CAMAMF: 01778 return "FGC/CAMA (MF)"; 01779 case SIG_FXSLS: 01780 return "FXS Loopstart"; 01781 case SIG_FXSGS: 01782 return "FXS Groundstart"; 01783 case SIG_FXSKS: 01784 return "FXS Kewlstart"; 01785 case SIG_FXOLS: 01786 return "FXO Loopstart"; 01787 case SIG_FXOGS: 01788 return "FXO Groundstart"; 01789 case SIG_FXOKS: 01790 return "FXO Kewlstart"; 01791 case SIG_PRI: 01792 return "ISDN PRI"; 01793 case SIG_BRI: 01794 return "ISDN BRI Point to Point"; 01795 case SIG_BRI_PTMP: 01796 return "ISDN BRI Point to MultiPoint"; 01797 case SIG_SS7: 01798 return "SS7"; 01799 case SIG_SF: 01800 return "SF (Tone) Immediate"; 01801 case SIG_SFWINK: 01802 return "SF (Tone) Wink"; 01803 case SIG_SF_FEATD: 01804 return "SF (Tone) with Feature Group D (DTMF)"; 01805 case SIG_SF_FEATDMF: 01806 return "SF (Tone) with Feature Group D (MF)"; 01807 case SIG_SF_FEATB: 01808 return "SF (Tone) with Feature Group B (MF)"; 01809 case SIG_GR303FXOKS: 01810 return "GR-303 with FXOKS"; 01811 case SIG_GR303FXSKS: 01812 return "GR-303 with FXSKS"; 01813 case 0: 01814 return "Pseudo"; 01815 default: 01816 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01817 return buf; 01818 } 01819 }
| static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 12535 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().
12536 { 12537 struct dahdi_pvt *p; 12538 retry: 12539 ast_mutex_lock(&iflock); 12540 for (p = iflist; p; p = p->next) { 12541 ast_mutex_lock(&p->lock); 12542 if (p->owner && !p->restartpending) { 12543 if (ast_channel_trylock(p->owner)) { 12544 if (option_debug > 2) 12545 ast_verbose("Avoiding deadlock\n"); 12546 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 12547 ast_mutex_unlock(&p->lock); 12548 ast_mutex_unlock(&iflock); 12549 goto retry; 12550 } 12551 if (option_debug > 2) 12552 ast_verbose("Softhanging up on %s\n", p->owner->name); 12553 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 12554 p->restartpending = 1; 12555 num_restart_pending++; 12556 ast_channel_unlock(p->owner); 12557 } 12558 ast_mutex_unlock(&p->lock); 12559 } 12560 ast_mutex_unlock(&iflock); 12561 }
| static void dahdi_ss7_error | ( | struct ss7 * | ss7, | |
| char * | s | |||
| ) | [static] |
Definition at line 10556 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 10541 of file chan_dahdi.c.
References ast_verbose, linksets, and NUM_SPANS.
Referenced by dahdi_restart(), and load_module().
10542 { 10543 #if 0 10544 int i; 10545 10546 for (i = 0; i < NUM_SPANS; i++) 10547 if (linksets[i].ss7 == ss7) 10548 break; 10549 10550 ast_verbose("[%d] %s", i+1, s); 10551 #else 10552 ast_verbose("%s", s); 10553 #endif 10554 }
| static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2037 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_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().
02038 { 02039 int x; 02040 int res; 02041 02042 if (p && p->echocanon && p->echotraining) { 02043 x = p->echotraining; 02044 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02045 if (res) 02046 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02047 else 02048 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 02049 } else { 02050 ast_debug(1, "No echo training requested\n"); 02051 } 02052 }
| static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
| struct dahdi_pvt * | master, | |||
| int | needlock | |||
| ) | [static] |
Definition at line 4040 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().
04041 { 04042 /* Unlink a specific slave or all slaves/masters from a given master */ 04043 int x; 04044 int hasslaves; 04045 if (!master) 04046 return; 04047 if (needlock) { 04048 ast_mutex_lock(&master->lock); 04049 if (slave) { 04050 while (ast_mutex_trylock(&slave->lock)) { 04051 DEADLOCK_AVOIDANCE(&master->lock); 04052 } 04053 } 04054 } 04055 hasslaves = 0; 04056 for (x = 0; x < MAX_SLAVES; x++) { 04057 if (master->slaves[x]) { 04058 if (!slave || (master->slaves[x] == slave)) { 04059 /* Take slave out of the conference */ 04060 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04061 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04062 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04063 master->slaves[x]->master = NULL; 04064 master->slaves[x] = NULL; 04065 } else 04066 hasslaves = 1; 04067 } 04068 if (!hasslaves) 04069 master->inconference = 0; 04070 } 04071 if (!slave) { 04072 if (master->master) { 04073 /* Take master out of the conference */ 04074 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04075 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04076 hasslaves = 0; 04077 for (x = 0; x < MAX_SLAVES; x++) { 04078 if (master->master->slaves[x] == master) 04079 master->master->slaves[x] = NULL; 04080 else if (master->master->slaves[x]) 04081 hasslaves = 1; 04082 } 04083 if (!hasslaves) 04084 master->master->inconference = 0; 04085 } 04086 master->master = NULL; 04087 } 04088 update_conf(master); 04089 if (needlock) { 04090 if (slave) 04091 ast_mutex_unlock(&slave->lock); 04092 ast_mutex_unlock(&master->lock); 04093 } 04094 }
| static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 313 of file chan_dahdi.c.
Referenced by ss_thread().
| static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
| int | idx | |||
| ) | [static] |
Definition at line 6514 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06515 { 06516 int j; 06517 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 06518 for (;;) 06519 { 06520 /* set bits of interest */ 06521 j = DAHDI_IOMUX_SIGEVENT; 06522 /* wait for some happening */ 06523 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06524 /* exit loop if we have it */ 06525 if (j & DAHDI_IOMUX_SIGEVENT) break; 06526 } 06527 /* get the event info */ 06528 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06529 return 0; 06530 }
| static int dahdi_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 5996 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.
05997 { 05998 struct dahdi_pvt *p = ast->tech_pvt; 05999 int res; 06000 int idx; 06001 idx = dahdi_get_index(ast, p, 0); 06002 if (idx < 0) { 06003 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06004 return -1; 06005 } 06006 06007 #if 0 06008 #ifdef HAVE_PRI 06009 ast_mutex_lock(&p->lock); 06010 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06011 if (p->pri->pri) { 06012 if (!pri_grab(p, p->pri)) { 06013 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06014 pri_rel(p->pri); 06015 } else 06016 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06017 } 06018 p->proceeding=1; 06019 } 06020 ast_mutex_unlock(&p->lock); 06021 #endif 06022 #endif 06023 /* Write a frame of (presumably voice) data */ 06024 if (frame->frametype != AST_FRAME_VOICE) { 06025 if (frame->frametype != AST_FRAME_IMAGE) 06026 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06027 return 0; 06028 } 06029 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06030 (frame->subclass != AST_FORMAT_ULAW) && 06031 (frame->subclass != AST_FORMAT_ALAW)) { 06032 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06033 return -1; 06034 } 06035 if (p->dialing) { 06036 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06037 return 0; 06038 } 06039 if (!p->owner) { 06040 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 06041 return 0; 06042 } 06043 if (p->cidspill) { 06044 ast_debug(1, "Dropping frame since I've still got a callerid spill\n"); 06045 return 0; 06046 } 06047 /* Return if it's not valid data */ 06048 if (!frame->data.ptr || !frame->datalen) 06049 return 0; 06050 06051 if (frame->subclass == AST_FORMAT_SLINEAR) { 06052 if (!p->subs[idx].linear) { 06053 p->subs[idx].linear = 1; 06054 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06055 if (res) 06056 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06057 } 06058 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 06059 } else { 06060 /* x-law already */ 06061 if (p->subs[idx].linear) { 06062 p->subs[idx].linear = 0; 06063 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06064 if (res) 06065 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06066 } 06067 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 06068 } 06069 if (res < 0) { 06070 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06071 return -1; 06072 } 06073 return 0; 06074 }
| static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3222 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().
03223 { 03224 int x; 03225 struct dahdi_pvt *p, *pl; 03226 03227 while (num_restart_pending) { 03228 usleep(1); 03229 } 03230 03231 ast_mutex_lock(&iflock); 03232 /* Destroy all the interfaces and free their memory */ 03233 p = iflist; 03234 while (p) { 03235 /* Free any callerid */ 03236 if (p->cidspill) 03237 ast_free(p->cidspill); 03238 pl = p; 03239 p = p->next; 03240 x = pl->channel; 03241 /* Free associated memory */ 03242 if (pl) 03243 destroy_dahdi_pvt(&pl); 03244 if (option_verbose > 2) 03245 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03246 } 03247 iflist = NULL; 03248 ifcount = 0; 03249 ast_mutex_unlock(&iflock); 03250 }
Definition at line 3172 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().
03173 { 03174 int owned = 0; 03175 int i = 0; 03176 03177 if (!now) { 03178 if (cur->owner) { 03179 owned = 1; 03180 } 03181 03182 for (i = 0; i < 3; i++) { 03183 if (cur->subs[i].owner) { 03184 owned = 1; 03185 } 03186 } 03187 if (!owned) { 03188 if (prev) { 03189 prev->next = cur->next; 03190 if (prev->next) 03191 prev->next->prev = prev; 03192 else 03193 ifend = prev; 03194 } else { 03195 iflist = cur->next; 03196 if (iflist) 03197 iflist->prev = NULL; 03198 else 03199 ifend = NULL; 03200 } 03201 destroy_dahdi_pvt(&cur); 03202 } 03203 } else { 03204 if (prev) { 03205 prev->next = cur->next; 03206 if (prev->next) 03207 prev->next->prev = prev; 03208 else 03209 ifend = prev; 03210 } else { 03211 iflist = cur->next; 03212 if (iflist) 03213 iflist->prev = NULL; 03214 else 03215 ifend = NULL; 03216 } 03217 destroy_dahdi_pvt(&cur); 03218 } 03219 return 0; 03220 }
| static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3149 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().
03150 { 03151 struct dahdi_pvt *p = *pvt; 03152 /* Remove channel from the list */ 03153 if (p->prev) 03154 p->prev->next = p->next; 03155 if (p->next) 03156 p->next->prev = p->prev; 03157 if (p->use_smdi) 03158 ast_smdi_interface_unref(p->smdi_iface); 03159 if (p->mwi_event_sub) 03160 ast_event_unsubscribe(p->mwi_event_sub); 03161 if (p->vars) { 03162 ast_variables_destroy(p->vars); 03163 } 03164 ast_mutex_destroy(&p->lock); 03165 dahdi_close_sub(p, SUB_REAL); 03166 if (p->owner) 03167 p->owner->tech_pvt = NULL; 03168 free(p); 03169 *pvt = NULL; 03170 }
| static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1746 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
| static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1576 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01577 { 01578 if (isdigit(digit)) 01579 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01580 else if (digit >= 'A' && digit <= 'D') 01581 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01582 else if (digit >= 'a' && digit <= 'd') 01583 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01584 else if (digit == '*') 01585 return DAHDI_TONE_DTMF_s; 01586 else if (digit == '#') 01587 return DAHDI_TONE_DTMF_p; 01588 else 01589 return -1; 01590 }
| static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4119 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().
04120 { 04121 int val; 04122 04123 p->ignoredtmf = 1; 04124 04125 val = 0; 04126 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04127 04128 if (!p->hardwaredtmf && p->dsp) { 04129 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 04130 ast_dsp_set_features(p->dsp, p->dsp_features); 04131 } 04132 }
| static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 10697 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().
10698 { 10699 struct ast_channel *chan = vchan; 10700 struct dahdi_pvt *pvt = chan->tech_pvt; 10701 struct ast_frame *f; 10702 char ex[80]; 10703 /* Wait up to 30 seconds for an answer */ 10704 int newms, ms = 30000; 10705 ast_verb(3, "Initiating idle call on channel %s\n", chan->name); 10706 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 10707 if (ast_call(chan, ex, 0)) { 10708 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 10709 ast_hangup(chan); 10710 return NULL; 10711 } 10712 while ((newms = ast_waitfor(chan, ms)) > 0) { 10713 f = ast_read(chan); 10714 if (!f) { 10715 /* Got hangup */ 10716 break; 10717 } 10718 if (f->frametype == AST_FRAME_CONTROL) { 10719 switch (f->subclass) { 10720 case AST_CONTROL_ANSWER: 10721 /* Launch the PBX */ 10722 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 10723 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 10724 chan->priority = 1; 10725 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 10726 ast_pbx_run(chan); 10727 /* It's already hungup, return immediately */ 10728 return NULL; 10729 case AST_CONTROL_BUSY: 10730 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name); 10731 break; 10732 case AST_CONTROL_CONGESTION: 10733 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name); 10734 break; 10735 }; 10736 } 10737 ast_frfree(f); 10738 ms = newms; 10739 } 10740 /* Hangup the channel since nothing happend */ 10741 ast_hangup(chan); 10742 return NULL; 10743 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8346 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_destroy_channel_bynum(), 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().
08347 { 08348 int count, res, res2, spoint, pollres=0; 08349 struct dahdi_pvt *i; 08350 struct dahdi_pvt *last = NULL; 08351 struct dahdi_pvt *doomed; 08352 time_t thispass = 0, lastpass = 0; 08353 int found; 08354 char buf[1024]; 08355 struct pollfd *pfds=NULL; 08356 int lastalloc = -1; 08357 /* This thread monitors all the frame relay interfaces which are not yet in use 08358 (and thus do not have a separate thread) indefinitely */ 08359 /* From here on out, we die whenever asked */ 08360 #if 0 08361 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08362 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08363 return NULL; 08364 } 08365 ast_debug(1, "Monitor starting...\n"); 08366 #endif 08367 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08368 08369 for (;;) { 08370 /* Lock the interface list */ 08371 ast_mutex_lock(&iflock); 08372 if (!pfds || (lastalloc != ifcount)) { 08373 if (pfds) { 08374 ast_free(pfds); 08375 pfds = NULL; 08376 } 08377 if (ifcount) { 08378 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08379 ast_mutex_unlock(&iflock); 08380 return NULL; 08381 } 08382 } 08383 lastalloc = ifcount; 08384 } 08385 /* Build the stuff we're going to poll on, that is the socket of every 08386 dahdi_pvt that does not have an associated owner channel */ 08387 count = 0; 08388 i = iflist; 08389 while (i) { 08390 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 08391 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) { 08392 /* This needs to be watched, as it lacks an owner */ 08393 pfds[count].fd = i->subs[SUB_REAL].dfd; 08394 pfds[count].events = POLLPRI; 08395 pfds[count].revents = 0; 08396 /* If we are monitoring for VMWI or sending CID, we need to 08397 read from the channel as well */ 08398 if (i->cidspill || i->mwimonitor_fsk) 08399 pfds[count].events |= POLLIN; 08400 count++; 08401 } 08402 } 08403 i = i->next; 08404 } 08405 /* Okay, now that we know what to do, release the interface lock */ 08406 ast_mutex_unlock(&iflock); 08407 08408 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08409 pthread_testcancel(); 08410 /* Wait at least a second for something to happen */ 08411 res = poll(pfds, count, 1000); 08412 pthread_testcancel(); 08413 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08414 08415 /* Okay, poll has finished. Let's see what happened. */ 08416 if (res < 0) { 08417 if ((errno != EAGAIN) && (errno != EINTR)) 08418 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08419 continue; 08420 } 08421 /* Alright, lock the interface list again, and let's look and see what has 08422 happened */ 08423 ast_mutex_lock(&iflock); 08424 found = 0; 08425 spoint = 0; 08426 lastpass = thispass; 08427 thispass = time(NULL); 08428 i = iflist; 08429 doomed = NULL; 08430 for (i = iflist;; i = i->next) { 08431 if (doomed) { 08432 int res; 08433 res = dahdi_destroy_channel_bynum(doomed->channel); 08434 if (!res) { 08435 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08436 } 08437 doomed = NULL; 08438 } 08439 if (!i) { 08440 break; 08441 } 08442 08443 if (thispass != lastpass) { 08444 if (!found && ((i == last) || ((i == iflist) && !last))) { 08445 last = i; 08446 if (last) { 08447 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) { 08448 res = has_voicemail(last); 08449 if (last->msgstate != res) { 08450 08451 /* This channel has a new voicemail state, 08452 * initiate a thread to send an MWI message 08453 */ 08454 pthread_attr_t attr; 08455 pthread_t threadid; 08456 struct mwi_thread_data *mtd; 08457 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 08458 if (res2) { 08459 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 08460 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 08461 } 08462 pthread_attr_init(&attr); 08463 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08464 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08465 last->msgstate = res; 08466 mtd->pvt = last; 08467 last->mwisendactive = 1; 08468 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) { 08469 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel); 08470 ast_free(mtd); 08471 last->mwisendactive = 0; 08472 } 08473 } 08474 found ++; 08475 } 08476 } 08477 last = last->next; 08478 } 08479 } 08480 } 08481 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08482 if (i->radio && !i->owner) 08483 { 08484 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08485 if (res) 08486 { 08487 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08488 /* Don't hold iflock while handling init events */ 08489 ast_mutex_unlock(&iflock); 08490 doomed = handle_init_event(i, res); 08491 ast_mutex_lock(&iflock); 08492 } 08493 continue; 08494 } 08495 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08496 if (pollres & POLLIN) { 08497 if (i->owner || i->subs[SUB_REAL].owner) { 08498 #ifdef HAVE_PRI 08499 if (!i->pri) 08500 #endif 08501 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08502 continue; 08503 } 08504 if (!i->cidspill && !i->mwimonitor_fsk) { 08505 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08506 continue; 08507 } 08508 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08509 if (res > 0) { 08510 if (i->mwimonitor_fsk) { 08511 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 08512 pthread_attr_t attr; 08513 pthread_t threadid; 08514 struct mwi_thread_data *mtd; 08515 08516 pthread_attr_init(&attr); 08517 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08518 08519 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 08520 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08521 mtd->pvt = i; 08522 memcpy(mtd->buf, buf, res); 08523 mtd->len = res; 08524 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 08525 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 08526 ast_free(mtd); 08527 } 08528 i->mwimonitoractive = 1; 08529 } 08530 } 08531 } 08532 } else { 08533 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08534 } 08535 } 08536 if (pollres & POLLPRI) { 08537 if (i->owner || i->subs[SUB_REAL].owner) { 08538 #ifdef HAVE_PRI 08539 if (!i->pri) 08540 #endif 08541 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08542 continue; 08543 } 08544 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08545 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08546 /* Don't hold iflock while handling init events */ 08547 ast_mutex_unlock(&iflock); 08548 doomed = handle_init_event(i, res); 08549 ast_mutex_lock(&iflock); 08550 } 08551 } 08552 } 08553 ast_mutex_unlock(&iflock); 08554 } 08555 /* Never reached */ 08556 return NULL; 08557 08558 }
| static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4134 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().
04135 { 04136 int val; 04137 04138 if (p->channel == CHAN_PSEUDO) 04139 return; 04140 04141 p->ignoredtmf = 0; 04142 04143 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04144 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04145 04146 if (!p->hardwaredtmf && p->dsp) { 04147 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 04148 ast_dsp_set_features(p->dsp, p->dsp_features); 04149 } 04150 }
| static char* event2str | ( | int | event | ) | [static] |
Definition at line 1736 of file chan_dahdi.c.
References ARRAY_LEN, and buf.
Referenced by __dahdi_exception(), dahdi_handle_event(), 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 2106 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02107 { 02108 int j; 02109 int k; 02110 float linear_gain = pow(10.0, gain / 20.0); 02111 02112 switch (law) { 02113 case DAHDI_LAW_ALAW: 02114 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02115 if (gain) { 02116 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02117 if (k > 32767) k = 32767; 02118 if (k < -32767) k = -32767; 02119 g->rxgain[j] = AST_LIN2A(k); 02120 } else { 02121 g->rxgain[j] = j; 02122 } 02123 } 02124 break; 02125 case DAHDI_LAW_MULAW: 02126 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02127 if (gain) { 02128 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02129 if (k > 32767) k = 32767; 02130 if (k < -32767) k = -32767; 02131 g->rxgain[j] = AST_LIN2MU(k); 02132 } else { 02133 g->rxgain[j] = j; 02134 } 02135 } 02136 break; 02137 } 02138 }
| static void fill_txgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2072 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02073 { 02074 int j; 02075 int k; 02076 float linear_gain = pow(10.0, gain / 20.0); 02077 02078 switch (law) { 02079 case DAHDI_LAW_ALAW: 02080 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02081 if (gain) { 02082 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02083 if (k > 32767) k = 32767; 02084 if (k < -32767) k = -32767; 02085 g->txgain[j] = AST_LIN2A(k); 02086 } else { 02087 g->txgain[j] = j; 02088 } 02089 } 02090 break; 02091 case DAHDI_LAW_MULAW: 02092 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02093 if (gain) { 02094 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02095 if (k > 32767) k = 32767; 02096 if (k < -32767) k = -32767; 02097 g->txgain[j] = AST_LIN2MU(k); 02098 } else { 02099 g->txgain[j] = j; 02100 } 02101 } 02102 break; 02103 } 02104 }
| static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 13400 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 4578 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().
04579 { 04580 int res; 04581 struct dahdi_spaninfo zi; 04582 struct dahdi_params params; 04583 04584 memset(&zi, 0, sizeof(zi)); 04585 zi.spanno = p->span; 04586 04587 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 04588 if (zi.alarms != DAHDI_ALARM_NONE) 04589 return zi.alarms; 04590 } else { 04591 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04592 return 0; 04593 } 04594 04595 /* No alarms on the span. Check for channel alarms. */ 04596 memset(¶ms, 0, sizeof(params)); 04597 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04598 return params.chan_alarms; 04599 04600 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04601 04602 return DAHDI_ALARM_NONE; 04603 }
| static void handle_alarms | ( | struct dahdi_pvt * | p, | |
| int | alms | |||
| ) | [static] |
Definition at line 4671 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().
04672 { 04673 const char *alarm_str = alarm2str(alms); 04674 04675 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04676 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04677 "Alarm: %s\r\n" 04678 "Channel: %d\r\n", 04679 alarm_str, p->channel); 04680 }
| static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13016 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.
13017 { 13018 int i, j; 13019 switch (cmd) { 13020 case CLI_INIT: 13021 e->command = "dahdi show cadences"; 13022 e->usage = 13023 "Usage: dahdi show cadences\n" 13024 " Shows all cadences currently defined\n"; 13025 return NULL; 13026 case CLI_GENERATE: 13027 return NULL; 13028 } 13029 for (i = 0; i < num_cadence; i++) { 13030 char output[1024]; 13031 char tmp[16], tmp2[64]; 13032 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 13033 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 13034 13035 for (j = 0; j < 16; j++) { 13036 if (cadences[i].ringcadence[j] == 0) 13037 break; 13038 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 13039 if (cidrings[i] * 2 - 1 == j) 13040 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 13041 else 13042 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 13043 if (j != 0) 13044 strncat(output, ",", sizeof(output) - strlen(output) - 1); 13045 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 13046 } 13047 ast_cli(a->fd,"%s\n",output); 13048 } 13049 return CLI_SUCCESS; 13050 }
Definition at line 8123 of file chan_dahdi.c.
References ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, chan, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), 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().
08124 { 08125 int res; 08126 pthread_t threadid; 08127 struct ast_channel *chan; 08128 08129 /* Handle an event on a given channel for the monitor thread. */ 08130 08131 switch (event) { 08132 case DAHDI_EVENT_NONE: 08133 case DAHDI_EVENT_BITSCHANGED: 08134 break; 08135 case DAHDI_EVENT_WINKFLASH: 08136 case DAHDI_EVENT_RINGOFFHOOK: 08137 if (i->inalarm) break; 08138 if (i->radio) break; 08139 /* Got a ring/answer. What kind of channel are we? */ 08140 switch (i->sig) { 08141 case SIG_FXOLS: 08142 case SIG_FXOGS: 08143 case SIG_FXOKS: 08144 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08145 if (res && (errno == EBUSY)) 08146 break; 08147 if (i->cidspill) { 08148 /* Cancel VMWI spill */ 08149 ast_free(i->cidspill); 08150 i->cidspill = NULL; 08151 } 08152 if (i->immediate) { 08153 dahdi_enable_ec(i); 08154 /* The channel is immediately up. Start right away */ 08155 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08156 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 08157 if (!chan) { 08158 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 08159 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08160 if (res < 0) 08161 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08162 } 08163 } else { 08164 /* Check for callerid, digits, etc */ 08165 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 08166 if (chan) { 08167 if (has_voicemail(i)) 08168 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08169 else 08170 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08171 if (res < 0) 08172 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08173 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08174 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08175 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08176 if (res < 0) 08177 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08178 ast_hangup(chan); 08179 } 08180 } else 08181 ast_log(LOG_WARNING, "Unable to create channel\n"); 08182 } 08183 break; 08184 case SIG_FXSLS: 08185 case SIG_FXSGS: 08186 case SIG_FXSKS: 08187 i->ringt = i->ringt_base; 08188 /* Fall through */ 08189 case SIG_EMWINK: 08190 case SIG_FEATD: 08191 case SIG_FEATDMF: 08192 case SIG_FEATDMF_TA: 08193 case SIG_E911: 08194 case SIG_FGC_CAMA: 08195 case SIG_FGC_CAMAMF: 08196 case SIG_FEATB: 08197 case SIG_EM: 08198 case SIG_EM_E1: 08199 case SIG_SFWINK: 08200 case SIG_SF_FEATD: 08201 case SIG_SF_FEATDMF: 08202 case SIG_SF_FEATB: 08203 case SIG_SF: 08204 /* Check for callerid, digits, etc */ 08205 if (i->cid_start == CID_START_POLARITY_IN) { 08206 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08207 } else { 08208 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08209 } 08210 08211 if (!chan) { 08212 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08213 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08214 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08215 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08216 if (res < 0) { 08217 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08218 } 08219 ast_hangup(chan); 08220 } 08221 break; 08222 default: 08223 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08224 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08225 if (res < 0) 08226 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08227 return NULL; 08228 } 08229 break; 08230 case DAHDI_EVENT_NOALARM: 08231 i->inalarm = 0; 08232 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08233 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08234 "Channel: %d\r\n", i->channel); 08235 break; 08236 case DAHDI_EVENT_ALARM: 08237 i->inalarm = 1; 08238 res = get_alarms(i); 08239 handle_alarms(i, res); 08240 /* fall thru intentionally */ 08241 case DAHDI_EVENT_ONHOOK: 08242 if (i->radio) 08243 break; 08244 /* Back on hook. Hang up. */ 08245 switch (i->sig) { 08246 case SIG_FXOLS: 08247 case SIG_FXOGS: 08248 case SIG_FEATD: 08249 case SIG_FEATDMF: 08250 case SIG_FEATDMF_TA: 08251 case SIG_E911: 08252 case SIG_FGC_CAMA: 08253 case SIG_FGC_CAMAMF: 08254 case SIG_FEATB: 08255 case SIG_EM: 08256 case SIG_EM_E1: 08257 case SIG_EMWINK: 08258 case SIG_SF_FEATD: 08259 case SIG_SF_FEATDMF: 08260 case SIG_SF_FEATB: 08261 case SIG_SF: 08262 case SIG_SFWINK: 08263 case SIG_FXSLS: 08264 case SIG_FXSGS: 08265 case SIG_FXSKS: 08266 case SIG_GR303FXSKS: 08267 dahdi_disable_ec(i); 08268 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08269 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08270 break; 08271 case SIG_GR303FXOKS: 08272 case SIG_FXOKS: 08273 dahdi_disable_ec(i); 08274 /* Diddle the battery for the zhone */ 08275 #ifdef ZHONE_HACK 08276 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08277 usleep(1); 08278 #endif 08279 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08280 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08281 break; 08282 case SIG_PRI: 08283 case SIG_SS7: 08284 case SIG_BRI: 08285 case SIG_BRI_PTMP: 08286 dahdi_disable_ec(i); 08287 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08288 break; 08289 default: 08290 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08291 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08292 return NULL; 08293 } 08294 break; 08295 case DAHDI_EVENT_POLARITY: 08296 switch (i->sig) { 08297 case SIG_FXSLS: 08298 case SIG_FXSKS: 08299 case SIG_FXSGS: 08300 /* We have already got a PR before the channel was 08301 created, but it wasn't handled. We need polarity 08302 to be REV for remote hangup detection to work. 08303 At least in Spain */ 08304 if (i->hanguponpolarityswitch) 08305 i->polarity = POLARITY_REV; 08306 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 08307 i->polarity = POLARITY_REV; 08308 ast_verb(2, "Starting post polarity " 08309 "CID detection on channel %d\n", 08310 i->channel); 08311 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08312 if (!chan) { 08313 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08314 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08315 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08316 } 08317 } 08318 break; 08319 default: 08320 ast_log(LOG_WARNING, "handle_init_event detected " 08321 "polarity reversal on non-FXO (SIG_FXS) " 08322 "interface %d\n", i->channel); 08323 } 08324 break; 08325 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08326 ast_log(LOG_NOTICE, 08327 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08328 i->channel); 08329 return i; 08330 case DAHDI_EVENT_NEONMWI_ACTIVE: 08331 if (i->mwimonitor_neon) { 08332 notify_message(i->mailbox, 1); 08333 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 08334 } 08335 break; 08336 case DAHDI_EVENT_NEONMWI_INACTIVE: 08337 if (i->mwimonitor_neon) { 08338 notify_message(i->mailbox, 0); 08339 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 08340 } 08341 break; 08342 } 08343 return NULL; 08344 }
| static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12228 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.
12229 { 12230 int span; 12231 int x; 12232 switch (cmd) { 12233 case CLI_INIT: 12234 e->command = "pri debug span"; 12235 e->usage = 12236 "Usage: pri debug span <span>\n" 12237 " Enables debugging on a given PRI span\n"; 12238 return NULL; 12239 case CLI_GENERATE: 12240 return complete_span_4(a->line, a->word, a->pos, a->n); 12241 } 12242 if (a->argc < 4) { 12243 return CLI_SHOWUSAGE; 12244 } 12245 span = atoi(a->argv[3]); 12246 if ((span < 1) || (span > NUM_SPANS)) { 12247 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 12248 return CLI_SUCCESS; 12249 } 12250 if (!pris[span-1].pri) { 12251 ast_cli(a->fd, "No PRI running on span %d\n", span); 12252 return CLI_SUCCESS; 12253 } 12254 for (x = 0; x < NUM_DCHANS; x++) { 12255 if (pris[span-1].dchans[x]) 12256 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12257 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12258 PRI_DEBUG_Q921_STATE); 12259 } 12260 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 12261 return CLI_SUCCESS; 12262 }
| static char* handle_pri_no_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12266 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.
12267 { 12268 int span; 12269 int x; 12270 switch (cmd) { 12271 case CLI_INIT: 12272 e->command = "pri no debug span"; 12273 e->usage = 12274 "Usage: pri no debug span <span>\n" 12275 " Disables debugging on a given PRI span\n"; 12276 return NULL; 12277 case CLI_GENERATE: 12278 return complete_span_5(a->line, a->word, a->pos, a->n); 12279 } 12280 if (a->argc < 5) 12281 return CLI_SHOWUSAGE; 12282 12283 span = atoi(a->argv[4]); 12284 if ((span < 1) || (span > NUM_SPANS)) { 12285 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12286 return CLI_SUCCESS; 12287 } 12288 if (!pris[span-1].pri) { 12289 ast_cli(a->fd, "No PRI running on span %d\n", span); 12290 return CLI_SUCCESS; 12291 } 12292 for (x = 0; x < NUM_DCHANS; x++) { 12293 if (pris[span-1].dchans[x]) 12294 pri_set_debug(pris[span-1].dchans[x], 0); 12295 } 12296 ast_cli(a->fd, "Disabled debugging on span %d\n", span); 12297 return CLI_SUCCESS; 12298 }
| static char* handle_pri_really_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12300 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.
12301 { 12302 int span; 12303 int x; 12304 switch (cmd) { 12305 case CLI_INIT: 12306 e->command = "pri intensive debug span"; 12307 e->usage = 12308 "Usage: pri intensive debug span <span>\n" 12309 " Enables debugging down to the Q.921 level\n"; 12310 return NULL; 12311 case CLI_GENERATE: 12312 return complete_span_5(a->line, a->word, a->pos, a->n); 12313 } 12314 12315 if (a->argc < 5) 12316 return CLI_SHOWUSAGE; 12317 span = atoi(a->argv[4]); 12318 if ((span < 1) || (span > NUM_SPANS)) { 12319 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12320 return CLI_SUCCESS; 12321 } 12322 if (!pris[span-1].pri) { 12323 ast_cli(a->fd, "No PRI running on span %d\n", span); 12324 return CLI_SUCCESS; 12325 } 12326 for (x = 0; x < NUM_DCHANS; x++) { 12327 if (pris[span-1].dchans[x]) 12328 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12329 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12330 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 12331 } 12332 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span); 12333 return CLI_SUCCESS; 12334 }
| static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12192 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.
12193 { 12194 int myfd; 12195 switch (cmd) { 12196 case CLI_INIT: 12197 e->command = "pri set debug file"; 12198 e->usage = "Usage: pri set debug file [output-file]\n" 12199 " Sends PRI debug output to the specified output file\n"; 12200 return NULL; 12201 case CLI_GENERATE: 12202 return NULL; 12203 } 12204 if (a->argc < 5) 12205 return CLI_SHOWUSAGE; 12206 12207 if (ast_strlen_zero(a->argv[4])) 12208 return CLI_SHOWUSAGE; 12209 12210 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 12211 if (myfd < 0) { 12212 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 12213 return CLI_SUCCESS; 12214 } 12215 12216 ast_mutex_lock(&pridebugfdlock); 12217 12218 if (pridebugfd >= 0) 12219 close(pridebugfd); 12220 12221 pridebugfd = myfd; 12222 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 12223 ast_mutex_unlock(&pridebugfdlock); 12224 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 12225 return CLI_SUCCESS; 12226 }
| static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12440 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.
12441 { 12442 int x; 12443 int span; 12444 int count=0; 12445 int debug=0; 12446 12447 switch (cmd) { 12448 case CLI_INIT: 12449 e->command = "pri show debug"; 12450 e->usage = 12451 "Usage: pri show debug\n" 12452 " Show the debug state of pri spans\n"; 12453 return NULL; 12454 case CLI_GENERATE: 12455 return NULL; 12456 } 12457 12458 for (span = 0; span < NUM_SPANS; span++) { 12459 if (pris[span].pri) { 12460 for (x = 0; x < NUM_DCHANS; x++) { 12461 debug = 0; 12462 if (pris[span].dchans[x]) { 12463 debug = pri_get_debug(pris[span].dchans[x]); 12464 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" ); 12465 count++; 12466 } 12467 } 12468 } 12469 12470 } 12471 ast_mutex_lock(&pridebugfdlock); 12472 if (pridebugfd >= 0) 12473 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 12474 ast_mutex_unlock(&pridebugfdlock); 12475 12476 if (!count) 12477 ast_cli(a->fd, "No debug set or no PRI running\n"); 12478 return CLI_SUCCESS; 12479 }
| static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12390 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.
12391 { 12392 int span; 12393 int x; 12394 char status[256]; 12395 switch (cmd) { 12396 case CLI_INIT: 12397 e->command = "pri show span"; 12398 e->usage = 12399 "Usage: pri show span <span>\n" 12400 " Displays PRI Information on a given PRI span\n"; 12401 return NULL; 12402 case CLI_GENERATE: 12403 return complete_span_4(a->line, a->word, a->pos, a->n); 12404 } 12405 12406 if (a->argc < 4) 12407 return CLI_SHOWUSAGE; 12408 span = atoi(a->argv[3]); 12409 if ((span < 1) || (span > NUM_SPANS)) { 12410 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 12411 return CLI_SUCCESS; 12412 } 12413 if (!pris[span-1].pri) { 12414 ast_cli(a->fd, "No PRI running on span %d\n", span); 12415 return CLI_SUCCESS; 12416 } 12417 for (x = 0; x < NUM_DCHANS; x++) { 12418 if (pris[span-1].dchannels[x]) { 12419 #ifdef PRI_DUMP_INFO_STR 12420 char *info_str = NULL; 12421 #endif 12422 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 12423 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 12424 ast_cli(a->fd, "Status: %s\n", status); 12425 #ifdef PRI_DUMP_INFO_STR 12426 info_str = pri_dump_info_str(pris[span-1].pri); 12427 if (info_str) { 12428 ast_cli(a->fd, "%s", info_str); 12429 ast_free(info_str); 12430 } 12431 #else 12432 pri_dump_info(pris[span-1].pri); 12433 #endif 12434 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 12435 } 12436 } 12437 return CLI_SUCCESS; 12438 }
| static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12357 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.
12358 { 12359 int span; 12360 int x; 12361 char status[256]; 12362 12363 switch (cmd) { 12364 case CLI_INIT: 12365 e->command = "pri show spans"; 12366 e->usage = 12367 "Usage: pri show spans\n" 12368 " Displays PRI Information\n"; 12369 return NULL; 12370 case CLI_GENERATE: 12371 return NULL; 12372 } 12373 12374 if (a->argc != 3) 12375 return CLI_SHOWUSAGE; 12376 12377 for (span = 0; span < NUM_SPANS; span++) { 12378 if (pris[span].pri) { 12379 for (x = 0; x < NUM_DCHANS; x++) { 12380 if (pris[span].dchannels[x]) { 12381 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 12382 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status); 12383 } 12384 } 12385 } 12386 } 12387 return CLI_SUCCESS; 12388 }
| static char* handle_pri_unset_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12171 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.
12172 { 12173 switch (cmd) { 12174 case CLI_INIT: 12175 e->command = "pri unset debug file"; 12176 e->usage = "Usage: pri unset debug file\n" 12177 " Stop sending debug output to the previously \n" 12178 " specified file\n"; 12179 return NULL; 12180 case CLI_GENERATE: 12181 return NULL; 12182 } 12183 /* Assume it is unset */ 12184 ast_mutex_lock(&pridebugfdlock); 12185 close(pridebugfd); 12186 pridebugfd = -1; 12187 ast_cli(a->fd, "PRI debug output to file disabled\n"); 12188 ast_mutex_unlock(&pridebugfdlock); 12189 return CLI_SUCCESS; 12190 }
| static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12481 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.
12482 { 12483 switch (cmd) { 12484 case CLI_INIT: 12485 e->command = "pri show version"; 12486 e->usage = 12487 "Usage: pri show version\n" 12488 "Show libpri version information\n"; 12489 return NULL; 12490 case CLI_GENERATE: 12491 return NULL; 12492 } 12493 12494 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 12495 12496 return CLI_SUCCESS; 12497 }
| static char* handle_ss7_block_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13789 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.
13790 { 13791 int linkset, cic; 13792 int blocked = -1, i; 13793 switch (cmd) { 13794 case CLI_INIT: 13795 e->command = "ss7 block cic"; 13796 e->usage = 13797 "Usage: ss7 block cic <linkset> <CIC>\n" 13798 " Sends a remote blocking request for the given CIC on the specified linkset\n"; 13799 return NULL; 13800 case CLI_GENERATE: 13801 return NULL; 13802 } 13803 if (a->argc == 5) 13804 linkset = atoi(a->argv[3]); 13805 else 13806 return CLI_SHOWUSAGE; 13807 13808 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13809 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13810 return CLI_SUCCESS; 13811 } 13812 13813 if (!linksets[linkset-1].ss7) { 13814 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13815 return CLI_SUCCESS; 13816 } 13817 13818 cic = atoi(a->argv[4]); 13819 13820 if (cic < 1) { 13821 ast_cli(a->fd, "Invalid CIC specified!\n"); 13822 return CLI_SUCCESS; 13823 } 13824 13825 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13826 if (linksets[linkset-1].pvts[i]->cic == cic) { 13827 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 13828 if (!blocked) { 13829 ast_mutex_lock(&linksets[linkset-1].lock); 13830 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 13831 ast_mutex_unlock(&linksets[linkset-1].lock); 13832 } 13833 } 13834 } 13835 13836 if (blocked < 0) { 13837 ast_cli(a->fd, "Invalid CIC specified!\n"); 13838 return CLI_SUCCESS; 13839 } 13840 13841 if (!blocked) 13842 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic); 13843 else 13844 ast_cli(a->fd, "CIC %d already locally blocked\n", cic); 13845 13846 /* Break poll on the linkset so it sends our messages */ 13847 pthread_kill(linksets[linkset-1].master, SIGURG); 13848 13849 return CLI_SUCCESS; 13850 }
| static char* handle_ss7_block_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13852 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.
13853 { 13854 int linkset; 13855 int i; 13856 switch (cmd) { 13857 case CLI_INIT: 13858 e->command = "ss7 block linkset"; 13859 e->usage = 13860 "Usage: ss7 block linkset <linkset number>\n" 13861 " Sends a remote blocking request for all CICs on the given linkset\n"; 13862 return NULL; 13863 case CLI_GENERATE: 13864 return NULL; 13865 } 13866 if (a->argc == 4) 13867 linkset = atoi(a->argv[3]); 13868 else 13869 return CLI_SHOWUSAGE; 13870 13871 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13872 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13873 return CLI_SUCCESS; 13874 } 13875 13876 if (!linksets[linkset-1].ss7) { 13877 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13878 return CLI_SUCCESS; 13879 } 13880 13881 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13882 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 13883 ast_mutex_lock(&linksets[linkset-1].lock); 13884 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 13885 ast_mutex_unlock(&linksets[linkset-1].lock); 13886 } 13887 13888 /* Break poll on the linkset so it sends our messages */ 13889 pthread_kill(linksets[linkset-1].master, SIGURG); 13890 13891 return CLI_SUCCESS; 13892 }
| static char* handle_ss7_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13758 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.
13759 { 13760 int span; 13761 switch (cmd) { 13762 case CLI_INIT: 13763 e->command = "ss7 debug linkset"; 13764 e->usage = 13765 "Usage: ss7 debug linkset <linkset>\n" 13766 " Enables debugging on a given SS7 linkset\n"; 13767 return NULL; 13768 case CLI_GENERATE: 13769 return NULL; 13770 } 13771 if (a->argc < 4) 13772 return CLI_SHOWUSAGE; 13773 span = atoi(a->argv[3]); 13774 if ((span < 1) || (span > NUM_SPANS)) { 13775 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 13776 return CLI_SUCCESS; 13777 } 13778 if (!linksets[span-1].ss7) { 13779 ast_cli(a->fd, "No SS7 running on linkset %d\n", span); 13780 return CLI_SUCCESS; 13781 } 13782 if (linksets[span-1].ss7) 13783 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP); 13784 13785 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span); 13786 return CLI_SUCCESS; 13787 }
| static char* handle_ss7_no_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13727 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.
13728 { 13729 int span; 13730 switch (cmd) { 13731 case CLI_INIT: 13732 e->command = "ss7 no debug linkset"; 13733 e->usage = 13734 "Usage: ss7 no debug linkset <span>\n" 13735 " Disables debugging on a given SS7 linkset\n"; 13736 return NULL; 13737 case CLI_GENERATE: 13738 return NULL; 13739 } 13740 if (a->argc < 5) 13741 return CLI_SHOWUSAGE; 13742 span = atoi(a->argv[4]); 13743 if ((span < 1) || (span > NUM_SPANS)) { 13744 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS); 13745 return CLI_SUCCESS; 13746 } 13747 if (!linksets[span-1].ss7) { 13748 ast_cli(a->fd, "No SS7 running on linkset %d\n", span); 13749 return CLI_SUCCESS; 13750 } 13751 if (linksets[span-1].ss7) 13752 ss7_set_debug(linksets[span-1].ss7, 0); 13753 13754 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span); 13755 return CLI_SUCCESS; 13756 }
| static char* handle_ss7_show_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13994 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.
13995 { 13996 int linkset; 13997 struct dahdi_ss7 *ss7; 13998 switch (cmd) { 13999 case CLI_INIT: 14000 e->command = "ss7 show linkset"; 14001 e->usage = 14002 "Usage: ss7 show linkset <span>\n" 14003 " Shows the status of an SS7 linkset.\n"; 14004 return NULL; 14005 case CLI_GENERATE: 14006 return NULL; 14007 } 14008 14009 if (a->argc < 4) 14010 return CLI_SHOWUSAGE; 14011 linkset = atoi(a->argv[3]); 14012 if ((linkset < 1) || (linkset > NUM_SPANS)) { 14013 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 14014 return CLI_SUCCESS; 14015 } 14016 if (!linksets[linkset-1].ss7) { 14017 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 14018 return CLI_SUCCESS; 14019 } 14020 if (linksets[linkset-1].ss7) 14021 ss7 = &linksets[linkset-1]; 14022 14023 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down"); 14024 14025 return CLI_SUCCESS; 14026 }
| static char* handle_ss7_unblock_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13894 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.
13895 { 13896 int linkset, cic; 13897 int i, blocked = -1; 13898 switch (cmd) { 13899 case CLI_INIT: 13900 e->command = "ss7 unblock cic"; 13901 e->usage = 13902 "Usage: ss7 unblock cic <linkset> <CIC>\n" 13903 " Sends a remote unblocking request for the given CIC on the specified linkset\n"; 13904 return NULL; 13905 case CLI_GENERATE: 13906 return NULL; 13907 } 13908 13909 if (a->argc == 5) 13910 linkset = atoi(a->argv[3]); 13911 else 13912 return CLI_SHOWUSAGE; 13913 13914 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13915 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13916 return CLI_SUCCESS; 13917 } 13918 13919 if (!linksets[linkset-1].ss7) { 13920 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13921 return CLI_SUCCESS; 13922 } 13923 13924 cic = atoi(a->argv[4]); 13925 13926 if (cic < 1) { 13927 ast_cli(a->fd, "Invalid CIC specified!\n"); 13928 return CLI_SUCCESS; 13929 } 13930 13931 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13932 if (linksets[linkset-1].pvts[i]->cic == cic) { 13933 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 13934 if (blocked) { 13935 ast_mutex_lock(&linksets[linkset-1].lock); 13936 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 13937 ast_mutex_unlock(&linksets[linkset-1].lock); 13938 } 13939 } 13940 } 13941 13942 if (blocked > 0) 13943 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic); 13944 13945 /* Break poll on the linkset so it sends our messages */ 13946 pthread_kill(linksets[linkset-1].master, SIGURG); 13947 13948 return CLI_SUCCESS; 13949 }
| static char* handle_ss7_unblock_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13951 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.
13952 { 13953 int linkset; 13954 int i; 13955 switch (cmd) { 13956 case CLI_INIT: 13957 e->command = "ss7 unblock linkset"; 13958 e->usage = 13959 "Usage: ss7 unblock linkset <linkset number>\n" 13960 " Sends a remote unblocking request for all CICs on the specified linkset\n"; 13961 return NULL; 13962 case CLI_GENERATE: 13963 return NULL; 13964 } 13965 13966 if (a->argc == 4) 13967 linkset = atoi(a->argv[3]); 13968 else 13969 return CLI_SHOWUSAGE; 13970 13971 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13972 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13973 return CLI_SUCCESS; 13974 } 13975 13976 if (!linksets[linkset-1].ss7) { 13977 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13978 return CLI_SUCCESS; 13979 } 13980 13981 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13982 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 13983 ast_mutex_lock(&linksets[linkset-1].lock); 13984 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 13985 ast_mutex_unlock(&linksets[linkset-1].lock); 13986 } 13987 13988 /* Break poll on the linkset so it sends our messages */ 13989 pthread_kill(linksets[linkset-1].master, SIGURG); 13990 13991 return CLI_SUCCESS; 13992 }
| static char* handle_ss7_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14028 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.
14029 { 14030 switch (cmd) { 14031 case CLI_INIT: 14032 e->command = "ss7 show version"; 14033 e->usage = 14034 "Usage: ss7 show version\n" 14035 " Show the libss7 version\n"; 14036 return NULL; 14037 case CLI_GENERATE: 14038 return NULL; 14039 } 14040 14041 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version()); 14042 14043 return CLI_SUCCESS; 14044 }
| static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2346 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().
02347 { 02348 int new_msgs; 02349 struct ast_event *event; 02350 char *mailbox, *context; 02351 02352 mailbox = context = ast_strdupa(p->mailbox); 02353 strsep(&context, "@"); 02354 if (ast_strlen_zero(context)) 02355 context = "default"; 02356 02357 event = ast_event_get_cached(AST_EVENT_MWI, 02358 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02359 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02360 AST_EVENT_IE_END); 02361 02362 if (event) { 02363 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 02364 ast_event_destroy(event); 02365 } else 02366 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 02367 02368 return new_msgs; 02369 }
| static int isourconf | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c | |||
| ) | [static] |
Definition at line 1861 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01862 { 01863 /* If they're listening to our channel, they're ours */ 01864 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01865 return 1; 01866 /* If they're a talker on our (allocated) conference, they're ours */ 01867 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01868 return 1; 01869 return 0; 01870 }
Definition at line 1891 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_pvt::law, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by update_conf().
01892 { 01893 int x; 01894 int useslavenative; 01895 struct dahdi_pvt *slave = NULL; 01896 /* Start out optimistic */ 01897 useslavenative = 1; 01898 /* Update conference state in a stateless fashion */ 01899 for (x = 0; x < 3; x++) { 01900 /* Any three-way calling makes slave native mode *definitely* out 01901 of the question */ 01902 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01903 useslavenative = 0; 01904 } 01905 /* If we don't have any 3-way calls, check to see if we have 01906 precisely one slave */ 01907 if (useslavenative) { 01908 for (x = 0; x < MAX_SLAVES; x++) { 01909 if (p->slaves[x]) { 01910 if (slave) { 01911 /* Whoops already have a slave! No 01912 slave native and stop right away */ 01913 slave = NULL; 01914 useslavenative = 0; 01915 break; 01916 } else { 01917 /* We have one slave so far */ 01918 slave = p->slaves[x]; 01919 } 01920 } 01921 } 01922 } 01923 /* If no slave, slave native definitely out */ 01924 if (!slave) 01925 useslavenative = 0; 01926 else if (slave->law != p->law) { 01927 useslavenative = 0; 01928 slave = NULL; 01929 } 01930 if (out) 01931 *out = slave; 01932 return useslavenative; 01933 }
| static int linkset_addsigchan | ( | int | sigchan | ) | [static] |
Definition at line 13606 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().
13607 { 13608 struct dahdi_ss7 *link; 13609 int res; 13610 int curfd; 13611 struct dahdi_params p; 13612 struct dahdi_bufferinfo bi; 13613 struct dahdi_spaninfo si; 13614 13615 13616 link = ss7_resolve_linkset(cur_linkset); 13617 if (!link) { 13618 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 13619 return -1; 13620 } 13621 13622 if (cur_ss7type < 0) { 13623 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n"); 13624 return -1; 13625 } 13626 13627 if (!link->ss7) 13628 link->ss7 = ss7_new(cur_ss7type); 13629 13630 if (!link->ss7) { 13631 ast_log(LOG_ERROR, "Can't create new SS7!\n"); 13632 return -1; 13633 } 13634 13635 link->type = cur_ss7type; 13636 13637 if (cur_pointcode < 0) { 13638 ast_log(LOG_ERROR, "Unspecified pointcode!\n"); 13639 return -1; 13640 } else 13641 ss7_set_pc(link->ss7, cur_pointcode); 13642 13643 if (sigchan < 0) { 13644 ast_log(LOG_ERROR, "Invalid sigchan!\n"); 13645 return -1; 13646 } else { 13647 if (link->numsigchans >= NUM_DCHANS) { 13648 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset); 13649 return -1; 13650 } 13651 curfd = link->numsigchans; 13652 13653 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600); 13654 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) { 13655 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno)); 13656 return -1; 13657 } 13658 memset(&p, 0, sizeof(p)); 13659 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p); 13660 if (res) { 13661 dahdi_close_ss7_fd(link, curfd); 13662 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno)); 13663 return -1; 13664 } 13665 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) { 13666 dahdi_close_ss7_fd(link, curfd); 13667 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan); 13668 return -1; 13669 } 13670 13671 memset(&bi, 0, sizeof(bi)); 13672 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 13673 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 13674 bi.numbufs = 32; 13675 bi.bufsize = 512; 13676 13677 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) { 13678 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno)); 13679 dahdi_close_ss7_fd(link, curfd); 13680 return -1; 13681 } 13682 13683 if (p.sigtype == DAHDI_SIG_MTP2) 13684 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]); 13685 else 13686 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]); 13687 13688 link->numsigchans++; 13689 13690 memset(&si, 0, sizeof(si)); 13691 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si); 13692 if (res) { 13693 dahdi_close_ss7_fd(link, curfd); 13694 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno)); 13695 } 13696 13697 if (!si.alarms) { 13698 link->linkstate[curfd] = LINKSTATE_DOWN; 13699 ss7_link_noalarm(link->ss7, link->fds[curfd]); 13700 } else { 13701 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM; 13702 ss7_link_alarm(link->ss7, link->fds[curfd]); 13703 } 13704 } 13705 13706 if (cur_adjpointcode < 0) { 13707 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n"); 13708 return -1; 13709 } else { 13710 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode); 13711 } 13712 13713 if (cur_defaultdpc < 0) { 13714 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n"); 13715 return -1; 13716 } 13717 13718 if (cur_networkindicator < 0) { 13719 ast_log(LOG_ERROR, "Invalid networkindicator!\n"); 13720 return -1; 13721 } else 13722 ss7_set_network_ind(link->ss7, cur_networkindicator); 13723 13724 return 0; 13725 }
| static int load_module | ( | void | ) | [static] |
Definition at line 15346 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().
15347 { 15348 int res; 15349 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15350 int y, i; 15351 #endif 15352 15353 #ifdef HAVE_PRI 15354 memset(pris, 0, sizeof(pris)); 15355 for (y = 0; y < NUM_SPANS; y++) { 15356 ast_mutex_init(&pris[y].lock); 15357 pris[y].offset = -1; 15358 pris[y].master = AST_PTHREADT_NULL; 15359 for (i = 0; i < NUM_DCHANS; i++) 15360 pris[y].fds[i] = -1; 15361 } 15362 pri_set_error(dahdi_pri_error); 15363 pri_set_message(dahdi_pri_message); 15364 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 15365 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 15366 #endif 15367 #ifdef HAVE_SS7 15368 memset(linksets, 0, sizeof(linksets)); 15369 for (y = 0; y < NUM_SPANS; y++) { 15370 ast_mutex_init(&linksets[y].lock); 15371 linksets[y].master = AST_PTHREADT_NULL; 15372 for (i = 0; i < NUM_DCHANS; i++) 15373 linksets[y].fds[i] = -1; 15374 } 15375 ss7_set_error(dahdi_ss7_error); 15376 ss7_set_message(dahdi_ss7_message); 15377 #endif /* HAVE_SS7 */ 15378 res = setup_dahdi(0); 15379 /* Make sure we can register our DAHDI channel type */ 15380 if (res) 15381 return AST_MODULE_LOAD_DECLINE; 15382 if (ast_channel_register(&dahdi_tech)) { 15383 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 15384 __unload_module(); 15385 return AST_MODULE_LOAD_FAILURE; 15386 } 15387 #ifdef HAVE_PRI 15388 ast_string_field_init(&inuse, 16); 15389 ast_string_field_set(&inuse, name, "GR-303InUse"); 15390 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 15391 #endif 15392 #ifdef HAVE_SS7 15393 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15394 #endif 15395 15396 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 15397 15398 memset(round_robin, 0, sizeof(round_robin)); 15399 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" ); 15400 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" ); 15401 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" ); 15402 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" ); 15403 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" ); 15404 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels"); 15405 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)"); 15406 15407 ast_cond_init(&mwi_thread_complete, NULL); 15408 ast_cond_init(&ss_thread_complete, NULL); 15409 15410 return res; 15411 }
| static struct dahdi_pvt* mkintf | ( | int | channel, | |
| const struct dahdi_chan_conf * | conf, | |||
| struct dahdi_pri * | pri, | |||
| int | reloading | |||
| ) | [static, read] |
Definition at line 8744 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_calloc, ast_copy_string(), ast_dsp_set_digitmode(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_log(), ast_mutex_init(), ast_smdi_interface_find(), ast_strdupa, ast_strlen_zero(), ast_variable_new(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::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, ast_variable::file, 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, ast_variable::name, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, ast_variable::next, 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, ast_variable::value, and dahdi_pvt::vars.
Referenced by build_channels(), and process_dahdi().
08745 { 08746 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08747 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08748 char fn[80]; 08749 struct dahdi_bufferinfo bi; 08750 08751 int res; 08752 int span = 0; 08753 int here = 0; 08754 int x; 08755 struct dahdi_pvt **wlist; 08756 struct dahdi_pvt **wend; 08757 struct dahdi_params p; 08758 08759 wlist = &iflist; 08760 wend = &ifend; 08761 08762 #ifdef HAVE_PRI 08763 if (pri) { 08764 wlist = &pri->crvs; 08765 wend = &pri->crvend; 08766 } 08767 #endif 08768 08769 tmp2 = *wlist; 08770 prev = NULL; 08771 08772 while (tmp2) { 08773 if (!tmp2->destroy) { 08774 if (tmp2->channel == channel) { 08775 tmp = tmp2; 08776 here = 1; 08777 break; 08778 } 08779 if (tmp2->channel > channel) { 08780 break; 08781 } 08782 } 08783 prev = tmp2; 08784 tmp2 = tmp2->next; 08785 } 08786 08787 if (!here && reloading != 1) { 08788 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08789 if (tmp) 08790 free(tmp); 08791 return NULL; 08792 } 08793 ast_mutex_init(&tmp->lock); 08794 ifcount++; 08795 for (x = 0; x < 3; x++) 08796 tmp->subs[x].dfd = -1; 08797 tmp->channel = channel; 08798 tmp->priindication_oob = conf->chan.priindication_oob; 08799 } 08800 08801 if (tmp) { 08802 int chan_sig = conf->chan.sig; 08803 if (!here) { 08804 if ((channel != CHAN_PSEUDO) && !pri) { 08805 int count = 0; 08806 snprintf(fn, sizeof(fn), "%d", channel); 08807 /* Open non-blocking */ 08808 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08809 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 */ 08810 usleep(1); 08811 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08812 count++; 08813 } 08814 /* Allocate a DAHDI structure */ 08815 if (tmp->subs[SUB_REAL].dfd < 0) { 08816 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); 08817 destroy_dahdi_pvt(&tmp); 08818 return NULL; 08819 } 08820 memset(&p, 0, sizeof(p)); 08821 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08822 if (res < 0) { 08823 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08824 destroy_dahdi_pvt(&tmp); 08825 return NULL; 08826 } 08827 if (conf->is_sig_auto) 08828 chan_sig = sigtype_to_signalling(p.sigtype); 08829 if (p.sigtype != (chan_sig & 0x3ffff)) { 08830 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)); 08831 destroy_dahdi_pvt(&tmp); 08832 return NULL; 08833 } 08834 tmp->law = p.curlaw; 08835 tmp->span = p.spanno; 08836 span = p.spanno - 1; 08837 } else { 08838 if (channel == CHAN_PSEUDO) 08839 chan_sig = 0; 08840 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08841 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08842 return NULL; 08843 } 08844 } 08845 #ifdef HAVE_SS7 08846 if (chan_sig == SIG_SS7) { 08847 struct dahdi_ss7 *ss7; 08848 int clear = 0; 08849 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 08850 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08851 destroy_dahdi_pvt(&tmp); 08852 return NULL; 08853 } 08854 08855 ss7 = ss7_resolve_linkset(cur_linkset); 08856 if (!ss7) { 08857 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 08858 destroy_dahdi_pvt(&tmp); 08859 return NULL; 08860 } 08861 if (cur_cicbeginswith < 0) { 08862 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 08863 destroy_dahdi_pvt(&tmp); 08864 return NULL; 08865 } 08866 08867 tmp->cic = cur_cicbeginswith++; 08868 08869 /* DB: Add CIC's DPC information */ 08870 tmp->dpc = cur_defaultdpc; 08871 08872 tmp->ss7 = ss7; 08873 tmp->ss7call = NULL; 08874 ss7->pvts[ss7->numchans++] = tmp; 08875 08876 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix)); 08877 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix)); 08878 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix)); 08879 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix)); 08880 08881 ss7->called_nai = conf->ss7.called_nai; 08882 ss7->calling_nai = conf->ss7.calling_nai; 08883 } 08884 #endif 08885 #ifdef HAVE_PRI 08886 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08887 int offset; 08888 int myswitchtype; 08889 int matchesdchan; 08890 int x,y; 08891 offset = 0; 08892 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 08893 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08894 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08895 destroy_dahdi_pvt(&tmp); 08896 return NULL; 08897 } 08898 if (span >= NUM_SPANS) { 08899 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08900 destroy_dahdi_pvt(&tmp); 08901 return NULL; 08902 } else { 08903 struct dahdi_spaninfo si; 08904 si.spanno = 0; 08905 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08906 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08907 destroy_dahdi_pvt(&tmp); 08908 return NULL; 08909 } 08910 /* Store the logical span first based upon the real span */ 08911 tmp->logicalspan = pris[span].prilogicalspan; 08912 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08913 if (span < 0) { 08914 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08915 destroy_dahdi_pvt(&tmp); 08916 return NULL; 08917 } 08918 if ((chan_sig == SIG_PRI) || 08919 (chan_sig == SIG_BRI) || 08920 (chan_sig == SIG_BRI_PTMP)) 08921 myswitchtype = conf->pri.switchtype; 08922 else 08923 myswitchtype = PRI_SWITCH_GR303_TMC; 08924 /* Make sure this isn't a d-channel */ 08925 matchesdchan=0; 08926 for (x = 0; x < NUM_SPANS; x++) { 08927 for (y = 0; y < NUM_DCHANS; y++) { 08928 if (pris[x].dchannels[y] == tmp->channel) { 08929 matchesdchan = 1; 08930 break; 08931 } 08932 } 08933 } 08934 offset = p.chanpos; 08935 if (!matchesdchan) { 08936 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08937 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08938 destroy_dahdi_pvt(&tmp); 08939 return NULL; 08940 } 08941 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08942 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08943 destroy_dahdi_pvt(&tmp); 08944 return NULL; 08945 } 08946 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08947 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08948 destroy_dahdi_pvt(&tmp); 08949 return NULL; 08950 } 08951 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08952 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08953 destroy_dahdi_pvt(&tmp); 08954 return NULL; 08955 } 08956 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08957 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08958 destroy_dahdi_pvt(&tmp); 08959 return NULL; 08960 } 08961 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08962 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08963 destroy_dahdi_pvt(&tmp); 08964 return NULL; 08965 } 08966 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08967 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08968 destroy_dahdi_pvt(&tmp); 08969 return NULL; 08970 } 08971 if (pris[span].numchans >= MAX_CHANNELS) { 08972 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08973 pris[span].trunkgroup); 08974 destroy_dahdi_pvt(&tmp); 08975 return NULL; 08976 } 08977 08978 pris[span].sig = chan_sig; 08979 pris[span].nodetype = conf->pri.nodetype; 08980 pris[span].switchtype = myswitchtype; 08981 pris[span].nsf = conf->pri.nsf; 08982 pris[span].dialplan = conf->pri.dialplan; 08983 pris[span].localdialplan = conf->pri.localdialplan; 08984 pris[span].pvts[pris[span].numchans++] = tmp; 08985 pris[span].minunused = conf->pri.minunused; 08986 pris[span].minidle = conf->pri.minidle; 08987 pris[span].overlapdial = conf->pri.overlapdial; 08988 #ifdef HAVE_PRI_INBANDDISCONNECT 08989 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08990 #endif 08991 pris[span].facilityenable = conf->pri.facilityenable; 08992 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08993 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08994 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08995 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08996 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08997 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08998 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08999 pris[span].resetinterval = conf->pri.resetinterval; 09000 09001 tmp->pri = &pris[span]; 09002 tmp->prioffset = offset; 09003 tmp->call = NULL; 09004 } else { 09005 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 09006 destroy_dahdi_pvt(&tmp); 09007 return NULL; 09008 } 09009 } 09010 } else { 09011 tmp->prioffset = 0; 09012 } 09013 #endif 09014 } else { 09015 chan_sig = tmp->sig; 09016 if (tmp->subs[SUB_REAL].dfd > -1) { 09017 memset(&p, 0, sizeof(p)); 09018 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 09019 } 09020 } 09021 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 09022 switch (chan_sig) { 09023 case SIG_FXSKS: 09024 case SIG_FXSLS: 09025 case SIG_EM: 09026 case SIG_EM_E1: 09027 case SIG_EMWINK: 09028 case SIG_FEATD: 09029 case SIG_FEATDMF: 09030 case SIG_FEATDMF_TA: 09031 case SIG_FEATB: 09032 case SIG_E911: 09033 case SIG_SF: 09034 case SIG_SFWINK: 09035 case SIG_FGC_CAMA: 09036 case SIG_FGC_CAMAMF: 09037 case SIG_SF_FEATD: 09038 case SIG_SF_FEATDMF: 09039 case SIG_SF_FEATB: 09040 p.starttime = 250; 09041 break; 09042 } 09043 09044 if (tmp->radio) { 09045 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 09046 p.channo = channel; 09047 p.rxwinktime = 1; 09048 p.rxflashtime = 1; 09049 p.starttime = 1; 09050 p.debouncetime = 5; 09051 } 09052 if (!tmp->radio) { 09053 p.channo = channel; 09054 /* Override timing settings based on config file */ 09055 if (conf->timing.prewinktime >= 0) 09056 p.prewinktime = conf->timing.prewinktime; 09057 if (conf->timing.preflashtime >= 0) 09058 p.preflashtime = conf->timing.preflashtime; 09059 if (conf->timing.winktime >= 0) 09060 p.winktime = conf->timing.winktime; 09061 if (conf->timing.flashtime >= 0) 09062 p.flashtime = conf->timing.flashtime; 09063 if (conf->timing.starttime >= 0) 09064 p.starttime = conf->timing.starttime; 09065 if (conf->timing.rxwinktime >= 0) 09066 p.rxwinktime = conf->timing.rxwinktime; 09067 if (conf->timing.rxflashtime >= 0) 09068 p.rxflashtime = conf->timing.rxflashtime; 09069 if (conf->timing.debouncetime >= 0) 09070 p.debouncetime = conf->timing.debouncetime; 09071 } 09072 09073 /* dont set parms on a pseudo-channel (or CRV) */ 09074 if (tmp->subs[SUB_REAL].dfd >= 0) 09075 { 09076 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 09077 if (res < 0) { 09078 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 09079 destroy_dahdi_pvt(&tmp); 09080 return NULL; 09081 } 09082 } 09083 #if 1 09084 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 09085 memset(&bi, 0, sizeof(bi)); 09086 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09087 if (!res) { 09088 bi.txbufpolicy = conf->chan.buf_policy; 09089 bi.rxbufpolicy = conf->chan.buf_policy; 09090 bi.numbufs = conf->chan.buf_no; 09091 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09092 if (res < 0) { 09093 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 09094 } 09095 } else 09096 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 09097 } 09098 #endif 09099 tmp->immediate = conf->chan.immediate; 09100 tmp->transfertobusy = conf->chan.transfertobusy; 09101 if (chan_sig & __DAHDI_SIG_FXS) { 09102 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 09103 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 09104 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 09105 } 09106 tmp->sig = chan_sig; 09107 tmp->outsigmod = conf->chan.outsigmod; 09108 tmp->ringt_base = ringt_base; 09109 tmp->firstradio = 0; 09110 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 09111 tmp->permcallwaiting = conf->chan.callwaiting; 09112 else 09113 tmp->permcallwaiting = 0; 09114 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 09115 tmp->destroy = 0; 09116 tmp->drings = conf->chan.drings; 09117 09118 /* 10 is a nice default. */ 09119 if (tmp->drings.ringnum[0].range == 0) 09120 tmp->drings.ringnum[0].range = 10; 09121 if (tmp->drings.ringnum[1].range == 0) 09122 tmp->drings.ringnum[1].range = 10; 09123 if (tmp->drings.ringnum[2].range == 0) 09124 tmp->drings.ringnum[2].range = 10; 09125 09126 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 09127 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 09128 tmp->threewaycalling = conf->chan.threewaycalling; 09129 tmp->adsi = conf->chan.adsi; 09130 tmp->use_smdi = conf->chan.use_smdi; 09131 tmp->permhidecallerid = conf->chan.hidecallerid; 09132 tmp->callreturn = conf->chan.callreturn; 09133 tmp->echocancel = conf->chan.echocancel; 09134 tmp->echotraining = conf->chan.echotraining; 09135 tmp->pulse = conf->chan.pulse; 09136 if (tmp->echocancel.head.tap_length) { 09137 tmp->echocanbridged = conf->chan.echocanbridged; 09138 } else { 09139 if (conf->chan.echocanbridged) 09140 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 09141 tmp->echocanbridged = 0; 09142 } 09143 tmp->busydetect = conf->chan.busydetect; 09144 tmp->busycount = conf->chan.busycount; 09145 tmp->busy_tonelength = conf->chan.busy_tonelength; 09146 tmp->busy_quietlength = conf->chan.busy_quietlength; 09147 tmp->callprogress = conf->chan.callprogress; 09148 tmp->cancallforward = conf->chan.cancallforward; 09149 tmp->dtmfrelax = conf->chan.dtmfrelax; 09150 tmp->callwaiting = tmp->permcallwaiting; 09151 tmp->hidecallerid = tmp->permhidecallerid; 09152 tmp->channel = channel; 09153 tmp->stripmsd = conf->chan.stripmsd; 09154 tmp->use_callerid = conf->chan.use_callerid; 09155 tmp->cid_signalling = conf->chan.cid_signalling; 09156 tmp->cid_start = conf->chan.cid_start; 09157 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09158 tmp->restrictcid = conf->chan.restrictcid; 09159 tmp->use_callingpres = conf->chan.use_callingpres; 09160 tmp->priexclusive = conf->chan.priexclusive; 09161 if (tmp->usedistinctiveringdetection) { 09162 if (!tmp->use_callerid) { 09163 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09164 tmp->use_callerid = 1; 09165 } 09166 } 09167 09168 if (tmp->cid_signalling == CID_SIG_SMDI) { 09169 if (!tmp->use_smdi) { 09170 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09171 tmp->use_smdi = 1; 09172 } 09173 } 09174 if (tmp->use_smdi) { 09175 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09176 if (!(tmp->smdi_iface)) { 09177 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09178 tmp->use_smdi = 0; 09179 } 09180 } 09181 09182 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09183 tmp->amaflags = conf->chan.amaflags; 09184 if (!here) { 09185 tmp->confno = -1; 09186 tmp->propconfno = -1; 09187 } 09188 tmp->canpark = conf->chan.canpark; 09189 tmp->transfer = conf->chan.transfer; 09190 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09191 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09192 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09193 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09194 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09195 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 09196 tmp->cid_ton = 0; 09197 if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP)) { 09198 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09199 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09200 } else { 09201 tmp->cid_num[0] = '\0'; 09202 tmp->cid_name[0] = '\0'; 09203 } 09204 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09205 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 09206 char *mailbox, *context; 09207 mailbox = context = ast_strdupa(tmp->mailbox); 09208 strsep(&context, "@"); 09209 if (ast_strlen_zero(context)) 09210 context = "default"; 09211 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 09212 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 09213 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 09214 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 09215 AST_EVENT_IE_END); 09216 } 09217 tmp->msgstate = -1; 09218 tmp->group = conf->chan.group; 09219 tmp->callgroup = conf->chan.callgroup; 09220 tmp->pickupgroup= conf->chan.pickupgroup; 09221 if (conf->chan.vars) { 09222 struct ast_variable *v, *tmpvar; 09223 for (v = conf->chan.vars ; v ; v = v->next) { 09224 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 09225 tmpvar->next = tmp->vars; 09226 tmp->vars = tmpvar; 09227 } 09228 } 09229 } 09230 tmp->cid_rxgain = conf->chan.cid_rxgain; 09231 tmp->rxgain = conf->chan.rxgain; 09232 tmp->txgain = conf->chan.txgain; 09233 tmp->tonezone = conf->chan.tonezone; 09234 tmp->onhooktime = time(NULL); 09235 if (tmp->subs[SUB_REAL].dfd > -1) { 09236 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09237 if (tmp->dsp) 09238 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09239 update_conf(tmp); 09240 if (!here) { 09241 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7)) 09242 /* Hang it up to be sure it's good */ 09243 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09244 } 09245 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09246 #ifdef HAVE_PRI 09247 /* the dchannel is down so put the channel in alarm */ 09248 if (tmp->pri && !pri_is_up(tmp->pri)) 09249 tmp->inalarm = 1; 09250 #endif 09251 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09252 tmp->inalarm = 1; 09253 handle_alarms(tmp, res); 09254 } 09255 } 09256 09257 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09258 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09259 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09260 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09261 if (!here) { 09262 tmp->locallyblocked = tmp->remotelyblocked = 0; 09263 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) 09264 tmp->inservice = 0; 09265 else /* We default to in service on protocols that don't have a reset */ 09266 tmp->inservice = 1; 09267 } 09268 } 09269 if (tmp && !here) { 09270 /* nothing on the iflist */ 09271 if (!*wlist) { 09272 *wlist = tmp; 09273 tmp->prev = NULL; 09274 tmp->next = NULL; 09275 *wend = tmp; 09276 } else { 09277 /* at least one member on the iflist */ 09278 struct dahdi_pvt *working = *wlist; 09279 09280 /* check if we maybe have to put it on the begining */ 09281 if (working->channel > tmp->channel) { 09282 tmp->next = *wlist; 09283 tmp->prev = NULL; 09284 (*wlist)->prev = tmp; 09285 *wlist = tmp; 09286 } else { 09287 /* go through all the members and put the member in the right place */ 09288 while (working) { 09289 /* in the middle */ 09290 if (working->next) { 09291 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09292 tmp->next = working->next; 09293 tmp->prev = working; 09294 working->next->prev = tmp; 09295 working->next = tmp; 09296 break; 09297 } 09298 } else { 09299 /* the last */ 09300 if (working->channel < tmp->channel) { 09301 working->next = tmp; 09302 tmp->next = NULL; 09303 tmp->prev = working; 09304 *wend = tmp; 09305 break; 09306 } 09307 } 09308 working = working->next; 09309 } 09310 } 09311 } 09312 } 09313 return tmp; 09314 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 295 of file chan_dahdi.c.
Referenced by mkintf().
00296 { 00297 /* This module does not handle MWI in an event-based manner. However, it 00298 * subscribes to MWI for each mailbox that is configured so that the core 00299 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00300 * event cache instead of checking the mailbox directly. */ 00301 }
| static void* mwi_send_thread | ( | void * | data | ) | [static] |
Definition at line 7950 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().
07951 { 07952 struct mwi_thread_data *mtd = data; 07953 struct timeval timeout_basis, suspend, now; 07954 int x, i, res; 07955 int num_read; 07956 enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */ 07957 07958 ast_mutex_lock(&mwi_thread_lock); 07959 mwi_thread_count++; 07960 ast_mutex_unlock(&mwi_thread_lock); 07961 07962 /* Determine how this spill is to be sent */ 07963 if(mwisend_rpas) { 07964 mwi_send_state = MWI_SEND_SA; 07965 } 07966 07967 gettimeofday(&timeout_basis, NULL); 07968 07969 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 07970 if (!mtd->pvt->cidspill) { 07971 mtd->pvt->mwisendactive = 0; 07972 ast_free(mtd); 07973 return NULL; 07974 } 07975 x = DAHDI_FLUSH_BOTH; 07976 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07977 x = 3000; 07978 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07979 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL, 07980 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0); 07981 mtd->pvt->cidpos = 0; 07982 07983 while (MWI_SEND_DONE != mwi_send_state) { 07984 num_read = 0; 07985 gettimeofday(&now, NULL); 07986 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) { 07987 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state); 07988 goto quit; 07989 } 07990 07991 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07992 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07993 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07994 goto quit; 07995 } 07996 07997 if (i & DAHDI_IOMUX_SIGEVENT) { 07998 /* If we get an event, screen out events that we do not act on. 07999 * Otherwise, let handle_init_event determine what is needed 08000 */ 08001 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 08002 switch (res) { 08003 case DAHDI_EVENT_RINGEROFF: 08004 if(mwi_send_state == MWI_SEND_SA_WAIT) { 08005 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 08006 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno)); 08007 goto quit; 08008 } 08009 mwi_send_state = MWI_SEND_PAUSE; 08010 gettimeofday(&suspend, NULL); 08011 } 08012 break; 08013 case DAHDI_EVENT_RINGERON: 08014 case DAHDI_EVENT_HOOKCOMPLETE: 08015 break; 08016 default: 08017 /* Got to the default init event handler */ 08018 if (0 < handle_init_event(mtd->pvt, res)) { 08019 /* I've spawned a thread, get out */ 08020 goto quit; 08021 } 08022 break; 08023 } 08024 } else if (i & DAHDI_IOMUX_READ) { 08025 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 08026 if (errno != ELAST) { 08027 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08028 goto quit; 08029 } 08030 break; 08031 } 08032 } 08033 /* Perform mwi send action */ 08034 switch ( mwi_send_state) { 08035 case MWI_SEND_SA: 08036 /* Send the Ring Pulse Signal Alert */ 08037 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 08038 if (res) { 08039 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 08040 goto quit; 08041 } 08042 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING); 08043 mwi_send_state = MWI_SEND_SA_WAIT; 08044 break; 08045 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 08046 break; 08047 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 08048 gettimeofday(&now, NULL); 08049 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) { 08050 mwi_send_state = MWI_SEND_SPILL; 08051 } 08052 break; 08053 case MWI_SEND_SPILL: 08054 /* We read some number of bytes. Write an equal amount of data */ 08055 if(0 < num_read) { 08056 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos) 08057 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos; 08058 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read); 08059 if (res > 0) { 08060 mtd->pvt->cidpos += res; 08061 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) { 08062 ast_free(mtd->pvt->cidspill); 08063 mtd->pvt->cidspill = NULL; 08064 mtd->pvt->cidpos = 0; 08065 mtd->pvt->cidlen = 0; 08066 mwi_send_state = MWI_SEND_CLEANUP; 08067 } 08068 } else { 08069 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno)); 08070 goto quit; 08071 } 08072 } 08073 break; 08074 case MWI_SEND_CLEANUP: 08075 /* For now, do nothing */ 08076 mwi_send_state = MWI_SEND_DONE; 08077 break; 08078 default: 08079 /* Should not get here, punt*/ 08080 goto quit; 08081 break; 08082 } 08083 } 08084 08085 quit: 08086 if(mtd->pvt->cidspill) { 08087 ast_free(mtd->pvt->cidspill); 08088 mtd->pvt->cidspill = NULL; 08089 } 08090 mtd->pvt->mwisendactive = 0; 08091 ast_free(mtd); 08092 08093 ast_mutex_lock(&mwi_thread_lock); 08094 mwi_thread_count--; 08095 ast_cond_signal(&mwi_thread_complete); 08096 ast_mutex_unlock(&mwi_thread_lock); 08097 08098 return NULL; 08099 }
| static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 7807 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().
07808 { 07809 struct mwi_thread_data *mtd = data; 07810 struct callerid_state *cs; 07811 pthread_t threadid; 07812 int samples = 0; 07813 char *name, *number; 07814 int flags; 07815 int i, res; 07816 unsigned int spill_done = 0; 07817 int spill_result = -1; 07818 07819 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 07820 mtd->pvt->mwimonitoractive = 0; 07821 07822 return NULL; 07823 } 07824 07825 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 07826 07827 bump_gains(mtd->pvt); 07828 07829 for (;;) { 07830 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07831 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07832 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07833 goto quit; 07834 } 07835 07836 if (i & DAHDI_IOMUX_SIGEVENT) { 07837 struct ast_channel *chan; 07838 07839 /* If we get an event, screen out events that we do not act on. 07840 * Otherwise, cancel and go to the simple switch to let it deal with it. 07841 */ 07842 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07843 07844 switch (res) { 07845 case DAHDI_EVENT_NEONMWI_ACTIVE: 07846 case DAHDI_EVENT_NEONMWI_INACTIVE: 07847 case DAHDI_EVENT_NONE: 07848 case DAHDI_EVENT_BITSCHANGED: 07849 break; 07850 case DAHDI_EVENT_NOALARM: 07851 mtd->pvt->inalarm = 0; 07852 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); 07853 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07854 "Channel: %d\r\n", mtd->pvt->channel); 07855 break; 07856 case DAHDI_EVENT_ALARM: 07857 mtd->pvt->inalarm = 1; 07858 res = get_alarms(mtd->pvt); 07859 handle_alarms(mtd->pvt, res); 07860 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 07861 default: 07862 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res)); 07863 callerid_free(cs); 07864 07865 restore_gains(mtd->pvt); 07866 mtd->pvt->ringt = mtd->pvt->ringt_base; 07867 07868 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) { 07869 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07870 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 07871 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07872 if (res < 0) 07873 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 07874 ast_hangup(chan); 07875 goto quit; 07876 } 07877 goto quit_no_clean; 07878 07879 } else { 07880 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 07881 } 07882 } 07883 } else if (i & DAHDI_IOMUX_READ) { 07884 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07885 if (errno != ELAST) { 07886 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07887 goto quit; 07888 } 07889 break; 07890 } 07891 samples += res; 07892 if (!spill_done) { 07893 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 07894 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07895 break; 07896 } else if (spill_result) { 07897 spill_done = 1; 07898 } 07899 } else { 07900 /* keep reading data until the energy level drops below the threshold 07901 so we don't get another 'trigger' on the remaining carrier signal 07902 */ 07903 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 07904 break; 07905 } 07906 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 07907 break; 07908 } 07909 } 07910 07911 if (spill_result == 1) { 07912 callerid_get(cs, &name, &number, &flags); 07913 if (flags & CID_MSGWAITING) { 07914 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 07915 notify_message(mtd->pvt->mailbox, 1); 07916 } else if (flags & CID_NOMSGWAITING) { 07917 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 07918 notify_message(mtd->pvt->mailbox, 0); 07919 } else { 07920 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 07921 } 07922 } 07923 07924 07925 quit: 07926 callerid_free(cs); 07927 07928 restore_gains(mtd->pvt); 07929 07930 quit_no_clean: 07931 mtd->pvt->mwimonitoractive = 0; 07932 07933 ast_free(mtd); 07934 07935 return NULL; 07936 }
| static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
| unsigned char * | buf, | |||
| int | len, | |||
| int | idx, | |||
| int | linear | |||
| ) | [static] |
Definition at line 5974 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().
05975 { 05976 int sent=0; 05977 int size; 05978 int res; 05979 int fd; 05980 fd = p->subs[idx].dfd; 05981 while (len) { 05982 size = len; 05983 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05984 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05985 res = write(fd, buf, size); 05986 if (res != size) { 05987 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05988 return sent; 05989 } 05990 len -= size; 05991 buf += size; 05992 } 05993 return sent; 05994 }
| static int my_getsigstr | ( | struct ast_channel * | chan, | |
| char * | str, | |||
| const char * | term, | |||
| int | ms | |||
| ) | [static] |
Definition at line 6495 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
06496 { 06497 char c; 06498 06499 *str = 0; /* start with empty output buffer */ 06500 for (;;) 06501 { 06502 /* Wait for the first digit (up to specified ms). */ 06503 c = ast_waitfordigit(chan, ms); 06504 /* if timeout, hangup or error, return as such */ 06505 if (c < 1) 06506 return c; 06507 *str++ = c; 06508 *str = 0; 06509 if (strchr(term, c)) 06510 return 1; 06511 } 06512 }
| 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 2285 of file chan_dahdi.c.
References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_safe_system(), ast_strdupa, ast_strlen_zero(), context, mailbox, s, and strsep().
Referenced by handle_init_event(), mwi_thread(), and ss_thread().
02286 { 02287 char s[sizeof(mwimonitornotify) + 80]; 02288 struct ast_event *event; 02289 char *mailbox, *context; 02290 02291 /* Strip off @default */ 02292 context = mailbox = ast_strdupa(mailbox_full); 02293 strsep(&context, "@"); 02294 if (ast_strlen_zero(context)) 02295 context = "default"; 02296 02297 if (!(event = ast_event_new(AST_EVENT_MWI, 02298 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02299 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02300 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02301 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02302 AST_EVENT_IE_END))) { 02303 return; 02304 } 02305 02306 ast_event_queue_and_cache(event); 02307 02308 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 02309 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 02310 ast_safe_system(s); 02311 } 02312 }
| static unsigned int parse_pointcode | ( | const char * | pcstring | ) | [static] |
Definition at line 8711 of file chan_dahdi.c.
Referenced by process_dahdi().
| static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3341 of file chan_dahdi.c.
References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, and dahdi_pri::pri.
Referenced by pri_find_principle().
03342 { 03343 int x = -1; 03344 03345 for (x = 0; x < NUM_DCHANS; x++) { 03346 if ((pri->dchans[x] == pri->pri)) 03347 break; 03348 } 03349 03350 return pri->fds[x]; 03351 }
| static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
| struct dahdi_pri * | pri, | |||
| struct dahdi_pvt * | bearer | |||
| ) | [static] |
Definition at line 3311 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().
03312 { 03313 bearer->owner = &inuse; 03314 bearer->realcall = crv; 03315 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03316 if (crv->subs[SUB_REAL].owner) 03317 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd); 03318 crv->bearer = bearer; 03319 crv->call = bearer->call; 03320 crv->pri = pri; 03321 return 0; 03322 }
| static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 10826 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().
10827 { 10828 do { 10829 pri->resetpos++; 10830 } while ((pri->resetpos < pri->numchans) && 10831 (!pri->pvts[pri->resetpos] || 10832 pri->pvts[pri->resetpos]->call || 10833 pri->pvts[pri->resetpos]->resetting)); 10834 if (pri->resetpos < pri->numchans) { 10835 /* Mark the channel as resetting and restart it */ 10836 pri->pvts[pri->resetpos]->resetting = 1; 10837 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 10838 } else { 10839 pri->resetting = 0; 10840 time(&pri->lastreset); 10841 } 10842 return 0; 10843 }
| static int pri_create_spanmap | ( | int | span, | |
| int | trunkgroup, | |||
| int | logicalspan | |||
| ) | [static] |
Definition at line 8696 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08697 { 08698 if (pris[span].mastertrunkgroup) { 08699 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); 08700 return -1; 08701 } 08702 pris[span].mastertrunkgroup = trunkgroup; 08703 pris[span].prilogicalspan = logicalspan; 08704 return 0; 08705 }
| static int pri_create_trunkgroup | ( | int | trunkgroup, | |
| int * | channels | |||
| ) | [static] |
Definition at line 8633 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().
08634 { 08635 struct dahdi_spaninfo si; 08636 struct dahdi_params p; 08637 int fd; 08638 int span; 08639 int ospan=0; 08640 int x,y; 08641 for (x = 0; x < NUM_SPANS; x++) { 08642 if (pris[x].trunkgroup == trunkgroup) { 08643 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08644 return -1; 08645 } 08646 } 08647 for (y = 0; y < NUM_DCHANS; y++) { 08648 if (!channels[y]) 08649 break; 08650 memset(&si, 0, sizeof(si)); 08651 memset(&p, 0, sizeof(p)); 08652 fd = open("/dev/dahdi/channel", O_RDWR); 08653 if (fd < 0) { 08654 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08655 return -1; 08656 } 08657 x = channels[y]; 08658 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08659 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08660 close(fd); 08661 return -1; 08662 } 08663 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08664 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08665 return -1; 08666 } 08667 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08668 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08669 close(fd); 08670 return -1; 08671 } 08672 span = p.spanno - 1; 08673 if (pris[span].trunkgroup) { 08674 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08675 close(fd); 08676 return -1; 08677 } 08678 if (pris[span].pvts[0]) { 08679 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08680 close(fd); 08681 return -1; 08682 } 08683 if (!y) { 08684 pris[span].trunkgroup = trunkgroup; 08685 pris[span].offset = channels[y] - p.chanpos; 08686 ospan = span; 08687 } 08688 pris[ospan].dchannels[y] = channels[y]; 08689 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08690 pris[span].span = span + 1; 08691 close(fd); 08692 } 08693 return 0; 08694 }
| static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10920 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_BUSY, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callingpres, dahdi_pvt::channel, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confirmanswer, dahdi_pvt::context, dahdi_enable_ec(), dahdi_hangup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_queue_frame(), dahdi_request(), dahdi_setlaw(), DCHAN_NOTINALARM, DCHAN_UP, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, dahdi_pri::debug, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_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().
10921 { 10922 struct dahdi_pri *pri = vpri; 10923 pri_event *e; 10924 struct pollfd fds[NUM_DCHANS]; 10925 int res; 10926 int chanpos = 0; 10927 int x; 10928 int haveidles; 10929 int activeidles; 10930 int nextidle = -1; 10931 struct ast_channel *c; 10932 struct timeval tv, lowest, *next; 10933 struct timeval lastidle = ast_tvnow(); 10934 int doidling=0; 10935 char *cc; 10936 char idlen[80]; 10937 struct ast_channel *idle; 10938 pthread_t p; 10939 time_t t; 10940 int i, which=-1; 10941 int numdchans; 10942 int cause=0; 10943 struct dahdi_pvt *crv; 10944 pthread_t threadid; 10945 char ani2str[6]; 10946 char plancallingnum[256]; 10947 char plancallingani[256]; 10948 char calledtonstr[10]; 10949 10950 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10951 10952 gettimeofday(&lastidle, NULL); 10953 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10954 /* Need to do idle dialing, check to be sure though */ 10955 cc = strchr(pri->idleext, '@'); 10956 if (cc) { 10957 *cc = '\0'; 10958 cc++; 10959 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10960 #if 0 10961 /* Extensions may not be loaded yet */ 10962 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10963 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10964 else 10965 #endif 10966 doidling = 1; 10967 } else 10968 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10969 } 10970 for (;;) { 10971 for (i = 0; i < NUM_DCHANS; i++) { 10972 if (!pri->dchannels[i]) 10973 break; 10974 fds[i].fd = pri->fds[i]; 10975 fds[i].events = POLLIN | POLLPRI; 10976 fds[i].revents = 0; 10977 } 10978 numdchans = i; 10979 time(&t); 10980 ast_mutex_lock(&pri->lock); 10981 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10982 if (pri->resetting && pri_is_up(pri)) { 10983 if (pri->resetpos < 0) 10984 pri_check_restart(pri); 10985 } else { 10986 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10987 pri->resetting = 1; 10988 pri->resetpos = -1; 10989 } 10990 } 10991 } 10992 /* Look for any idle channels if appropriate */ 10993 if (doidling && pri_is_up(pri)) { 10994 nextidle = -1; 10995 haveidles = 0; 10996 activeidles = 0; 10997 for (x = pri->numchans; x >= 0; x--) { 10998 if (pri->pvts[x] && !pri->pvts[x]->owner && 10999 !pri->pvts[x]->call) { 11000 if (haveidles < pri->minunused) { 11001 haveidles++; 11002 } else if (!pri->pvts[x]->resetting) { 11003 nextidle = x; 11004 break; 11005 } 11006 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 11007 activeidles++; 11008 } 11009 if (nextidle > -1) { 11010 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 11011 /* Don't create a new idle call more than once per second */ 11012 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 11013 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause); 11014 if (idle) { 11015 pri->pvts[nextidle]->isidlecall = 1; 11016 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 11017 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 11018 dahdi_hangup(idle); 11019 } 11020 } else 11021 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 11022 lastidle = ast_tvnow(); 11023 } 11024 } else if ((haveidles < pri->minunused) && 11025 (activeidles > pri->minidle)) { 11026 /* Mark something for hangup if there is something 11027 that can be hungup */ 11028 for (x = pri->numchans; x >= 0; x--) { 11029 /* find a candidate channel */ 11030 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 11031 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11032 haveidles++; 11033 /* Stop if we have enough idle channels or 11034 can't spare any more active idle ones */ 11035 if ((haveidles >= pri->minunused) || 11036 (activeidles <= pri->minidle)) 11037 break; 11038 } 11039 } 11040 } 11041 } 11042 /* Start with reasonable max */ 11043 lowest = ast_tv(60, 0); 11044 for (i = 0; i < NUM_DCHANS; i++) { 11045 /* Find lowest available d-channel */ 11046 if (!pri->dchannels[i]) 11047 break; 11048 if ((next = pri_schedule_next(pri->dchans[i]))) { 11049 /* We need relative time here */ 11050 tv = ast_tvsub(*next, ast_tvnow()); 11051 if (tv.tv_sec < 0) { 11052 tv = ast_tv(0,0); 11053 } 11054 if (doidling || pri->resetting) { 11055 if (tv.tv_sec > 1) { 11056 tv = ast_tv(1, 0); 11057 } 11058 } else { 11059 if (tv.tv_sec > 60) { 11060 tv = ast_tv(60, 0); 11061 } 11062 } 11063 } else if (doidling || pri->resetting) { 11064 /* Make sure we stop at least once per second if we're 11065 monitoring idle channels */ 11066 tv = ast_tv(1,0); 11067 } else { 11068 /* Don't poll for more than 60 seconds */ 11069 tv = ast_tv(60, 0); 11070 } 11071 if (!i || ast_tvcmp(tv, lowest) < 0) { 11072 lowest = tv; 11073 } 11074 } 11075 ast_mutex_unlock(&pri->lock); 11076 11077 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11078 pthread_testcancel(); 11079 e = NULL; 11080 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 11081 pthread_testcancel(); 11082 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11083 11084 ast_mutex_lock(&pri->lock); 11085 if (!res) { 11086 for (which = 0; which < NUM_DCHANS; which++) { 11087 if (!pri->dchans[which]) 11088 break; 11089 /* Just a timeout, run the scheduler */ 11090 e = pri_schedule_run(pri->dchans[which]); 11091 if (e) 11092 break; 11093 } 11094 } else if (res > -1) { 11095 for (which = 0; which < NUM_DCHANS; which++) { 11096 if (!pri->dchans[which]) 11097 break; 11098 if (fds[which].revents & POLLPRI) { 11099 /* Check for an event */ 11100 x = 0; 11101 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 11102 if (x) { 11103 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); 11104 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent", 11105 "PRIEvent: %s\r\n" 11106 "PRIEventCode: %d\r\n" 11107 "D-channel: %s\r\n" 11108 "Span: %d\r\n", 11109 event2str(x), 11110 x, 11111 pri_order(which), 11112 pri->span 11113 ); 11114 } 11115 /* Keep track of alarm state */ 11116 if (x == DAHDI_EVENT_ALARM) { 11117 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 11118 pri_find_dchan(pri); 11119 } else if (x == DAHDI_EVENT_NOALARM) { 11120 pri->dchanavail[which] |= DCHAN_NOTINALARM; 11121 pri_restart(pri->dchans[which]); 11122 } 11123 11124 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 11125 } else if (fds[which].revents & POLLIN) { 11126 e = pri_check_event(pri->dchans[which]); 11127 } 11128 if (e) 11129 break; 11130 } 11131 } else if (errno != EINTR) 11132 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 11133 11134 if (e) { 11135 if (pri->debug) 11136 pri_dump_event(pri->dchans[which], e); 11137 11138 if (e->e != PRI_EVENT_DCHAN_DOWN) { 11139 if (!(pri->dchanavail[which] & DCHAN_UP)) { 11140 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span); 11141 } 11142 pri->dchanavail[which] |= DCHAN_UP; 11143 } else if (pri->sig != SIG_BRI_PTMP) { 11144 if (pri->dchanavail[which] & DCHAN_UP) { 11145 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span); 11146 } 11147 pri->dchanavail[which] &= ~DCHAN_UP; 11148 } 11149 11150 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 11151 /* Must be an NFAS group that has the secondary dchan active */ 11152 pri->pri = pri->dchans[which]; 11153 11154 switch (e->e) { 11155 case PRI_EVENT_DCHAN_UP: 11156 if (!pri->pri) pri_find_dchan(pri); 11157 11158 /* Note presense of D-channel */ 11159 time(&pri->lastreset); 11160 11161 /* Restart in 5 seconds */ 11162 if (pri->resetinterval > -1) { 11163 pri->lastreset -= pri->resetinterval; 11164 pri->lastreset += 5; 11165 } 11166 pri->resetting = 0; 11167 /* Take the channels from inalarm condition */ 11168 for (i = 0; i < pri->numchans; i++) 11169 if (pri->pvts[i]) { 11170 pri->pvts[i]->inalarm = 0; 11171 } 11172 break; 11173 case PRI_EVENT_DCHAN_DOWN: 11174 pri_find_dchan(pri); 11175 if (!pri_is_up(pri)) { 11176 pri->resetting = 0; 11177 /* Hangup active channels and put them in alarm mode */ 11178 for (i = 0; i < pri->numchans; i++) { 11179 struct dahdi_pvt *p = pri->pvts[i]; 11180 if (p) { 11181 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 11182 /* T309 is not enabled : hangup calls when alarm occurs */ 11183 if (p->call) { 11184 if (p->pri && p->pri->pri) { 11185 pri_hangup(p->pri->pri, p->call, -1); 11186 pri_destroycall(p->pri->pri, p->call); 11187 p->call = NULL; 11188 } else 11189 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 11190 } 11191 if (p->realcall) { 11192 pri_hangup_all(p->realcall, pri); 11193 } else if (p->owner) 11194 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11195 } 11196 p->inalarm = 1; 11197 } 11198 } 11199 } 11200 break; 11201 case PRI_EVENT_RESTART: 11202 if (e->restart.channel > -1) { 11203 chanpos = pri_find_principle(pri, e->restart.channel); 11204 if (chanpos < 0) 11205 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 11206 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11207 else { 11208 ast_verb(3, "B-channel %d/%d restarted on span %d\n", 11209 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11210 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11211 if (pri->pvts[chanpos]->call) { 11212 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 11213 pri->pvts[chanpos]->call = NULL; 11214 } 11215 /* Force soft hangup if appropriate */ 11216 if (pri->pvts[chanpos]->realcall) 11217 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11218 else if (pri->pvts[chanpos]->owner) 11219 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11220 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11221 } 11222 } else { 11223 ast_verb(3, "Restart on requested on entire span %d\n", pri->span); 11224 for (x = 0; x < pri->numchans; x++) 11225 if (pri->pvts[x]) { 11226 ast_mutex_lock(&pri->pvts[x]->lock); 11227 if (pri->pvts[x]->call) { 11228 pri_destroycall(pri->pri, pri->pvts[x]->call); 11229 pri->pvts[x]->call = NULL; 11230 } 11231 if (pri->pvts[x]->realcall) 11232 pri_hangup_all(pri->pvts[x]->realcall, pri); 11233 else if (pri->pvts[x]->owner) 11234 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11235 ast_mutex_unlock(&pri->pvts[x]->lock); 11236 } 11237 } 11238 break; 11239 case PRI_EVENT_KEYPAD_DIGIT: 11240 chanpos = pri_find_principle(pri, e->digit.channel); 11241 if (chanpos < 0) { 11242 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 11243 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 11244 } else { 11245 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 11246 if (chanpos > -1) { 11247 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11248 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 11249 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 11250 /* how to do that */ 11251 int digitlen = strlen(e->digit.digits); 11252 char digit; 11253 int i; 11254 for (i = 0; i < digitlen; i++) { 11255 digit = e->digit.digits[i]; 11256 { 11257 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11258 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11259 } 11260 } 11261 } 11262 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11263 } 11264 } 11265 break; 11266 11267 case PRI_EVENT_INFO_RECEIVED: 11268 chanpos = pri_find_principle(pri, e->ring.channel); 11269 if (chanpos < 0) { 11270 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 11271 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11272 } else { 11273 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 11274 if (chanpos > -1) { 11275 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11276 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 11277 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 11278 /* how to do that */ 11279 int digitlen = strlen(e->ring.callednum); 11280 char digit; 11281 int i; 11282 for (i = 0; i < digitlen; i++) { 11283 digit = e->ring.callednum[i]; 11284 { 11285 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11286 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11287 } 11288 } 11289 } 11290 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11291 } 11292 } 11293 break; 11294 case PRI_EVENT_RING: 11295 crv = NULL; 11296 if (e->ring.channel == -1) 11297 chanpos = pri_find_empty_chan(pri, 1); 11298 else 11299 chanpos = pri_find_principle(pri, e->ring.channel); 11300 /* if no channel specified find one empty */ 11301 if (chanpos < 0) { 11302 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 11303 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11304 } else { 11305 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11306 if (pri->pvts[chanpos]->owner) { 11307 if (pri->pvts[chanpos]->call == e->ring.call) { 11308 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 11309 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11310 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11311 break; 11312 } else { 11313 /* This is where we handle initial glare */ 11314 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n", 11315 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11316 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11317 chanpos = -1; 11318 } 11319 } 11320 if (chanpos > -1) 11321 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11322 } 11323 if ((chanpos < 0) && (e->ring.flexible)) 11324 chanpos = pri_find_empty_chan(pri, 1); 11325 if (chanpos > -1) { 11326 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11327 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11328 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 11329 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 11330 if (crv) 11331 ast_mutex_lock(&crv->lock); 11332 if (!crv || crv->owner) { 11333 pri->pvts[chanpos]->call = NULL; 11334 if (crv) { 11335 if (crv->owner) 11336 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11337 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); 11338 } else 11339 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); 11340 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 11341 if (crv) 11342 ast_mutex_unlock(&crv->lock); 11343 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11344 break; 11345 } 11346 } 11347 pri->pvts[chanpos]->call = e->ring.call; 11348 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 11349 if (pri->pvts[chanpos]->use_callerid) { 11350 ast_shrink_phone_number(plancallingnum); 11351 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 11352 #ifdef PRI_ANI 11353 if (!ast_strlen_zero(e->ring.callingani)) { 11354 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 11355 ast_shrink_phone_number(plancallingani); 11356 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 11357 } else { 11358 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11359 } 11360 #endif 11361 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 11362 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 11363 } else { 11364 pri->pvts[chanpos]->cid_num[0] = '\0'; 11365 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11366 pri->pvts[chanpos]->cid_name[0] = '\0'; 11367 pri->pvts[chanpos]->cid_ton = 0; 11368 } 11369 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 11370 e->ring.redirectingnum, e->ring.callingplanrdnis); 11371 /* If immediate=yes go to s|1 */ 11372 if (pri->pvts[chanpos]->immediate) { 11373 ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); 11374 pri->pvts[chanpos]->exten[0] = 's'; 11375 pri->pvts[chanpos]->exten[1] = '\0'; 11376 } 11377 /* Get called number */ 11378 else if (!ast_strlen_zero(e->ring.callednum)) { 11379 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 11380 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11381 } else if (pri->overlapdial) 11382 pri->pvts[chanpos]->exten[0] = '\0'; 11383 else { 11384 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 11385 pri->pvts[chanpos]->exten[0] = 's'; 11386 pri->pvts[chanpos]->exten[1] = '\0'; 11387 } 11388 /* Set DNID on all incoming calls -- even immediate */ 11389 if (!ast_strlen_zero(e->ring.callednum)) 11390 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11391 /* No number yet, but received "sending complete"? */ 11392 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 11393 ast_verb(3, "Going to extension s|1 because of Complete received\n"); 11394 pri->pvts[chanpos]->exten[0] = 's'; 11395 pri->pvts[chanpos]->exten[1] = '\0'; 11396 } 11397 11398 /* Make sure extension exists (or in overlap dial mode, can exist) */ 11399 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 11400 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11401 /* Setup law */ 11402 int law; 11403 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 11404 /* Set to audio mode at this point */ 11405 law = 1; 11406 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11407 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 11408 } 11409 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 11410 law = DAHDI_LAW_ALAW; 11411 else 11412 law = DAHDI_LAW_MULAW; 11413 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 11414 if (res < 0) 11415 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 11416 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 11417 if (res < 0) 11418 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 11419 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 11420 /* Just announce proceeding */ 11421 pri->pvts[chanpos]->proceeding = 1; 11422 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 11423 } else { 11424 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 11425 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11426 else 11427 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11428 } 11429 /* Get the use_callingpres state */ 11430 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 11431 11432 /* Start PBX */ 11433 if (!e->ring.complete 11434 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 11435 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 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 if (crv) { 11442 /* Set bearer and such */ 11443 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 11444 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11445 pri->pvts[chanpos]->owner = &inuse; 11446 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 11447 } else { 11448 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11449 } 11450 ast_mutex_lock(&pri->lock); 11451 if (c) { 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 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11468 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11469 if (e->ring.redirectingreason >= 0) 11470 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11471 } 11472 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) { 11473 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 11474 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 11475 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11476 } else { 11477 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11478 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11479 if (c) 11480 ast_hangup(c); 11481 else { 11482 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11483 pri->pvts[chanpos]->call = NULL; 11484 } 11485 } 11486 } else { 11487 /* 11488 * Release the PRI lock while we create the channel 11489 * so other threads can send D channel messages. 11490 */ 11491 ast_mutex_unlock(&pri->lock); 11492 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 11493 ast_mutex_lock(&pri->lock); 11494 if (c) { 11495 /* 11496 * It is reasonably safe to set the following 11497 * channel variables while the PRI and DAHDI private 11498 * structures are locked. The PBX has not been 11499 * started yet and it is unlikely that any other task 11500 * will do anything with the channel we have just 11501 * created. 11502 */ 11503 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11504 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11505 } 11506 if (e->ring.ani2 >= 0) { 11507 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11508 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11509 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11510 } 11511 11512 #ifdef SUPPORT_USERUSER 11513 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11514 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11515 } 11516 #endif 11517 11518 if (e->ring.redirectingreason >= 0) 11519 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11520 11521 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11522 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11523 } 11524 if (c && !ast_pbx_start(c)) { 11525 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 11526 plancallingnum, pri->pvts[chanpos]->exten, 11527 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11528 11529 dahdi_enable_ec(pri->pvts[chanpos]); 11530 } else { 11531 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11532 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11533 if (c) { 11534 ast_hangup(c); 11535 } else { 11536 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11537 pri->pvts[chanpos]->call = NULL; 11538 } 11539 } 11540 } 11541 } else { 11542 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 11543 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 11544 pri->pvts[chanpos]->prioffset, pri->span); 11545 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 11546 pri->pvts[chanpos]->call = NULL; 11547 pri->pvts[chanpos]->exten[0] = '\0'; 11548 } 11549 if (crv) 11550 ast_mutex_unlock(&crv->lock); 11551 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11552 } else { 11553 if (e->ring.flexible) 11554 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 11555 else 11556 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 11557 } 11558 break; 11559 case PRI_EVENT_RINGING: 11560 chanpos = pri_find_principle(pri, e->ringing.channel); 11561 if (chanpos < 0) { 11562 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 11563 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11564 } else { 11565 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 11566 if (chanpos < 0) { 11567 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 11568 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11569 } else { 11570 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11571 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11572 dahdi_enable_ec(pri->pvts[chanpos]); 11573 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 11574 pri->pvts[chanpos]->alerting = 1; 11575 } else 11576 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n"); 11577 11578 #ifdef PRI_PROGRESS_MASK 11579 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11580 #else 11581 if (e->ringing.progress == 8) { 11582 #endif 11583 /* Now we can do call progress detection */ 11584 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11585 /* RINGING detection isn't required because we got ALERTING signal */ 11586 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 11587 pri->pvts[chanpos]->dsp_features = 0; 11588 } 11589 } 11590 11591 #ifdef SUPPORT_USERUSER 11592 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 11593 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11594 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11595 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 11596 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11597 } 11598 #endif 11599 11600 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11601 } 11602 } 11603 break; 11604 case PRI_EVENT_PROGRESS: 11605 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 11606 chanpos = pri_find_principle(pri, e->proceeding.channel); 11607 if (chanpos > -1) { 11608 #ifdef PRI_PROGRESS_MASK 11609 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 11610 #else 11611 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 11612 #endif 11613 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11614 11615 if (e->proceeding.cause > -1) { 11616 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); 11617 11618 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 11619 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 11620 if (pri->pvts[chanpos]->owner) { 11621 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 11622 11623 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 11624 f.subclass = AST_CONTROL_BUSY; 11625 } 11626 } 11627 } 11628 11629 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11630 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 11631 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11632 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11633 #ifdef PRI_PROGRESS_MASK 11634 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11635 #else 11636 if (e->proceeding.progress == 8) { 11637 #endif 11638 /* Now we can do call progress detection */ 11639 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11640 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11641 pri->pvts[chanpos]->dsp_features = 0; 11642 } 11643 /* Bring voice path up */ 11644 f.subclass = AST_CONTROL_PROGRESS; 11645 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11646 } 11647 pri->pvts[chanpos]->progress = 1; 11648 pri->pvts[chanpos]->dialing = 0; 11649 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11650 } 11651 } 11652 break; 11653 case PRI_EVENT_PROCEEDING: 11654 chanpos = pri_find_principle(pri, e->proceeding.channel); 11655 if (chanpos > -1) { 11656 if (!pri->pvts[chanpos]->proceeding) { 11657 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11658 11659 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11660 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 11661 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11662 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11663 #ifdef PRI_PROGRESS_MASK 11664 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11665 #else 11666 if (e->proceeding.progress == 8) { 11667 #endif 11668 /* Now we can do call progress detection */ 11669 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11670 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11671 pri->pvts[chanpos]->dsp_features = 0; 11672 } 11673 /* Bring voice path up */ 11674 f.subclass = AST_CONTROL_PROGRESS; 11675 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11676 } 11677 pri->pvts[chanpos]->proceeding = 1; 11678 pri->pvts[chanpos]->dialing = 0; 11679 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11680 } 11681 } 11682 break; 11683 case PRI_EVENT_FACNAME: 11684 chanpos = pri_find_principle(pri, e->facname.channel); 11685 if (chanpos < 0) { 11686 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 11687 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11688 } else { 11689 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 11690 if (chanpos < 0) { 11691 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 11692 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11693 } else { 11694 /* Re-use *69 field for PRI */ 11695 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11696 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 11697 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 11698 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 11699 dahdi_enable_ec(pri->pvts[chanpos]); 11700 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11701 } 11702 } 11703 break; 11704 case PRI_EVENT_ANSWER: 11705 chanpos = pri_find_principle(pri, e->answer.channel); 11706 if (chanpos < 0) { 11707 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 11708 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11709 } else { 11710 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 11711 if (chanpos < 0) { 11712 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 11713 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11714 } else { 11715 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11716 /* Now we can do call progress detection */ 11717 11718 /* We changed this so it turns on the DSP no matter what... progress or no progress. 11719 * By this time, we need DTMF detection and other features that were previously disabled 11720 * -- Matt F */ 11721 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11722 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11723 pri->pvts[chanpos]->dsp_features = 0; 11724 } 11725 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 11726 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); 11727 x = DAHDI_START; 11728 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11729 if (res < 0) { 11730 if (errno != EINPROGRESS) { 11731 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 11732 } 11733 } 11734 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11735 pri->pvts[chanpos]->dialing = 1; 11736 /* Send any "w" waited stuff */ 11737 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 11738 if (res < 0) { 11739 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 11740 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11741 } else 11742 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 11743 11744 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11745 } else if (pri->pvts[chanpos]->confirmanswer) { 11746 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 11747 } else { 11748 pri->pvts[chanpos]->dialing = 0; 11749 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 11750 /* Enable echo cancellation if it's not on already */ 11751 dahdi_enable_ec(pri->pvts[chanpos]); 11752 } 11753 11754 #ifdef SUPPORT_USERUSER 11755 if (!ast_strlen_zero(e->answer.useruserinfo)) { 11756 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11757 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11758 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 11759 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11760 } 11761 #endif 11762 11763 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11764 } 11765 } 11766 break; 11767 case PRI_EVENT_HANGUP: 11768 chanpos = pri_find_principle(pri, e->hangup.channel); 11769 if (chanpos < 0) { 11770 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 11771 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11772 } else { 11773 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11774 if (chanpos > -1) { 11775 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11776 if (!pri->pvts[chanpos]->alreadyhungup) { 11777 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 11778 pri->pvts[chanpos]->alreadyhungup = 1; 11779 if (pri->pvts[chanpos]->realcall) 11780 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11781 else if (pri->pvts[chanpos]->owner) { 11782 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 11783 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11784 switch (pri->pvts[chanpos]->owner->_state) { 11785 case AST_STATE_BUSY: 11786 case AST_STATE_UP: 11787 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11788 break; 11789 default: 11790 switch (e->hangup.cause) { 11791 case PRI_CAUSE_USER_BUSY: 11792 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11793 break; 11794 case PRI_CAUSE_CALL_REJECTED: 11795 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11796 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11797 case PRI_CAUSE_SWITCH_CONGESTION: 11798 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11799 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11800 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11801 break; 11802 default: 11803 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11804 } 11805 break; 11806 } 11807 } 11808 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", 11809 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 11810 } else { 11811 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11812 pri->pvts[chanpos]->call = NULL; 11813 } 11814 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11815 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 11816 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11817 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11818 pri->pvts[chanpos]->resetting = 1; 11819 } 11820 if (e->hangup.aoc_units > -1) 11821 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11822 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11823 11824 #ifdef SUPPORT_USERUSER 11825 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 11826 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11827 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11828 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11829 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11830 } 11831 #endif 11832 11833 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11834 } else { 11835 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 11836 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11837 } 11838 } 11839 break; 11840 #ifndef PRI_EVENT_HANGUP_REQ 11841 #error please update libpri 11842 #endif 11843 case PRI_EVENT_HANGUP_REQ: 11844 chanpos = pri_find_principle(pri, e->hangup.channel); 11845 if (chanpos < 0) { 11846 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 11847 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11848 } else { 11849 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11850 if (chanpos > -1) { 11851 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11852 if (pri->pvts[chanpos]->realcall) 11853 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11854 else if (pri->pvts[chanpos]->owner) { 11855 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11856 switch (pri->pvts[chanpos]->owner->_state) { 11857 case AST_STATE_BUSY: 11858 case AST_STATE_UP: 11859 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11860 break; 11861 default: 11862 switch (e->hangup.cause) { 11863 case PRI_CAUSE_USER_BUSY: 11864 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11865 break; 11866 case PRI_CAUSE_CALL_REJECTED: 11867 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11868 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11869 case PRI_CAUSE_SWITCH_CONGESTION: 11870 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11871 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11872 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11873 break; 11874 default: 11875 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11876 } 11877 break; 11878 } 11879 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); 11880 if (e->hangup.aoc_units > -1) 11881 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11882 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11883 } else { 11884 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11885 pri->pvts[chanpos]->call = NULL; 11886 } 11887 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11888 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11889 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11890 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11891 pri->pvts[chanpos]->resetting = 1; 11892 } 11893 11894 #ifdef SUPPORT_USERUSER 11895 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11896 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11897 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11898 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11899 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11900 } 11901 #endif 11902 11903 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11904 } else { 11905 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); 11906 } 11907 } 11908 break; 11909 case PRI_EVENT_HANGUP_ACK: 11910 chanpos = pri_find_principle(pri, e->hangup.channel); 11911 if (chanpos < 0) { 11912 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11913 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11914 } else { 11915 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11916 if (chanpos > -1) { 11917 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11918 pri->pvts[chanpos]->call = NULL; 11919 pri->pvts[chanpos]->resetting = 0; 11920 if (pri->pvts[chanpos]->owner) { 11921 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11922 } 11923 11924 #ifdef SUPPORT_USERUSER 11925 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11926 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11927 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11928 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11929 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11930 } 11931 #endif 11932 11933 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11934 } 11935 } 11936 break; 11937 case PRI_EVENT_CONFIG_ERR: 11938 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11939 break; 11940 case PRI_EVENT_RESTART_ACK: 11941 chanpos = pri_find_principle(pri, e->restartack.channel); 11942 if (chanpos < 0) { 11943 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11944 channel number, so we have to figure it out... This must be why 11945 everybody resets exactly a channel at a time. */ 11946 for (x = 0; x < pri->numchans; x++) { 11947 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11948 chanpos = x; 11949 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11950 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11951 pri->pvts[chanpos]->prioffset, pri->span); 11952 if (pri->pvts[chanpos]->realcall) 11953 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11954 else if (pri->pvts[chanpos]->owner) { 11955 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11956 pri->pvts[chanpos]->prioffset, pri->span); 11957 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11958 } 11959 pri->pvts[chanpos]->resetting = 0; 11960 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11961 pri->pvts[chanpos]->prioffset, pri->span); 11962 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11963 if (pri->resetting) 11964 pri_check_restart(pri); 11965 break; 11966 } 11967 } 11968 if (chanpos < 0) { 11969 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11970 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11971 } 11972 } else { 11973 if (pri->pvts[chanpos]) { 11974 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11975 if (pri->pvts[chanpos]->realcall) 11976 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11977 else if (pri->pvts[chanpos]->owner) { 11978 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11979 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11980 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11981 } 11982 pri->pvts[chanpos]->resetting = 0; 11983 pri->pvts[chanpos]->inservice = 1; 11984 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11985 pri->pvts[chanpos]->prioffset, pri->span); 11986 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11987 if (pri->resetting) 11988 pri_check_restart(pri); 11989 } 11990 } 11991 break; 11992 case PRI_EVENT_SETUP_ACK: 11993 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11994 if (chanpos < 0) { 11995 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11996 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11997 } else { 11998 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11999 if (chanpos > -1) { 12000 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12001 pri->pvts[chanpos]->setup_ack = 1; 12002 /* Send any queued digits */ 12003 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 12004 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 12005 pri_information(pri->pri, pri->pvts[chanpos]->call, 12006 pri->pvts[chanpos]->dialdest[x]); 12007 } 12008 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12009 } else 12010 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 12011 } 12012 break; 12013 case PRI_EVENT_NOTIFY: 12014 chanpos = pri_find_principle(pri, e->notify.channel); 12015 if (chanpos < 0) { 12016 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 12017 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 12018 } else { 12019 struct ast_frame f = { AST_FRAME_CONTROL, }; 12020 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12021 switch (e->notify.info) { 12022 case PRI_NOTIFY_REMOTE_HOLD: 12023 f.subclass = AST_CONTROL_HOLD; 12024 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12025 break; 12026 case PRI_NOTIFY_REMOTE_RETRIEVAL: 12027 f.subclass = AST_CONTROL_UNHOLD; 12028 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12029 break; 12030 } 12031 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12032 } 12033 break; 12034 default: 12035 ast_debug(1, "Event: %d\n", e->e); 12036 } 12037 } 12038 ast_mutex_unlock(&pri->lock); 12039 } 12040 /* Never reached */ 12041 return NULL; 12042 }
Definition at line 10573 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 3353 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().
03354 { 03355 int oldslot = -1; 03356 struct pri *old; 03357 int newslot = -1; 03358 int x; 03359 old = pri->pri; 03360 for (x = 0; x < NUM_DCHANS; x++) { 03361 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03362 newslot = x; 03363 if (pri->dchans[x] == old) { 03364 oldslot = x; 03365 } 03366 } 03367 if (newslot < 0) { 03368 newslot = 0; 03369 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03370 pri->dchannels[newslot]); 03371 } 03372 if (old && (oldslot != newslot)) 03373 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03374 pri->dchannels[oldslot], pri->dchannels[newslot]); 03375 pri->pri = pri->dchans[newslot]; 03376 return 0; 03377 }
| static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
| int | backwards | |||
| ) | [static] |
Definition at line 9472 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().
09473 { 09474 int x; 09475 if (backwards) 09476 x = pri->numchans; 09477 else 09478 x = 0; 09479 for (;;) { 09480 if (backwards && (x < 0)) 09481 break; 09482 if (!backwards && (x >= pri->numchans)) 09483 break; 09484 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09485 ast_debug(1, "Found empty available channel %d/%d\n", 09486 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09487 return x; 09488 } 09489 if (backwards) 09490 x--; 09491 else 09492 x++; 09493 } 09494 return -1; 09495 }
| static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
| int | channel | |||
| ) | [static] |
Definition at line 10586 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().
10587 { 10588 int x; 10589 int span = PRI_SPAN(channel); 10590 int spanfd; 10591 struct dahdi_params param; 10592 int principle = -1; 10593 int explicit = PRI_EXPLICIT(channel); 10594 channel = PRI_CHANNEL(channel); 10595 10596 if (!explicit) { 10597 spanfd = pri_active_dchan_fd(pri); 10598 memset(¶m, 0, sizeof(param)); 10599 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 10600 return -1; 10601 span = pris[param.spanno - 1].prilogicalspan; 10602 } 10603 10604 for (x = 0; x < pri->numchans; x++) { 10605 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 10606 principle = x; 10607 break; 10608 } 10609 } 10610 10611 return principle; 10612 }
| static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
| int | principle, | |||
| q931_call * | c | |||
| ) | [static] |
Definition at line 10614 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().
10615 { 10616 int x; 10617 struct dahdi_pvt *crv; 10618 if (!c) { 10619 if (principle < 0) 10620 return -1; 10621 return principle; 10622 } 10623 if ((principle > -1) && 10624 (principle < pri->numchans) && 10625 (pri->pvts[principle]) && 10626 (pri->pvts[principle]->call == c)) 10627 return principle; 10628 /* First, check for other bearers */ 10629 for (x = 0; x < pri->numchans; x++) { 10630 if (!pri->pvts[x]) 10631 continue; 10632 if (pri->pvts[x]->call == c) { 10633 /* Found our call */ 10634 if (principle != x) { 10635 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 10636 10637 ast_verb(3, "Moving call from channel %d to channel %d\n", 10638 old->channel, new->channel); 10639 if (new->owner) { 10640 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 10641 old->channel, new->channel, new->channel); 10642 return -1; 10643 } 10644 /* Fix it all up now */ 10645 new->owner = old->owner; 10646 old->owner = NULL; 10647 if (new->owner) { 10648 ast_string_field_build(new->owner, name, 10649 "DAHDI/%d:%d-%d", pri->trunkgroup, 10650 new->channel, 1); 10651 new->owner->tech_pvt = new; 10652 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd); 10653 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 10654 old->subs[SUB_REAL].owner = NULL; 10655 } else 10656 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); 10657 new->call = old->call; 10658 old->call = NULL; 10659 10660 /* Copy any DSP that may be present */ 10661 new->dsp = old->dsp; 10662 new->dsp_features = old->dsp_features; 10663 old->dsp = NULL; 10664 old->dsp_features = 0; 10665 } 10666 return principle; 10667 } 10668 } 10669 /* Now check for a CRV with no bearer */ 10670 crv = pri->crvs; 10671 while (crv) { 10672 if (crv->call == c) { 10673 /* This is our match... Perform some basic checks */ 10674 if (crv->bearer) 10675 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 10676 else if (pri->pvts[principle]->owner) 10677 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 10678 else { 10679 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 10680 wakeup the potential sleeper */ 10681 dahdi_close_sub(crv, SUB_REAL); 10682 pri->pvts[principle]->call = crv->call; 10683 pri_assign_bearer(crv, pri, pri->pvts[principle]); 10684 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n", 10685 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 10686 pri->trunkgroup, crv->channel); 10687 wakeup_sub(crv, SUB_REAL, pri); 10688 } 10689 return principle; 10690 } 10691 crv = crv->next; 10692 } 10693 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 10694 return -1; 10695 }
Definition at line 1228 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, and dahdi_pri::master.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_send_keypad_facility_exec(), dahdi_write(), and ss_thread().
01229 { 01230 int res; 01231 /* Grab the lock first */ 01232 do { 01233 res = ast_mutex_trylock(&pri->lock); 01234 if (res) { 01235 DEADLOCK_AVOIDANCE(&pvt->lock); 01236 } 01237 } while (res); 01238 /* Then break the poll */ 01239 if (pri->master != AST_PTHREADT_NULL) 01240 pthread_kill(pri->master, SIGURG); 01241 return 0; 01242 }
Definition at line 10845 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().
10846 { 10847 int x; 10848 int redo; 10849 ast_mutex_unlock(&pri->lock); 10850 ast_mutex_lock(&p->lock); 10851 do { 10852 redo = 0; 10853 for (x = 0; x < 3; x++) { 10854 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) { 10855 redo++; 10856 DEADLOCK_AVOIDANCE(&p->lock); 10857 } 10858 if (p->subs[x].owner) { 10859 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED); 10860 ast_channel_unlock(p->subs[x].owner); 10861 } 10862 } 10863 } while (redo); 10864 ast_mutex_unlock(&p->lock); 10865 ast_mutex_lock(&pri->lock); 10866 return 0; 10867 }
| static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3301 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.
Referenced by mkintf(), and pri_dchannel().
03302 { 03303 int x; 03304 for (x = 0; x < NUM_DCHANS; x++) { 03305 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03306 return 1; 03307 } 03308 return 0; 03309 }
| static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3324 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 456 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_pri::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_send_keypad_facility_exec(), dahdi_write(), and ss_thread().
00457 { 00458 ast_mutex_unlock(&pri->lock); 00459 }
| static int pri_resolve_span | ( | int * | span, | |
| int | channel, | |||
| int | offset, | |||
| struct dahdi_spaninfo * | si | |||
| ) | [static] |
Definition at line 8587 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().
08588 { 08589 int x; 08590 int trunkgroup; 08591 /* Get appropriate trunk group if there is one */ 08592 trunkgroup = pris[*span].mastertrunkgroup; 08593 if (trunkgroup) { 08594 /* Select a specific trunk group */ 08595 for (x = 0; x < NUM_SPANS; x++) { 08596 if (pris[x].trunkgroup == trunkgroup) { 08597 *span = x; 08598 return 0; 08599 } 08600 } 08601 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08602 *span = -1; 08603 } else { 08604 if (pris[*span].trunkgroup) { 08605 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08606 *span = -1; 08607 } else if (pris[*span].mastertrunkgroup) { 08608 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08609 *span = -1; 08610 } else { 08611 if (si->totalchans == 31) { 08612 /* E1 */ 08613 pris[*span].dchannels[0] = 16 + offset; 08614 } else if (si->totalchans == 24) { 08615 /* T1 or J1 */ 08616 pris[*span].dchannels[0] = 24 + offset; 08617 } else if (si->totalchans == 3) { 08618 /* BRI */ 08619 pris[*span].dchannels[0] = 3 + offset; 08620 } else { 08621 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); 08622 *span = -1; 08623 return 0; 08624 } 08625 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08626 pris[*span].offset = offset; 08627 pris[*span].span = *span + 1; 08628 } 08629 } 08630 return 0; 08631 }
| static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
| const char * | cat, | |||
| struct ast_variable * | v, | |||
| int | reload, | |||
| int | options | |||
| ) | [static] |
Definition at line 14299 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().
14300 { 14301 struct dahdi_pvt *tmp; 14302 int y; 14303 int found_pseudo = 0; 14304 char dahdichan[MAX_CHANLIST_LEN] = {}; 14305 14306 for (; v; v = v->next) { 14307 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 14308 continue; 14309 14310 /* must have parkinglot in confp before build_channels is called */ 14311 if (!strcasecmp(v->name, "parkinglot")) { 14312 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 14313 } 14314 14315 /* Create the interface list */ 14316 if (!strcasecmp(v->name, "channel") 14317 #ifdef HAVE_PRI 14318 || !strcasecmp(v->name, "crv") 14319 #endif 14320 ) { 14321 int iscrv; 14322 if (options & PROC_DAHDI_OPT_NOCHAN) { 14323 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 14324 continue; 14325 } 14326 iscrv = !strcasecmp(v->name, "crv"); 14327 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 14328 return -1; 14329 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 14330 } else if (!strcasecmp(v->name, "buffers")) { 14331 int res; 14332 char policy[21] = ""; 14333 14334 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 14335 if (res != 2) { 14336 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 14337 confp->chan.buf_no = numbufs; 14338 continue; 14339 } 14340 if (confp->chan.buf_no < 0) 14341 confp->chan.buf_no = numbufs; 14342 if (!strcasecmp(policy, "full")) { 14343 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 14344 } else if (!strcasecmp(policy, "immediate")) { 14345 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 14346 } else { 14347 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 14348 } 14349 } else if (!strcasecmp(v->name, "dahdichan")) { 14350 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 14351 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 14352 usedistinctiveringdetection = ast_true(v->value); 14353 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 14354 distinctiveringaftercid = ast_true(v->value); 14355 } else if (!strcasecmp(v->name, "dring1context")) { 14356 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 14357 } else if (!strcasecmp(v->name, "dring2context")) { 14358 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 14359 } else if (!strcasecmp(v->name, "dring3context")) { 14360 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 14361 } else if (!strcasecmp(v->name, "dring1range")) { 14362 confp->chan.drings.ringnum[0].range = atoi(v->value); 14363 } else if (!strcasecmp(v->name, "dring2range")) { 14364 confp->chan.drings.ringnum[1].range = atoi(v->value); 14365 } else if (!strcasecmp(v->name, "dring3range")) { 14366 confp->chan.drings.ringnum[2].range = atoi(v->value); 14367 } else if (!strcasecmp(v->name, "dring1")) { 14368 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]); 14369 } else if (!strcasecmp(v->name, "dring2")) { 14370 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]); 14371 } else if (!strcasecmp(v->name, "dring3")) { 14372 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]); 14373 } else if (!strcasecmp(v->name, "usecallerid")) { 14374 confp->chan.use_callerid = ast_true(v->value); 14375 } else if (!strcasecmp(v->name, "cidsignalling")) { 14376 if (!strcasecmp(v->value, "bell")) 14377 confp->chan.cid_signalling = CID_SIG_BELL; 14378 else if (!strcasecmp(v->value, "v23")) 14379 confp->chan.cid_signalling = CID_SIG_V23; 14380 else if (!strcasecmp(v->value, "dtmf")) 14381 confp->chan.cid_signalling = CID_SIG_DTMF; 14382 else if (!strcasecmp(v->value, "smdi")) 14383 confp->chan.cid_signalling = CID_SIG_SMDI; 14384 else if (!strcasecmp(v->value, "v23_jp")) 14385 confp->chan.cid_signalling = CID_SIG_V23_JP; 14386 else if (ast_true(v->value)) 14387 confp->chan.cid_signalling = CID_SIG_BELL; 14388 } else if (!strcasecmp(v->name, "cidstart")) { 14389 if (!strcasecmp(v->value, "ring")) 14390 confp->chan.cid_start = CID_START_RING; 14391 else if (!strcasecmp(v->value, "polarity_in")) 14392 confp->chan.cid_start = CID_START_POLARITY_IN; 14393 else if (!strcasecmp(v->value, "polarity")) 14394 confp->chan.cid_start = CID_START_POLARITY; 14395 else if (ast_true(v->value)) 14396 confp->chan.cid_start = CID_START_RING; 14397 } else if (!strcasecmp(v->name, "threewaycalling")) { 14398 confp->chan.threewaycalling = ast_true(v->value); 14399 } else if (!strcasecmp(v->name, "cancallforward")) { 14400 confp->chan.cancallforward = ast_true(v->value); 14401 } else if (!strcasecmp(v->name, "relaxdtmf")) { 14402 if (ast_true(v->value)) 14403 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 14404 else 14405 confp->chan.dtmfrelax = 0; 14406 } else if (!strcasecmp(v->name, "mailbox")) { 14407 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 14408 } else if (!strcasecmp(v->name, "hasvoicemail")) { 14409 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 14410 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 14411 } 14412 } else if (!strcasecmp(v->name, "adsi")) { 14413 confp->chan.adsi = ast_true(v->value); 14414 } else if (!strcasecmp(v->name, "usesmdi")) { 14415 confp->chan.use_smdi = ast_true(v->value); 14416 } else if (!strcasecmp(v->name, "smdiport")) { 14417 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 14418 } else if (!strcasecmp(v->name, "transfer")) { 14419 confp->chan.transfer = ast_true(v->value); 14420 } else if (!strcasecmp(v->name, "canpark")) { 14421 confp->chan.canpark = ast_true(v->value); 14422 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 14423 confp->chan.echocanbridged = ast_true(v->value); 14424 } else if (!strcasecmp(v->name, "busydetect")) { 14425 confp->chan.busydetect = ast_true(v->value); 14426 } else if (!strcasecmp(v->name, "busycount")) { 14427 confp->chan.busycount = atoi(v->value); 14428 } else if (!strcasecmp(v->name, "busypattern")) { 14429 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) { 14430 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 14431 } 14432 } else if (!strcasecmp(v->name, "callprogress")) { 14433 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 14434 if (ast_true(v->value)) 14435 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 14436 } else if (!strcasecmp(v->name, "faxdetect")) { 14437 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 14438 if (!strcasecmp(v->value, "incoming")) { 14439 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 14440 } else if (!strcasecmp(v->value, "outgoing")) { 14441 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 14442 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 14443 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 14444 } else if (!strcasecmp(v->name, "echocancel")) { 14445 process_echocancel(confp, v->value, v->lineno); 14446 } else if (!strcasecmp(v->name, "echotraining")) { 14447 if (sscanf(v->value, "%30d", &y) == 1) { 14448 if ((y < 10) || (y > 4000)) { 14449 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 14450 } else { 14451 confp->chan.echotraining = y; 14452 } 14453 } else if (ast_true(v->value)) { 14454 confp->chan.echotraining = 400; 14455 } else 14456 confp->chan.echotraining = 0; 14457 } else if (!strcasecmp(v->name, "hidecallerid")) { 14458 confp->chan.hidecallerid = ast_true(v->value); 14459 } else if (!strcasecmp(v->name, "hidecalleridname")) { 14460 confp->chan.hidecalleridname = ast_true(v->value); 14461 } else if (!strcasecmp(v->name, "pulsedial")) { 14462 confp->chan.pulse = ast_true(v->value); 14463 } else if (!strcasecmp(v->name, "callreturn")) { 14464 confp->chan.callreturn = ast_true(v->value); 14465 } else if (!strcasecmp(v->name, "callwaiting")) { 14466 confp->chan.callwaiting = ast_true(v->value); 14467 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 14468 confp->chan.callwaitingcallerid = ast_true(v->value); 14469 } else if (!strcasecmp(v->name, "context")) { 14470 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 14471 } else if (!strcasecmp(v->name, "language")) { 14472 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 14473 } else if (!strcasecmp(v->name, "progzone")) { 14474 ast_copy_string(progzone, v->value, sizeof(progzone)); 14475 } else if (!strcasecmp(v->name, "mohinterpret") 14476 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 14477 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 14478 } else if (!strcasecmp(v->name, "mohsuggest")) { 14479 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 14480 } else if (!strcasecmp(v->name, "parkinglot")) { 14481 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 14482 } else if (!strcasecmp(v->name, "stripmsd")) { 14483 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 14484 confp->chan.stripmsd = atoi(v->value); 14485 } else if (!strcasecmp(v->name, "jitterbuffers")) { 14486 numbufs = atoi(v->value); 14487 } else if (!strcasecmp(v->name, "group")) { 14488 confp->chan.group = ast_get_group(v->value); 14489 } else if (!strcasecmp(v->name, "callgroup")) { 14490 if (!strcasecmp(v->value, "none")) 14491 confp->chan.callgroup = 0; 14492 else 14493 confp->chan.callgroup = ast_get_group(v->value); 14494 } else if (!strcasecmp(v->name, "pickupgroup")) { 14495 if (!strcasecmp(v->value, "none")) 14496 confp->chan.pickupgroup = 0; 14497 else 14498 confp->chan.pickupgroup = ast_get_group(v->value); 14499 } else if (!strcasecmp(v->name, "setvar")) { 14500 char *varname = ast_strdupa(v->value), *varval = NULL; 14501 struct ast_variable *tmpvar; 14502 if (varname && (varval = strchr(varname, '='))) { 14503 *varval++ = '\0'; 14504 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 14505 tmpvar->next = confp->chan.vars; 14506 confp->chan.vars = tmpvar; 14507 } 14508 } 14509 } else if (!strcasecmp(v->name, "immediate")) { 14510 confp->chan.immediate = ast_true(v->value); 14511 } else if (!strcasecmp(v->name, "transfertobusy")) { 14512 confp->chan.transfertobusy = ast_true(v->value); 14513 } else if (!strcasecmp(v->name, "mwimonitor")) { 14514 confp->chan.mwimonitor_neon = 0; 14515 confp->chan.mwimonitor_fsk = 0; 14516 confp->chan.mwimonitor_rpas = 0; 14517 if (strcasestr(v->value, "fsk")) { 14518 confp->chan.mwimonitor_fsk = 1; 14519 } 14520 if (strcasestr(v->value, "rpas")) { 14521 confp->chan.mwimonitor_rpas = 1; 14522 } 14523 if (strcasestr(v->value, "neon")) { 14524 confp->chan.mwimonitor_neon = 1; 14525 } 14526 /* If set to true or yes, assume that simple fsk is desired */ 14527 if (ast_true(v->value)) { 14528 confp->chan.mwimonitor_fsk = 1; 14529 } 14530 } else if (!strcasecmp(v->name, "cid_rxgain")) { 14531 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 14532 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 14533 } 14534 } else if (!strcasecmp(v->name, "rxgain")) { 14535 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 14536 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 14537 } 14538 } else if (!strcasecmp(v->name, "txgain")) { 14539 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 14540 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 14541 } 14542 } else if (!strcasecmp(v->name, "tonezone")) { 14543 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 14544 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 14545 } 14546 } else if (!strcasecmp(v->name, "callerid")) { 14547 if (!strcasecmp(v->value, "asreceived")) { 14548 confp->chan.cid_num[0] = '\0'; 14549 confp->chan.cid_name[0] = '\0'; 14550 } else { 14551 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 14552 } 14553 } else if (!strcasecmp(v->name, "fullname")) { 14554 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 14555 } else if (!strcasecmp(v->name, "cid_number")) { 14556 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 14557 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 14558 confp->chan.dahditrcallerid = ast_true(v->value); 14559 } else if (!strcasecmp(v->name, "restrictcid")) { 14560 confp->chan.restrictcid = ast_true(v->value); 14561 } else if (!strcasecmp(v->name, "usecallingpres")) { 14562 confp->chan.use_callingpres = ast_true(v->value); 14563 } else if (!strcasecmp(v->name, "accountcode")) { 14564 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 14565 } else if (!strcasecmp(v->name, "amaflags")) { 14566 y = ast_cdr_amaflags2int(v->value); 14567 if (y < 0) 14568 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 14569 else 14570 confp->chan.amaflags = y; 14571 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 14572 confp->chan.polarityonanswerdelay = atoi(v->value); 14573 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 14574 confp->chan.answeronpolarityswitch = ast_true(v->value); 14575 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 14576 confp->chan.hanguponpolarityswitch = ast_true(v->value); 14577 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 14578 confp->chan.sendcalleridafter = atoi(v->value); 14579 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 14580 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 14581 } else if (!strcasecmp(v->name, "mwisendtype")) { 14582 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 14583 mwisend_rpas = 1; 14584 } else { 14585 mwisend_rpas = 0; 14586 } 14587 } else if (reload != 1) { 14588 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 14589 int orig_radio = confp->chan.radio; 14590 int orig_outsigmod = confp->chan.outsigmod; 14591 int orig_auto = confp->is_sig_auto; 14592 14593 confp->chan.radio = 0; 14594 confp->chan.outsigmod = -1; 14595 confp->is_sig_auto = 0; 14596 if (!strcasecmp(v->value, "em")) { 14597 confp->chan.sig = SIG_EM; 14598 } else if (!strcasecmp(v->value, "em_e1")) { 14599 confp->chan.sig = SIG_EM_E1; 14600 } else if (!strcasecmp(v->value, "em_w")) { 14601 confp->chan.sig = SIG_EMWINK; 14602 } else if (!strcasecmp(v->value, "fxs_ls")) { 14603 confp->chan.sig = SIG_FXSLS; 14604 } else if (!strcasecmp(v->value, "fxs_gs")) { 14605 confp->chan.sig = SIG_FXSGS; 14606 } else if (!strcasecmp(v->value, "fxs_ks")) { 14607 confp->chan.sig = SIG_FXSKS; 14608 } else if (!strcasecmp(v->value, "fxo_ls")) { 14609 confp->chan.sig = SIG_FXOLS; 14610 } else if (!strcasecmp(v->value, "fxo_gs")) { 14611 confp->chan.sig = SIG_FXOGS; 14612 } else if (!strcasecmp(v->value, "fxo_ks")) { 14613 confp->chan.sig = SIG_FXOKS; 14614 } else if (!strcasecmp(v->value, "fxs_rx")) { 14615 confp->chan.sig = SIG_FXSKS; 14616 confp->chan.radio = 1; 14617 } else if (!strcasecmp(v->value, "fxo_rx")) { 14618 confp->chan.sig = SIG_FXOLS; 14619 confp->chan.radio = 1; 14620 } else if (!strcasecmp(v->value, "fxs_tx")) { 14621 confp->chan.sig = SIG_FXSLS; 14622 confp->chan.radio = 1; 14623 } else if (!strcasecmp(v->value, "fxo_tx")) { 14624 confp->chan.sig = SIG_FXOGS; 14625 confp->chan.radio = 1; 14626 } else if (!strcasecmp(v->value, "em_rx")) { 14627 confp->chan.sig = SIG_EM; 14628 confp->chan.radio = 1; 14629 } else if (!strcasecmp(v->value, "em_tx")) { 14630 confp->chan.sig = SIG_EM; 14631 confp->chan.radio = 1; 14632 } else if (!strcasecmp(v->value, "em_rxtx")) { 14633 confp->chan.sig = SIG_EM; 14634 confp->chan.radio = 2; 14635 } else if (!strcasecmp(v->value, "em_txrx")) { 14636 confp->chan.sig = SIG_EM; 14637 confp->chan.radio = 2; 14638 } else if (!strcasecmp(v->value, "sf")) { 14639 confp->chan.sig = SIG_SF; 14640 } else if (!strcasecmp(v->value, "sf_w")) { 14641 confp->chan.sig = SIG_SFWINK; 14642 } else if (!strcasecmp(v->value, "sf_featd")) { 14643 confp->chan.sig = SIG_FEATD; 14644 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14645 confp->chan.sig = SIG_FEATDMF; 14646 } else if (!strcasecmp(v->value, "sf_featb")) { 14647 confp->chan.sig = SIG_SF_FEATB; 14648 } else if (!strcasecmp(v->value, "sf")) { 14649 confp->chan.sig = SIG_SF; 14650 } else if (!strcasecmp(v->value, "sf_rx")) { 14651 confp->chan.sig = SIG_SF; 14652 confp->chan.radio = 1; 14653 } else if (!strcasecmp(v->value, "sf_tx")) { 14654 confp->chan.sig = SIG_SF; 14655 confp->chan.radio = 1; 14656 } else if (!strcasecmp(v->value, "sf_rxtx")) { 14657 confp->chan.sig = SIG_SF; 14658 confp->chan.radio = 2; 14659 } else if (!strcasecmp(v->value, "sf_txrx")) { 14660 confp->chan.sig = SIG_SF; 14661 confp->chan.radio = 2; 14662 } else if (!strcasecmp(v->value, "featd")) { 14663 confp->chan.sig = SIG_FEATD; 14664 } else if (!strcasecmp(v->value, "featdmf")) { 14665 confp->chan.sig = SIG_FEATDMF; 14666 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14667 confp->chan.sig = SIG_FEATDMF_TA; 14668 } else if (!strcasecmp(v->value, "e911")) { 14669 confp->chan.sig = SIG_E911; 14670 } else if (!strcasecmp(v->value, "fgccama")) { 14671 confp->chan.sig = SIG_FGC_CAMA; 14672 } else if (!strcasecmp(v->value, "fgccamamf")) { 14673 confp->chan.sig = SIG_FGC_CAMAMF; 14674 } else if (!strcasecmp(v->value, "featb")) { 14675 confp->chan.sig = SIG_FEATB; 14676 #ifdef HAVE_PRI 14677 } else if (!strcasecmp(v->value, "pri_net")) { 14678 confp->chan.sig = SIG_PRI; 14679 confp->pri.nodetype = PRI_NETWORK; 14680 } else if (!strcasecmp(v->value, "pri_cpe")) { 14681 confp->chan.sig = SIG_PRI; 14682 confp->pri.nodetype = PRI_CPE; 14683 } else if (!strcasecmp(v->value, "bri_cpe")) { 14684 confp->chan.sig = SIG_BRI; 14685 confp->pri.nodetype = PRI_CPE; 14686 } else if (!strcasecmp(v->value, "bri_net")) { 14687 confp->chan.sig = SIG_BRI; 14688 confp->pri.nodetype = PRI_NETWORK; 14689 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 14690 confp->chan.sig = SIG_BRI_PTMP; 14691 confp->pri.nodetype = PRI_CPE; 14692 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 14693 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 14694 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 14695 confp->chan.sig = SIG_GR303FXOKS; 14696 confp->pri.nodetype = PRI_NETWORK; 14697 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 14698 confp->chan.sig = SIG_GR303FXSKS; 14699 confp->pri.nodetype = PRI_CPE; 14700 #endif 14701 #ifdef HAVE_SS7 14702 } else if (!strcasecmp(v->value, "ss7")) { 14703 confp->chan.sig = SIG_SS7; 14704 #endif 14705 } else if (!strcasecmp(v->value, "auto")) { 14706 confp->is_sig_auto = 1; 14707 } else { 14708 confp->chan.outsigmod = orig_outsigmod; 14709 confp->chan.radio = orig_radio; 14710 confp->is_sig_auto = orig_auto; 14711 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14712 } 14713 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 14714 if (!strcasecmp(v->value, "em")) { 14715 confp->chan.outsigmod = SIG_EM; 14716 } else if (!strcasecmp(v->value, "em_e1")) { 14717 confp->chan.outsigmod = SIG_EM_E1; 14718 } else if (!strcasecmp(v->value, "em_w")) { 14719 confp->chan.outsigmod = SIG_EMWINK; 14720 } else if (!strcasecmp(v->value, "sf")) { 14721 confp->chan.outsigmod = SIG_SF; 14722 } else if (!strcasecmp(v->value, "sf_w")) { 14723 confp->chan.outsigmod = SIG_SFWINK; 14724 } else if (!strcasecmp(v->value, "sf_featd")) { 14725 confp->chan.outsigmod = SIG_FEATD; 14726 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14727 confp->chan.outsigmod = SIG_FEATDMF; 14728 } else if (!strcasecmp(v->value, "sf_featb")) { 14729 confp->chan.outsigmod = SIG_SF_FEATB; 14730 } else if (!strcasecmp(v->value, "sf")) { 14731 confp->chan.outsigmod = SIG_SF; 14732 } else if (!strcasecmp(v->value, "featd")) { 14733 confp->chan.outsigmod = SIG_FEATD; 14734 } else if (!strcasecmp(v->value, "featdmf")) { 14735 confp->chan.outsigmod = SIG_FEATDMF; 14736 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14737 confp->chan.outsigmod = SIG_FEATDMF_TA; 14738 } else if (!strcasecmp(v->value, "e911")) { 14739 confp->chan.outsigmod = SIG_E911; 14740 } else if (!strcasecmp(v->value, "fgccama")) { 14741 confp->chan.outsigmod = SIG_FGC_CAMA; 14742 } else if (!strcasecmp(v->value, "fgccamamf")) { 14743 confp->chan.outsigmod = SIG_FGC_CAMAMF; 14744 } else if (!strcasecmp(v->value, "featb")) { 14745 confp->chan.outsigmod = SIG_FEATB; 14746 } else { 14747 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14748 } 14749 #ifdef HAVE_PRI 14750 } else if (!strcasecmp(v->name, "pridialplan")) { 14751 if (!strcasecmp(v->value, "national")) { 14752 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 14753 } else if (!strcasecmp(v->value, "unknown")) { 14754 confp->pri.dialplan = PRI_UNKNOWN + 1; 14755 } else if (!strcasecmp(v->value, "private")) { 14756 confp->pri.dialplan = PRI_PRIVATE + 1; 14757 } else if (!strcasecmp(v->value, "international")) { 14758 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 14759 } else if (!strcasecmp(v->value, "local")) { 14760 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 14761 } else if (!strcasecmp(v->value, "dynamic")) { 14762 confp->pri.dialplan = -1; 14763 } else if (!strcasecmp(v->value, "redundant")) { 14764 confp->pri.dialplan = -2; 14765 } else { 14766 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14767 } 14768 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 14769 if (!strcasecmp(v->value, "national")) { 14770 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 14771 } else if (!strcasecmp(v->value, "unknown")) { 14772 confp->pri.localdialplan = PRI_UNKNOWN + 1; 14773 } else if (!strcasecmp(v->value, "private")) { 14774 confp->pri.localdialplan = PRI_PRIVATE + 1; 14775 } else if (!strcasecmp(v->value, "international")) { 14776 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 14777 } else if (!strcasecmp(v->value, "local")) { 14778 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 14779 } else if (!strcasecmp(v->value, "dynamic")) { 14780 confp->pri.localdialplan = -1; 14781 } else if (!strcasecmp(v->value, "redundant")) { 14782 confp->pri.localdialplan = -2; 14783 } else { 14784 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 14785 } 14786 } else if (!strcasecmp(v->name, "switchtype")) { 14787 if (!strcasecmp(v->value, "national")) 14788 confp->pri.switchtype = PRI_SWITCH_NI2; 14789 else if (!strcasecmp(v->value, "ni1")) 14790 confp->pri.switchtype = PRI_SWITCH_NI1; 14791 else if (!strcasecmp(v->value, "dms100")) 14792 confp->pri.switchtype = PRI_SWITCH_DMS100; 14793 else if (!strcasecmp(v->value, "4ess")) 14794 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 14795 else if (!strcasecmp(v->value, "5ess")) 14796 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 14797 else if (!strcasecmp(v->value, "euroisdn")) 14798 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 14799 else if (!strcasecmp(v->value, "qsig")) 14800 confp->pri.switchtype = PRI_SWITCH_QSIG; 14801 else { 14802 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 14803 return -1; 14804 } 14805 } else if (!strcasecmp(v->name, "nsf")) { 14806 if (!strcasecmp(v->value, "sdn")) 14807 confp->pri.nsf = PRI_NSF_SDN; 14808 else if (!strcasecmp(v->value, "megacom")) 14809 confp->pri.nsf = PRI_NSF_MEGACOM; 14810 else if (!strcasecmp(v->value, "tollfreemegacom")) 14811 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 14812 else if (!strcasecmp(v->value, "accunet")) 14813 confp->pri.nsf = PRI_NSF_ACCUNET; 14814 else if (!strcasecmp(v->value, "none")) 14815 confp->pri.nsf = PRI_NSF_NONE; 14816 else { 14817 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 14818 confp->pri.nsf = PRI_NSF_NONE; 14819 } 14820 } else if (!strcasecmp(v->name, "priindication")) { 14821 if (!strcasecmp(v->value, "outofband")) 14822 confp->chan.priindication_oob = 1; 14823 else if (!strcasecmp(v->value, "inband")) 14824 confp->chan.priindication_oob = 0; 14825 else 14826 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 14827 v->value, v->lineno); 14828 } else if (!strcasecmp(v->name, "priexclusive")) { 14829 confp->chan.priexclusive = ast_true(v->value); 14830 } else if (!strcasecmp(v->name, "internationalprefix")) { 14831 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 14832 } else if (!strcasecmp(v->name, "nationalprefix")) { 14833 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 14834 } else if (!strcasecmp(v->name, "localprefix")) { 14835 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 14836 } else if (!strcasecmp(v->name, "privateprefix")) { 14837 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 14838 } else if (!strcasecmp(v->name, "unknownprefix")) { 14839 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 14840 } else if (!strcasecmp(v->name, "resetinterval")) { 14841 if (!strcasecmp(v->value, "never")) 14842 confp->pri.resetinterval = -1; 14843 else if (atoi(v->value) >= 60) 14844 confp->pri.resetinterval = atoi(v->value); 14845 else 14846 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 14847 v->value, v->lineno); 14848 } else if (!strcasecmp(v->name, "minunused")) { 14849 confp->pri.minunused = atoi(v->value); 14850 } else if (!strcasecmp(v->name, "minidle")) { 14851 confp->pri.minidle = atoi(v->value); 14852 } else if (!strcasecmp(v->name, "idleext")) { 14853 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 14854 } else if (!strcasecmp(v->name, "idledial")) { 14855 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 14856 } else if (!strcasecmp(v->name, "overlapdial")) { 14857 if (ast_true(v->value)) { 14858 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14859 } else if (!strcasecmp(v->value, "incoming")) { 14860 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 14861 } else if (!strcasecmp(v->value, "outgoing")) { 14862 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 14863 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 14864 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14865 } else { 14866 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 14867 } 14868 #ifdef HAVE_PRI_INBANDDISCONNECT 14869 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 14870 confp->pri.inbanddisconnect = ast_true(v->value); 14871 #endif 14872 } else if (!strcasecmp(v->name, "pritimer")) { 14873 #ifdef PRI_GETSET_TIMERS 14874 char tmp[20]; 14875 char *timerc; 14876 char *c; 14877 int timer; 14878 int timeridx; 14879 14880 ast_copy_string(tmp, v->value, sizeof(tmp)); 14881 c = tmp; 14882 timerc = strsep(&c, ","); 14883 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 14884 timeridx = pri_timer2idx(timerc); 14885 timer = atoi(c); 14886 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 14887 ast_log(LOG_WARNING, 14888 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 14889 v->lineno); 14890 } else if (!timer) { 14891 ast_log(LOG_WARNING, 14892 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 14893 c, timerc, v->lineno); 14894 } else { 14895 pritimers[timeridx] = timer; 14896 } 14897 } else { 14898 ast_log(LOG_WARNING, 14899 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 14900 v->value, v->lineno); 14901 } 14902 14903 } else if (!strcasecmp(v->name, "facilityenable")) { 14904 confp->pri.facilityenable = ast_true(v->value); 14905 #endif /* PRI_GETSET_TIMERS */ 14906 #endif /* HAVE_PRI */ 14907 #ifdef HAVE_SS7 14908 } else if (!strcasecmp(v->name, "ss7type")) { 14909 if (!strcasecmp(v->value, "itu")) { 14910 cur_ss7type = SS7_ITU; 14911 } else if (!strcasecmp(v->value, "ansi")) { 14912 cur_ss7type = SS7_ANSI; 14913 } else 14914 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 14915 } else if (!strcasecmp(v->name, "linkset")) { 14916 cur_linkset = atoi(v->value); 14917 } else if (!strcasecmp(v->name, "pointcode")) { 14918 cur_pointcode = parse_pointcode(v->value); 14919 } else if (!strcasecmp(v->name, "adjpointcode")) { 14920 cur_adjpointcode = parse_pointcode(v->value); 14921 } else if (!strcasecmp(v->name, "defaultdpc")) { 14922 cur_defaultdpc = parse_pointcode(v->value); 14923 } else if (!strcasecmp(v->name, "cicbeginswith")) { 14924 cur_cicbeginswith = atoi(v->value); 14925 } else if (!strcasecmp(v->name, "networkindicator")) { 14926 if (!strcasecmp(v->value, "national")) 14927 cur_networkindicator = SS7_NI_NAT; 14928 else if (!strcasecmp(v->value, "national_spare")) 14929 cur_networkindicator = SS7_NI_NAT_SPARE; 14930 else if (!strcasecmp(v->value, "international")) 14931 cur_networkindicator = SS7_NI_INT; 14932 else if (!strcasecmp(v->value, "international_spare")) 14933 cur_networkindicator = SS7_NI_INT_SPARE; 14934 else 14935 cur_networkindicator = -1; 14936 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 14937 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix)); 14938 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 14939 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix)); 14940 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 14941 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix)); 14942 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 14943 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix)); 14944 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 14945 if (!strcasecmp(v->value, "national")) { 14946 confp->ss7.called_nai = SS7_NAI_NATIONAL; 14947 } else if (!strcasecmp(v->value, "international")) { 14948 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL; 14949 } else if (!strcasecmp(v->value, "subscriber")) { 14950 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER; 14951 } else if (!strcasecmp(v->value, "dynamic")) { 14952 confp->ss7.called_nai = SS7_NAI_DYNAMIC; 14953 } else { 14954 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 14955 } 14956 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 14957 if (!strcasecmp(v->value, "national")) { 14958 confp->ss7.calling_nai = SS7_NAI_NATIONAL; 14959 } else if (!strcasecmp(v->value, "international")) { 14960 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL; 14961 } else if (!strcasecmp(v->value, "subscriber")) { 14962 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER; 14963 } else if (!strcasecmp(v->value, "dynamic")) { 14964 confp->ss7.calling_nai = SS7_NAI_DYNAMIC; 14965 } else { 14966 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 14967 } 14968 } else if (!strcasecmp(v->name, "sigchan")) { 14969 int sigchan, res; 14970 sigchan = atoi(v->value); 14971 res = linkset_addsigchan(sigchan); 14972 if (res < 0) 14973 return -1; 14974 14975 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 14976 struct dahdi_ss7 *link; 14977 link = ss7_resolve_linkset(cur_linkset); 14978 if (!link) { 14979 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 14980 return -1; 14981 } 14982 if (ast_true(v->value)) 14983 link->flags |= LINKSET_FLAG_EXPLICITACM; 14984 14985 #endif /* HAVE_SS7 */ 14986 } else if (!strcasecmp(v->name, "cadence")) { 14987 /* setup to scan our argument */ 14988 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 14989 int i; 14990 struct dahdi_ring_cadence new_cadence; 14991 int cid_location = -1; 14992 int firstcadencepos = 0; 14993 char original_args[80]; 14994 int cadence_is_ok = 1; 14995 14996 ast_copy_string(original_args, v->value, sizeof(original_args)); 14997 /* 16 cadences allowed (8 pairs) */ 14998 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]); 14999 15000 /* Cadence must be even (on/off) */ 15001 if (element_count % 2 == 1) { 15002 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 15003 cadence_is_ok = 0; 15004 } 15005 15006 /* Ring cadences cannot be negative */ 15007 for (i = 0; i < element_count; i++) { 15008 if (c[i] == 0) { 15009 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 15010 cadence_is_ok = 0; 15011 break; 15012 } else if (c[i] < 0) { 15013 if (i % 2 == 1) { 15014 /* Silence duration, negative possibly okay */ 15015 if (cid_location == -1) { 15016 cid_location = i; 15017 c[i] *= -1; 15018 } else { 15019 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 15020 cadence_is_ok = 0; 15021 break; 15022 } 15023 } else { 15024 if (firstcadencepos == 0) { 15025 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 15026 /* duration will be passed negative to the DAHDI driver */ 15027 } else { 15028 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 15029 cadence_is_ok = 0; 15030 break; 15031 } 15032 } 15033 } 15034 } 15035 15036 /* Substitute our scanned cadence */ 15037 for (i = 0; i < 16; i++) { 15038 new_cadence.ringcadence[i] = c[i]; 15039 } 15040 15041 if (cadence_is_ok) { 15042 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 15043 if (element_count < 2) { 15044 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 15045 } else { 15046 if (cid_location == -1) { 15047 /* user didn't say; default to first pause */ 15048 cid_location = 1; 15049 } else { 15050 /* convert element_index to cidrings value */ 15051 cid_location = (cid_location + 1) / 2; 15052 } 15053 /* ---we like their cadence; try to install it--- */ 15054 if (!user_has_defined_cadences++) 15055 /* this is the first user-defined cadence; clear the default user cadences */ 15056 num_cadence = 0; 15057 if ((num_cadence+1) >= NUM_CADENCE_MAX) 15058 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 15059 else { 15060 cadences[num_cadence] = new_cadence; 15061 cidrings[num_cadence++] = cid_location; 15062 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 15063 } 15064 } 15065 } 15066 } else if (!strcasecmp(v->name, "ringtimeout")) { 15067 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 15068 } else if (!strcasecmp(v->name, "prewink")) { 15069 confp->timing.prewinktime = atoi(v->value); 15070 } else if (!strcasecmp(v->name, "preflash")) { 15071 confp->timing.preflashtime = atoi(v->value); 15072 } else if (!strcasecmp(v->name, "wink")) { 15073 confp->timing.winktime = atoi(v->value); 15074 } else if (!strcasecmp(v->name, "flash")) { 15075 confp->timing.flashtime = atoi(v->value); 15076 } else if (!strcasecmp(v->name, "start")) { 15077 confp->timing.starttime = atoi(v->value); 15078 } else if (!strcasecmp(v->name, "rxwink")) { 15079 confp->timing.rxwinktime = atoi(v->value); 15080 } else if (!strcasecmp(v->name, "rxflash")) { 15081 confp->timing.rxflashtime = atoi(v->value); 15082 } else if (!strcasecmp(v->name, "debounce")) { 15083 confp->timing.debouncetime = atoi(v->value); 15084 } else if (!strcasecmp(v->name, "toneduration")) { 15085 int toneduration; 15086 int ctlfd; 15087 int res; 15088 struct dahdi_dialparams dps; 15089 15090 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 15091 if (ctlfd == -1) { 15092 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 15093 return -1; 15094 } 15095 15096 toneduration = atoi(v->value); 15097 if (toneduration > -1) { 15098 memset(&dps, 0, sizeof(dps)); 15099 15100 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 15101 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 15102 if (res < 0) { 15103 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 15104 return -1; 15105 } 15106 } 15107 close(ctlfd); 15108 } else if (!strcasecmp(v->name, "defaultcic")) { 15109 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 15110 } else if (!strcasecmp(v->name, "defaultozz")) { 15111 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 15112 } else if (!strcasecmp(v->name, "mwilevel")) { 15113 mwilevel = atoi(v->value); 15114 } 15115 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 15116 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 15117 } 15118 if (dahdichan[0]) { 15119 /* The user has set 'dahdichan' */ 15120 /*< \todo pass proper line number instead of 0 */ 15121 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 15122 return -1; 15123 } 15124 } 15125 /*< \todo why check for the pseudo in the per-channel section. 15126 * Any actual use for manual setup of the pseudo channel? */ 15127 if (!found_pseudo && reload != 1) { 15128 /* use the default configuration for a channel, so 15129 that any settings from real configured channels 15130 don't "leak" into the pseudo channel config 15131 */ 15132 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 15133 15134 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 15135 15136 if (tmp) { 15137 ast_verb(3, "Automatically generated pseudo channel\n"); 15138 } else { 15139 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 15140 } 15141 } 15142 return 0; 15143 }
| static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
| const char * | data, | |||
| unsigned int | line | |||
| ) | [static] |
Definition at line 14243 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().
14244 { 14245 char *parse = ast_strdupa(data); 14246 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 14247 unsigned int param_count; 14248 unsigned int x; 14249 14250 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 14251 return; 14252 14253 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 14254 14255 /* first parameter is tap length, process it here */ 14256 14257 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 14258 14259 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 14260 confp->chan.echocancel.head.tap_length = x; 14261 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 14262 confp->chan.echocancel.head.tap_length = 128; 14263 14264 /* now process any remaining parameters */ 14265 14266 for (x = 1; x < param_count; x++) { 14267 struct { 14268 char *name; 14269 char *value; 14270 } param; 14271 14272 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 14273 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 14274 continue; 14275 } 14276 14277 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 14278 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 14279 continue; 14280 } 14281 14282 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 14283 14284 if (param.value) { 14285 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 14286 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 14287 continue; 14288 } 14289 } 14290 confp->chan.echocancel.head.param_count++; 14291 } 14292 }
| static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10869 of file chan_dahdi.c.
Referenced by pri_dchannel().
| static int reload | ( | void | ) | [static] |
Definition at line 15513 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
15514 { 15515 int res = 0; 15516 15517 res = setup_dahdi(1); 15518 if (res) { 15519 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 15520 return -1; 15521 } 15522 return 0; 15523 }
| static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1935 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup().
01936 { 01937 p->confno = -1; 01938 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01939 if (p->subs[SUB_REAL].dfd > -1) { 01940 struct dahdi_confinfo zi; 01941 01942 memset(&zi, 0, sizeof(zi)); 01943 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01944 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01945 } 01946 return 0; 01947 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 8560 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().
08561 { 08562 /* If we're supposed to be stopped -- stay stopped */ 08563 if (monitor_thread == AST_PTHREADT_STOP) 08564 return 0; 08565 ast_mutex_lock(&monlock); 08566 if (monitor_thread == pthread_self()) { 08567 ast_mutex_unlock(&monlock); 08568 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08569 return -1; 08570 } 08571 if (monitor_thread != AST_PTHREADT_NULL) { 08572 /* Wake up the thread */ 08573 pthread_kill(monitor_thread, SIGURG); 08574 } else { 08575 /* Start a new monitor */ 08576 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 08577 ast_mutex_unlock(&monlock); 08578 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08579 return -1; 08580 } 08581 } 08582 ast_mutex_unlock(&monlock); 08583 return 0; 08584 }
| static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2314 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().
02315 { 02316 int res; 02317 if (p->saveconf.confmode) { 02318 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02319 p->saveconf.confmode = 0; 02320 if (res) { 02321 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02322 return -1; 02323 } 02324 } 02325 ast_debug(1, "Restored conferencing\n"); 02326 return 0; 02327 }
| static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2195 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().
02196 { 02197 int res; 02198 02199 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02200 if (res) { 02201 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02202 return -1; 02203 } 02204 02205 return 0; 02206 }
| static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2241 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), and dahdi_handle_event().
02242 { 02243 struct dahdi_confinfo c; 02244 int res; 02245 if (p->saveconf.confmode) { 02246 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02247 return -1; 02248 } 02249 p->saveconf.chan = 0; 02250 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02251 if (res) { 02252 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02253 p->saveconf.confmode = 0; 02254 return -1; 02255 } 02256 memset(&c, 0, sizeof(c)); 02257 c.confmode = DAHDI_CONF_NORMAL; 02258 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02259 if (res) { 02260 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02261 return -1; 02262 } 02263 ast_debug(1, "Disabled conferencing\n"); 02264 return 0; 02265 }
| static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2371 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().
02372 { 02373 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02374 int res; 02375 /* Take out of linear mode if necessary */ 02376 if (p->subs[SUB_REAL].linear) { 02377 p->subs[SUB_REAL].linear = 0; 02378 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02379 } 02380 while (p->cidpos < p->cidlen) { 02381 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02382 if (res < 0) { 02383 if (errno == EAGAIN) 02384 return 0; 02385 else { 02386 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02387 return -1; 02388 } 02389 } 02390 if (!res) 02391 return 0; 02392 p->cidpos += res; 02393 } 02394 ast_free(p->cidspill); 02395 p->cidspill = NULL; 02396 if (p->callwaitcas) { 02397 /* Wait for CID/CW to expire */ 02398 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02399 } else 02400 restore_conference(p); 02401 return 0; 02402 }
| static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2331 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().
02332 { 02333 p->callwaitcas = 0; 02334 p->cidcwexpire = 0; 02335 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02336 return -1; 02337 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02338 /* Make sure we account for the end */ 02339 p->cidlen += READ_SIZE * 4; 02340 p->cidpos = 0; 02341 send_callerid(p); 02342 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02343 return 0; 02344 }
| static int set_actual_gain | ( | int | fd, | |
| int | chan, | |||
| float | rxgain, | |||
| float | txgain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2176 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), mkintf(), pri_dchannel(), and restore_gains().
02177 { 02178 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02179 }
| static int set_actual_rxgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2158 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02159 { 02160 struct dahdi_gains g; 02161 int res; 02162 02163 memset(&g, 0, sizeof(g)); 02164 g.chan = chan; 02165 res = ioctl(fd, DAHDI_GETGAINS, &g); 02166 if (res) { 02167 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02168 return res; 02169 } 02170 02171 fill_rxgain(&g, gain, law); 02172 02173 return ioctl(fd, DAHDI_SETGAINS, &g); 02174 }
| static int set_actual_txgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2140 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02141 { 02142 struct dahdi_gains g; 02143 int res; 02144 02145 memset(&g, 0, sizeof(g)); 02146 g.chan = chan; 02147 res = ioctl(fd, DAHDI_GETGAINS, &g); 02148 if (res) { 02149 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02150 return res; 02151 } 02152 02153 fill_txgain(&g, gain, law); 02154 02155 return ioctl(fd, DAHDI_SETGAINS, &g); 02156 }
| static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 15145 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().
15146 { 15147 struct ast_config *cfg, *ucfg; 15148 struct ast_variable *v; 15149 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 15150 struct dahdi_chan_conf conf; 15151 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 15152 const char *cat; 15153 int res; 15154 15155 #ifdef HAVE_PRI 15156 char *c; 15157 int spanno; 15158 int i; 15159 int logicalspan; 15160 int trunkgroup; 15161 int dchannels[NUM_DCHANS]; 15162 #endif 15163 15164 cfg = ast_config_load(config, config_flags); 15165 15166 /* Error if we have no config file */ 15167 if (!cfg) { 15168 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 15169 return 0; 15170 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 15171 ucfg = ast_config_load("users.conf", config_flags); 15172 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 15173 return 0; 15174 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15175 cfg = ast_config_load(config, config_flags); 15176 } else { 15177 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15178 ucfg = ast_config_load("users.conf", config_flags); 15179 } 15180 15181 /* It's a little silly to lock it, but we mind as well just to be sure */ 15182 ast_mutex_lock(&iflock); 15183 #ifdef HAVE_PRI 15184 if (reload != 1) { 15185 /* Process trunkgroups first */ 15186 v = ast_variable_browse(cfg, "trunkgroups"); 15187 while (v) { 15188 if (!strcasecmp(v->name, "trunkgroup")) { 15189 trunkgroup = atoi(v->value); 15190 if (trunkgroup > 0) { 15191 if ((c = strchr(v->value, ','))) { 15192 i = 0; 15193 memset(dchannels, 0, sizeof(dchannels)); 15194 while (c && (i < NUM_DCHANS)) { 15195 dchannels[i] = atoi(c + 1); 15196 if (dchannels[i] < 0) { 15197 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); 15198 } else 15199 i++; 15200 c = strchr(c + 1, ','); 15201 } 15202 if (i) { 15203 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 15204 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); 15205 } else 15206 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"); 15207 } else 15208 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15209 } else 15210 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15211 } else 15212 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 15213 } else if (!strcasecmp(v->name, "spanmap")) { 15214 spanno = atoi(v->value); 15215 if (spanno > 0) { 15216 if ((c = strchr(v->value, ','))) { 15217 trunkgroup = atoi(c + 1); 15218 if (trunkgroup > 0) { 15219 if ((c = strchr(c + 1, ','))) 15220 logicalspan = atoi(c + 1); 15221 else 15222 logicalspan = 0; 15223 if (logicalspan >= 0) { 15224 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 15225 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15226 } else 15227 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15228 } else 15229 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); 15230 } else 15231 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 15232 } else 15233 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 15234 } else 15235 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 15236 } else { 15237 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 15238 } 15239 v = v->next; 15240 } 15241 } 15242 #endif 15243 15244 /* Copy the default jb config over global_jbconf */ 15245 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 15246 15247 mwimonitornotify[0] = '\0'; 15248 15249 v = ast_variable_browse(cfg, "channels"); 15250 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) { 15251 ast_mutex_unlock(&iflock); 15252 ast_config_destroy(cfg); 15253 if (ucfg) { 15254 ast_config_destroy(ucfg); 15255 } 15256 return res; 15257 } 15258 15259 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 15260 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 15261 /* [channels] and [trunkgroups] are used. Let's also reserve 15262 * [globals] and [general] for future use 15263 */ 15264 if (!strcasecmp(cat, "general") || 15265 !strcasecmp(cat, "trunkgroups") || 15266 !strcasecmp(cat, "globals") || 15267 !strcasecmp(cat, "channels")) { 15268 continue; 15269 } 15270 15271 memcpy(&conf, &base_conf, sizeof(conf)); 15272 15273 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 15274 ast_mutex_unlock(&iflock); 15275 ast_config_destroy(cfg); 15276 if (ucfg) { 15277 ast_config_destroy(cfg); 15278 } 15279 return res; 15280 } 15281 } 15282 15283 ast_config_destroy(cfg); 15284 15285 if (ucfg) { 15286 const char *chans; 15287 15288 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0); 15289 15290 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 15291 if (!strcasecmp(cat, "general")) { 15292 continue; 15293 } 15294 15295 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 15296 15297 if (ast_strlen_zero(chans)) { 15298 continue; 15299 } 15300 15301 memcpy(&conf, &base_conf, sizeof(conf)); 15302 15303 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 15304 ast_config_destroy(ucfg); 15305 ast_mutex_unlock(&iflock); 15306 return res; 15307 } 15308 } 15309 ast_config_destroy(ucfg); 15310 } 15311 ast_mutex_unlock(&iflock); 15312 15313 #ifdef HAVE_PRI 15314 if (reload != 1) { 15315 int x; 15316 for (x = 0; x < NUM_SPANS; x++) { 15317 if (pris[x].pvts[0]) { 15318 if (start_pri(pris + x)) { 15319 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 15320 return -1; 15321 } else 15322 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 15323 } 15324 } 15325 } 15326 #endif 15327 #ifdef HAVE_SS7 15328 if (reload != 1) { 15329 int x; 15330 for (x = 0; x < NUM_SPANS; x++) { 15331 if (linksets[x].ss7) { 15332 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) { 15333 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 15334 return -1; 15335 } else 15336 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 15337 } 15338 } 15339 } 15340 #endif 15341 /* And start the monitor for the first time */ 15342 restart_monitor(); 15343 return 0; 15344 }
| static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
Definition at line 8739 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 9976 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().
09977 { 09978 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 09979 if (size) { 09980 *buf = '\0'; 09981 } 09982 return; 09983 } 09984 switch (nai) { 09985 case SS7_NAI_INTERNATIONAL: 09986 snprintf(buf, size, "%s%s", ss7->internationalprefix, number); 09987 break; 09988 case SS7_NAI_NATIONAL: 09989 snprintf(buf, size, "%s%s", ss7->nationalprefix, number); 09990 break; 09991 case SS7_NAI_SUBSCRIBER: 09992 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number); 09993 break; 09994 case SS7_NAI_UNKNOWN: 09995 snprintf(buf, size, "%s%s", ss7->unknownprefix, number); 09996 break; 09997 default: 09998 snprintf(buf, size, "%s", number); 09999 break; 10000 } 10001 }
| 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 9795 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().
09796 { 09797 int i; 09798 09799 for (i = 0; i < linkset->numchans; i++) { 09800 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 09801 if (state) { 09802 if (state[i]) 09803 linkset->pvts[i]->remotelyblocked = block; 09804 } else 09805 linkset->pvts[i]->remotelyblocked = block; 09806 } 09807 } 09808 }
| static int ss7_find_cic | ( | struct dahdi_ss7 * | linkset, | |
| int | cic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9750 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 1251 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().
01252 { 01253 int res; 01254 /* Grab the lock first */ 01255 do { 01256 res = ast_mutex_trylock(&pri->lock); 01257 if (res) { 01258 DEADLOCK_AVOIDANCE(&pvt->lock); 01259 } 01260 } while (res); 01261 /* Then break the poll */ 01262 if (pri->master != AST_PTHREADT_NULL) 01263 pthread_kill(pri->master, SIGURG); 01264 return 0; 01265 }
| static void ss7_handle_cqm | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9763 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().
09764 { 09765 unsigned char status[32]; 09766 struct dahdi_pvt *p = NULL; 09767 int i, offset; 09768 09769 for (i = 0; i < linkset->numchans; i++) { 09770 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 09771 p = linkset->pvts[i]; 09772 offset = p->cic - startcic; 09773 status[offset] = 0; 09774 if (p->locallyblocked) 09775 status[offset] |= (1 << 0) | (1 << 4); 09776 if (p->remotelyblocked) 09777 status[offset] |= (1 << 1) | (1 << 5); 09778 if (p->ss7call) { 09779 if (p->outgoing) 09780 status[offset] |= (1 << 3); 09781 else 09782 status[offset] |= (1 << 2); 09783 } else 09784 status[offset] |= 0x3 << 2; 09785 } 09786 } 09787 09788 if (p) 09789 isup_cqr(linkset->ss7, startcic, endcic, dpc, status); 09790 else 09791 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n"); 09792 09793 }
| static void ss7_inservice | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9810 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 10007 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().
10008 { 10009 int res, i; 10010 struct timeval *next = NULL, tv; 10011 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data; 10012 struct ss7 *ss7 = linkset->ss7; 10013 ss7_event *e = NULL; 10014 struct dahdi_pvt *p; 10015 int chanpos; 10016 struct pollfd pollers[NUM_DCHANS]; 10017 int cic; 10018 unsigned int dpc; 10019 int nextms = 0; 10020 10021 ss7_start(ss7); 10022 10023 while(1) { 10024 ast_mutex_lock(&linkset->lock); 10025 if ((next = ss7_schedule_next(ss7))) { 10026 tv = ast_tvnow(); 10027 tv.tv_sec = next->tv_sec - tv.tv_sec; 10028 tv.tv_usec = next->tv_usec - tv.tv_usec; 10029 if (tv.tv_usec < 0) { 10030 tv.tv_usec += 1000000; 10031 tv.tv_sec -= 1; 10032 } 10033 if (tv.tv_sec < 0) { 10034 tv.tv_sec = 0; 10035 tv.tv_usec = 0; 10036 } 10037 nextms = tv.tv_sec * 1000; 10038 nextms += tv.tv_usec / 1000; 10039 } 10040 ast_mutex_unlock(&linkset->lock); 10041 10042 for (i = 0; i < linkset->numsigchans; i++) { 10043 pollers[i].fd = linkset->fds[i]; 10044 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]); 10045 pollers[i].revents = 0; 10046 } 10047 10048 res = poll(pollers, linkset->numsigchans, nextms); 10049 if ((res < 0) && (errno != EINTR)) { 10050 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno)); 10051 } else if (!res) { 10052 ast_mutex_lock(&linkset->lock); 10053 ss7_schedule_run(ss7); 10054 ast_mutex_unlock(&linkset->lock); 10055 continue; 10056 } 10057 10058 ast_mutex_lock(&linkset->lock); 10059 for (i = 0; i < linkset->numsigchans; i++) { 10060 if (pollers[i].revents & POLLPRI) { 10061 int x; 10062 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) { 10063 ast_log(LOG_ERROR, "Error in exception retrieval!\n"); 10064 } 10065 switch (x) { 10066 case DAHDI_EVENT_OVERRUN: 10067 ast_debug(1, "Overrun detected!\n"); 10068 break; 10069 case DAHDI_EVENT_BADFCS: 10070 ast_debug(1, "Bad FCS\n"); 10071 break; 10072 case DAHDI_EVENT_ABORT: 10073 ast_debug(1, "HDLC Abort\n"); 10074 break; 10075 case DAHDI_EVENT_ALARM: 10076 ast_log(LOG_ERROR, "Alarm on link!\n"); 10077 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM); 10078 linkset->linkstate[i] &= ~LINKSTATE_UP; 10079 ss7_link_alarm(ss7, pollers[i].fd); 10080 break; 10081 case DAHDI_EVENT_NOALARM: 10082 ast_log(LOG_ERROR, "Alarm cleared on link\n"); 10083 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN); 10084 linkset->linkstate[i] |= LINKSTATE_STARTING; 10085 ss7_link_noalarm(ss7, pollers[i].fd); 10086 break; 10087 default: 10088 ast_log(LOG_ERROR, "Got exception %d!\n", x); 10089 break; 10090 } 10091 } 10092 10093 if (pollers[i].revents & POLLIN) { 10094 ast_mutex_lock(&linkset->lock); 10095 res = ss7_read(ss7, pollers[i].fd); 10096 ast_mutex_unlock(&linkset->lock); 10097 } 10098 10099 if (pollers[i].revents & POLLOUT) { 10100 ast_mutex_lock(&linkset->lock); 10101 res = ss7_write(ss7, pollers[i].fd); 10102 ast_mutex_unlock(&linkset->lock); 10103 if (res < 0) { 10104 ast_debug(1, "Error in write %s\n", strerror(errno)); 10105 } 10106 } 10107 } 10108 10109 while ((e = ss7_check_event(ss7))) { 10110 switch (e->e) { 10111 case SS7_EVENT_UP: 10112 if (linkset->state != LINKSET_STATE_UP) { 10113 ast_verbose("--- SS7 Up ---\n"); 10114 ss7_reset_linkset(linkset); 10115 } 10116 linkset->state = LINKSET_STATE_UP; 10117 break; 10118 case SS7_EVENT_DOWN: 10119 ast_verbose("--- SS7 Down ---\n"); 10120 linkset->state = LINKSET_STATE_DOWN; 10121 for (i = 0; i < linkset->numchans; i++) { 10122 struct dahdi_pvt *p = linkset->pvts[i]; 10123 if (p) 10124 p->inalarm = 1; 10125 } 10126 break; 10127 case MTP2_LINK_UP: 10128 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data); 10129 break; 10130 case MTP2_LINK_DOWN: 10131 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data); 10132 break; 10133 case ISUP_EVENT_CPG: 10134 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc); 10135 if (chanpos < 0) { 10136 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic); 10137 break; 10138 } 10139 p = linkset->pvts[chanpos]; 10140 ast_mutex_lock(&p->lock); 10141 switch (e->cpg.event) { 10142 case CPG_EVENT_ALERTING: 10143 p->alerting = 1; 10144 p->subs[SUB_REAL].needringing = 1; 10145 break; 10146 case CPG_EVENT_PROGRESS: 10147 case CPG_EVENT_INBANDINFO: 10148 { 10149 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 10150 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic); 10151 dahdi_queue_frame(p, &f, linkset); 10152 p->progress = 1; 10153 p->dialing = 0; 10154 if (p->dsp && p->dsp_features) { 10155 ast_dsp_set_features(p->dsp, p->dsp_features); 10156 p->dsp_features = 0; 10157 } 10158 } 10159 break; 10160 default: 10161 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event); 10162 } 10163 10164 ast_mutex_unlock(&p->lock); 10165 break; 10166 case ISUP_EVENT_RSC: 10167 ast_verbose("Resetting CIC %d\n", e->rsc.cic); 10168 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc); 10169 if (chanpos < 0) { 10170 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic); 10171 break; 10172 } 10173 p = linkset->pvts[chanpos]; 10174 ast_mutex_lock(&p->lock); 10175 p->inservice = 1; 10176 p->remotelyblocked = 0; 10177 dpc = p->dpc; 10178 isup_set_call_dpc(e->rsc.call, dpc); 10179 if (p->ss7call) 10180 p->ss7call = NULL; 10181 if (p->owner) 10182 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10183 ast_mutex_unlock(&p->lock); 10184 isup_rlc(ss7, e->rsc.call); 10185 break; 10186 case ISUP_EVENT_GRS: 10187 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic); 10188 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc); 10189 if (chanpos < 0) { 10190 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic); 10191 break; 10192 } 10193 p = linkset->pvts[chanpos]; 10194 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc); 10195 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0); 10196 break; 10197 case ISUP_EVENT_CQM: 10198 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic); 10199 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc); 10200 break; 10201 case ISUP_EVENT_GRA: 10202 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic); 10203 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc); 10204 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1); 10205 break; 10206 case ISUP_EVENT_IAM: 10207 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); 10208 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc); 10209 if (chanpos < 0) { 10210 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic); 10211 isup_rel(ss7, e->iam.call, -1); 10212 break; 10213 } 10214 p = linkset->pvts[chanpos]; 10215 ast_mutex_lock(&p->lock); 10216 if (p->owner) { 10217 if (p->ss7call == e->iam.call) { 10218 ast_mutex_unlock(&p->lock); 10219 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic); 10220 break; 10221 } else { 10222 ast_mutex_unlock(&p->lock); 10223 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic); 10224 break; 10225 } 10226 } 10227 10228 dpc = p->dpc; 10229 p->ss7call = e->iam.call; 10230 isup_set_call_dpc(p->ss7call, dpc); 10231 10232 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) { 10233 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai); 10234 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind); 10235 } else 10236 p->cid_num[0] = 0; 10237 10238 if (p->immediate) { 10239 p->exten[0] = 's'; 10240 p->exten[1] = '\0'; 10241 } else if (!ast_strlen_zero(e->iam.called_party_num)) { 10242 char *st; 10243 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai); 10244 st = strchr(p->exten, '#'); 10245 if (st) 10246 *st = '\0'; 10247 } else 10248 p->exten[0] = '\0'; 10249 10250 p->cid_ani[0] = '\0'; 10251 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name))) 10252 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name)); 10253 else 10254 p->cid_name[0] = '\0'; 10255 10256 p->cid_ani2 = e->iam.oli_ani2; 10257 p->cid_ton = 0; 10258 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number)); 10259 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number)); 10260 p->gen_add_type = e->iam.gen_add_type; 10261 p->gen_add_nai = e->iam.gen_add_nai; 10262 p->gen_add_pres_ind = e->iam.gen_add_pres_ind; 10263 p->gen_add_num_plan = e->iam.gen_add_num_plan; 10264 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number)); 10265 p->gen_dig_type = e->iam.gen_dig_type; 10266 p->gen_dig_scheme = e->iam.gen_dig_scheme; 10267 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number)); 10268 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num)); 10269 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num)); 10270 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name)); 10271 p->calling_party_cat = e->iam.calling_party_cat; 10272 10273 /* Set DNID */ 10274 if (!ast_strlen_zero(e->iam.called_party_num)) 10275 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai); 10276 10277 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 10278 10279 if (e->iam.cot_check_required) { 10280 dahdi_loopback(p, 1); 10281 } else 10282 ss7_start_call(p, linkset); 10283 } else { 10284 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten); 10285 p->alreadyhungup = 1; 10286 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED); 10287 } 10288 ast_mutex_unlock(&p->lock); 10289 break; 10290 case ISUP_EVENT_COT: 10291 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc); 10292 if (chanpos < 0) { 10293 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic); 10294 isup_rel(ss7, e->cot.call, -1); 10295 break; 10296 } 10297 p = linkset->pvts[chanpos]; 10298 10299 ast_mutex_lock(&p->lock); 10300 10301 if (p->loopedback) { 10302 dahdi_loopback(p, 0); 10303 ss7_start_call(p, linkset); 10304 } 10305 10306 ast_mutex_unlock(&p->lock); 10307 10308 break; 10309 case ISUP_EVENT_CCR: 10310 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic); 10311 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc); 10312 if (chanpos < 0) { 10313 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic); 10314 break; 10315 } 10316 10317 p = linkset->pvts[chanpos]; 10318 10319 ast_mutex_lock(&p->lock); 10320 dahdi_loopback(p, 1); 10321 ast_mutex_unlock(&p->lock); 10322 10323 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc); 10324 break; 10325 case ISUP_EVENT_CVT: 10326 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic); 10327 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc); 10328 if (chanpos < 0) { 10329 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic); 10330 break; 10331 } 10332 10333 p = linkset->pvts[chanpos]; 10334 10335 ast_mutex_lock(&p->lock); 10336 dahdi_loopback(p, 1); 10337 ast_mutex_unlock(&p->lock); 10338 10339 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc); 10340 break; 10341 case ISUP_EVENT_REL: 10342 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc); 10343 if (chanpos < 0) { 10344 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic); 10345 break; 10346 } 10347 p = linkset->pvts[chanpos]; 10348 ast_mutex_lock(&p->lock); 10349 if (p->owner) { 10350 p->owner->hangupcause = e->rel.cause; 10351 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10352 } else if (!p->restartpending) 10353 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic); 10354 10355 /* End the loopback if we have one */ 10356 dahdi_loopback(p, 0); 10357 10358 isup_rlc(ss7, e->rel.call); 10359 p->ss7call = NULL; 10360 10361 ast_mutex_unlock(&p->lock); 10362 break; 10363 case ISUP_EVENT_ACM: 10364 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc); 10365 if (chanpos < 0) { 10366 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic); 10367 isup_rel(ss7, e->acm.call, -1); 10368 break; 10369 } else { 10370 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 10371 10372 p = linkset->pvts[chanpos]; 10373 10374 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic); 10375 10376 if (e->acm.call_ref_ident > 0) { 10377 p->rlt = 1; /* Setting it but not using it here*/ 10378 } 10379 10380 ast_mutex_lock(&p->lock); 10381 dahdi_queue_frame(p, &f, linkset); 10382 p->proceeding = 1; 10383 p->dialing = 0; 10384 /* Send alerting if subscriber is free */ 10385 if (e->acm.called_party_status_ind == 1) { 10386 p->alerting = 1; 10387 p->subs[SUB_REAL].needringing = 1; 10388 } 10389 ast_mutex_unlock(&p->lock); 10390 } 10391 break; 10392 case ISUP_EVENT_CGB: 10393 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc); 10394 if (chanpos < 0) { 10395 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic); 10396 break; 10397 } 10398 p = linkset->pvts[chanpos]; 10399 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1); 10400 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type); 10401 break; 10402 case ISUP_EVENT_CGU: 10403 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc); 10404 if (chanpos < 0) { 10405 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic); 10406 break; 10407 } 10408 p = linkset->pvts[chanpos]; 10409 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0); 10410 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type); 10411 break; 10412 case ISUP_EVENT_UCIC: 10413 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc); 10414 if (chanpos < 0) { 10415 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic); 10416 break; 10417 } 10418 p = linkset->pvts[chanpos]; 10419 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic); 10420 ast_mutex_lock(&p->lock); 10421 p->remotelyblocked = 1; 10422 p->inservice = 0; 10423 ast_mutex_unlock(&p->lock); //doesn't require a SS7 acknowledgement 10424 break; 10425 case ISUP_EVENT_BLO: 10426 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc); 10427 if (chanpos < 0) { 10428 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic); 10429 break; 10430 } 10431 p = linkset->pvts[chanpos]; 10432 ast_debug(1, "Blocking CIC %d\n", e->blo.cic); 10433 ast_mutex_lock(&p->lock); 10434 p->remotelyblocked = 1; 10435 ast_mutex_unlock(&p->lock); 10436 isup_bla(linkset->ss7, e->blo.cic, p->dpc); 10437 break; 10438 case ISUP_EVENT_BLA: 10439 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc); 10440 if (chanpos < 0) { 10441 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic); 10442 break; 10443 } 10444 ast_debug(1, "Blocking CIC %d\n", e->bla.cic); 10445 p = linkset->pvts[chanpos]; 10446 ast_mutex_lock(&p->lock); 10447 p->locallyblocked = 1; 10448 ast_mutex_unlock(&p->lock); 10449 break; 10450 case ISUP_EVENT_UBL: 10451 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc); 10452 if (chanpos < 0) { 10453 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic); 10454 break; 10455 } 10456 p = linkset->pvts[chanpos]; 10457 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic); 10458 ast_mutex_lock(&p->lock); 10459 p->remotelyblocked = 0; 10460 ast_mutex_unlock(&p->lock); 10461 isup_uba(linkset->ss7, e->ubl.cic, p->dpc); 10462 break; 10463 case ISUP_EVENT_UBA: 10464 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc); 10465 if (chanpos < 0) { 10466 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic); 10467 break; 10468 } 10469 p = linkset->pvts[chanpos]; 10470 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic); 10471 ast_mutex_lock(&p->lock); 10472 p->locallyblocked = 0; 10473 ast_mutex_unlock(&p->lock); 10474 break; 10475 case ISUP_EVENT_CON: 10476 case ISUP_EVENT_ANM: 10477 if (e->e == ISUP_EVENT_CON) 10478 cic = e->con.cic; 10479 else 10480 cic = e->anm.cic; 10481 10482 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc); 10483 if (chanpos < 0) { 10484 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic); 10485 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1); 10486 break; 10487 } else { 10488 p = linkset->pvts[chanpos]; 10489 ast_mutex_lock(&p->lock); 10490 p->subs[SUB_REAL].needanswer = 1; 10491 if (p->dsp && p->dsp_features) { 10492 ast_dsp_set_features(p->dsp, p->dsp_features); 10493 p->dsp_features = 0; 10494 } 10495 dahdi_enable_ec(p); 10496 ast_mutex_unlock(&p->lock); 10497 } 10498 break; 10499 case ISUP_EVENT_RLC: 10500 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc); 10501 if (chanpos < 0) { 10502 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic); 10503 break; 10504 } else { 10505 p = linkset->pvts[chanpos]; 10506 ast_mutex_lock(&p->lock); 10507 if (p->alreadyhungup) 10508 p->ss7call = NULL; 10509 else 10510 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n"); 10511 ast_mutex_unlock(&p->lock); 10512 } 10513 break; 10514 case ISUP_EVENT_FAA: 10515 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc); 10516 if (chanpos < 0) { 10517 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic); 10518 break; 10519 } else { 10520 p = linkset->pvts[chanpos]; 10521 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic); 10522 ast_mutex_lock(&p->lock); 10523 if (p->alreadyhungup){ 10524 p->ss7call = NULL; 10525 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n"); 10526 } 10527 ast_mutex_unlock(&p->lock); 10528 } 10529 break; 10530 default: 10531 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e)); 10532 break; 10533 } 10534 } 10535 ast_mutex_unlock(&linkset->lock); 10536 } 10537 10538 return 0; 10539 }
| static int ss7_pres_scr2cid_pres | ( | char | presentation_ind, | |
| char | screening_ind | |||
| ) | [static] |
Definition at line 10002 of file chan_dahdi.c.
Referenced by ss7_linkset().
| static void ss7_rel | ( | struct dahdi_ss7 * | ss7 | ) | [inline, static] |
Definition at line 1246 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_ss7::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().
01247 { 01248 ast_mutex_unlock(&ss7->lock); 01249 }
| static void ss7_reset_linkset | ( | struct dahdi_ss7 * | linkset | ) | [static] |
Definition at line 9820 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().
09821 { 09822 int i, startcic = -1, endcic, dpc; 09823 09824 if (linkset->numchans <= 0) 09825 return; 09826 09827 startcic = linkset->pvts[0]->cic; 09828 /* DB: CIC's DPC fix */ 09829 dpc = linkset->pvts[0]->dpc; 09830 09831 for (i = 0; i < linkset->numchans; i++) { 09832 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)) { 09833 continue; 09834 } else { 09835 endcic = linkset->pvts[i]->cic; 09836 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic); 09837 isup_grs(linkset->ss7, startcic, endcic, dpc); 09838 09839 /* DB: CIC's DPC fix */ 09840 if (linkset->pvts[i+1]) { 09841 startcic = linkset->pvts[i+1]->cic; 09842 dpc = linkset->pvts[i+1]->dpc; 09843 } 09844 } 09845 } 09846 }
| static struct dahdi_ss7* ss7_resolve_linkset | ( | int | linkset | ) | [static, read] |
Definition at line 8725 of file chan_dahdi.c.
References linksets, and NUM_SPANS.
Referenced by linkset_addsigchan(), mkintf(), and process_dahdi().
Definition at line 9860 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().
09861 { 09862 struct ss7 *ss7 = linkset->ss7; 09863 int res; 09864 int law = 1; 09865 struct ast_channel *c; 09866 char tmp[256]; 09867 09868 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 09869 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno)); 09870 09871 if (linkset->type == SS7_ITU) 09872 law = DAHDI_LAW_ALAW; 09873 else 09874 law = DAHDI_LAW_MULAW; 09875 09876 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law); 09877 if (res < 0) 09878 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel); 09879 09880 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) { 09881 p->proceeding = 1; 09882 isup_acm(ss7, p->ss7call); 09883 } 09884 09885 ast_mutex_unlock(&linkset->lock); 09886 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0); 09887 09888 if (!c) { 09889 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic); 09890 /* Holding this lock is assumed entering the function */ 09891 ast_mutex_lock(&linkset->lock); 09892 return; 09893 } else 09894 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic); 09895 09896 dahdi_enable_ec(p); 09897 09898 /* We only reference these variables in the context of the ss7_linkset function 09899 * when receiving either and IAM or a COT message. Since they are only accessed 09900 * from this context, we should be safe to unlock around them */ 09901 09902 ast_mutex_unlock(&p->lock); 09903 09904 if (!ast_strlen_zero(p->charge_number)) { 09905 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number); 09906 /* Clear this after we set it */ 09907 p->charge_number[0] = 0; 09908 } 09909 if (!ast_strlen_zero(p->gen_add_number)) { 09910 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number); 09911 /* Clear this after we set it */ 09912 p->gen_add_number[0] = 0; 09913 } 09914 if (!ast_strlen_zero(p->jip_number)) { 09915 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number); 09916 /* Clear this after we set it */ 09917 p->jip_number[0] = 0; 09918 } 09919 if (!ast_strlen_zero(p->gen_dig_number)) { 09920 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number); 09921 /* Clear this after we set it */ 09922 p->gen_dig_number[0] = 0; 09923 } 09924 if (!ast_strlen_zero(p->orig_called_num)) { 09925 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num); 09926 /* Clear this after we set it */ 09927 p->orig_called_num[0] = 0; 09928 } 09929 09930 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type); 09931 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp); 09932 /* Clear this after we set it */ 09933 p->gen_dig_type = 0; 09934 09935 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme); 09936 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp); 09937 /* Clear this after we set it */ 09938 p->gen_dig_scheme = 0; 09939 09940 if (!ast_strlen_zero(p->lspi_ident)) { 09941 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident); 09942 /* Clear this after we set it */ 09943 p->lspi_ident[0] = 0; 09944 } 09945 09946 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident); 09947 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp); 09948 /* Clear this after we set it */ 09949 p->call_ref_ident = 0; 09950 09951 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc); 09952 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp); 09953 /* Clear this after we set it */ 09954 p->call_ref_pc = 0; 09955 09956 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat); 09957 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp); 09958 /* Clear this after we set it */ 09959 p->calling_party_cat = 0; 09960 09961 if (!ast_strlen_zero(p->redirecting_num)) { 09962 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num); 09963 /* Clear this after we set it */ 09964 p->redirecting_num[0] = 0; 09965 } 09966 if (!ast_strlen_zero(p->generic_name)) { 09967 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name); 09968 /* Clear this after we set it */ 09969 p->generic_name[0] = 0; 09970 } 09971 09972 ast_mutex_lock(&p->lock); 09973 ast_mutex_lock(&linkset->lock); 09974 }
| static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6554 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_OVERLAPDIAL_INCOMING, dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, dahdi_pvt::exten, exten, 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, dahdi_pvt::inalarm, 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_pri::overlapdial, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, PVT_TO_CHANNEL, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, dahdi_pvt::span, ss_thread_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.
Referenced by dahdi_handle_event(), handle_init_event(), mwi_thread(), and pri_dchannel().
06555 { 06556 struct ast_channel *chan = data; 06557 struct dahdi_pvt *p = chan->tech_pvt; 06558 char exten[AST_MAX_EXTENSION] = ""; 06559 char exten2[AST_MAX_EXTENSION] = ""; 06560 unsigned char buf[256]; 06561 char dtmfcid[300]; 06562 char dtmfbuf[300]; 06563 struct callerid_state *cs = NULL; 06564 char *name = NULL, *number = NULL; 06565 int distMatches; 06566 int curRingData[3]; 06567 int receivedRingT; 06568 int counter1; 06569 int counter; 06570 int samples = 0; 06571 struct ast_smdi_md_message *smdi_msg = NULL; 06572 int flags = 0; 06573 int i; 06574 int timeout; 06575 int getforward = 0; 06576 char *s1, *s2; 06577 int len = 0; 06578 int res; 06579 int idx; 06580 06581 ast_mutex_lock(&ss_thread_lock); 06582 ss_thread_count++; 06583 ast_mutex_unlock(&ss_thread_lock); 06584 /* in the bizarre case where the channel has become a zombie before we 06585 even get started here, abort safely 06586 */ 06587 if (!p) { 06588 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06589 ast_hangup(chan); 06590 goto quit; 06591 } 06592 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 06593 idx = dahdi_get_index(chan, p, 1); 06594 if (idx < 0) { 06595 ast_log(LOG_WARNING, "Huh?\n"); 06596 ast_hangup(chan); 06597 goto quit; 06598 } 06599 if (p->dsp) 06600 ast_dsp_digitreset(p->dsp); 06601 switch (p->sig) { 06602 #ifdef HAVE_PRI 06603 case SIG_PRI: 06604 case SIG_BRI: 06605 case SIG_BRI_PTMP: 06606 /* Now loop looking for an extension */ 06607 ast_copy_string(exten, p->exten, sizeof(exten)); 06608 len = strlen(exten); 06609 res = 0; 06610 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06611 if (len && !ast_ignore_pattern(chan->context, exten)) 06612 tone_zone_play_tone(p->subs[idx].dfd, -1); 06613 else 06614 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06615 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06616 timeout = matchdigittimeout; 06617 else 06618 timeout = gendigittimeout; 06619 res = ast_waitfordigit(chan, timeout); 06620 if (res < 0) { 06621 ast_debug(1, "waitfordigit returned < 0...\n"); 06622 ast_hangup(chan); 06623 goto quit; 06624 } else if (res) { 06625 exten[len++] = res; 06626 exten[len] = '\0'; 06627 } else 06628 break; 06629 } 06630 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06631 if (ast_strlen_zero(exten)) { 06632 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n"); 06633 exten[0] = 's'; 06634 exten[1] = '\0'; 06635 } 06636 tone_zone_play_tone(p->subs[idx].dfd, -1); 06637 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06638 /* Start the real PBX */ 06639 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06640 if (p->dsp) { 06641 ast_dsp_digitreset(p->dsp); 06642 } 06643 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) { 06644 if (p->pri->pri) { 06645 if (!pri_grab(p, p->pri)) { 06646 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0); 06647 p->proceeding = 1; 06648 pri_rel(p->pri); 06649 } else { 06650 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06651 } 06652 } 06653 } 06654 dahdi_enable_ec(p); 06655 ast_setstate(chan, AST_STATE_RING); 06656 res = ast_pbx_run(chan); 06657 if (res) { 06658 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06659 } 06660 } else { 06661 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06662 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06663 ast_hangup(chan); 06664 p->exten[0] = '\0'; 06665 /* Since we send release complete here, we won't get one */ 06666 p->call = NULL; 06667 } 06668 goto quit; 06669 break; 06670 #endif 06671 case SIG_FEATD: 06672 case SIG_FEATDMF: 06673 case SIG_FEATDMF_TA: 06674 case SIG_E911: 06675 case SIG_FGC_CAMAMF: 06676 case SIG_FEATB: 06677 case SIG_EMWINK: 06678 case SIG_SF_FEATD: 06679 case SIG_SF_FEATDMF: 06680 case SIG_SF_FEATB: 06681 case SIG_SFWINK: 06682 if (dahdi_wink(p, idx)) 06683 goto quit; 06684 /* Fall through */ 06685 case SIG_EM: 06686 case SIG_EM_E1: 06687 case SIG_SF: 06688 case SIG_FGC_CAMA: 06689 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06690 if (p->dsp) 06691 ast_dsp_digitreset(p->dsp); 06692 /* set digit mode appropriately */ 06693 if (p->dsp) { 06694 if (NEED_MFDETECT(p)) 06695 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06696 else 06697 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06698 } 06699 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06700 /* Wait for the first digit only if immediate=no */ 06701 if (!p->immediate) 06702 /* Wait for the first digit (up to 5 seconds). */ 06703 res = ast_waitfordigit(chan, 5000); 06704 else 06705 res = 0; 06706 if (res > 0) { 06707 /* save first char */ 06708 dtmfbuf[0] = res; 06709 switch (p->sig) { 06710 case SIG_FEATD: 06711 case SIG_SF_FEATD: 06712 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06713 if (res > 0) 06714 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06715 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06716 break; 06717 case SIG_FEATDMF_TA: 06718 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06719 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06720 if (dahdi_wink(p, idx)) goto quit; 06721 dtmfbuf[0] = 0; 06722 /* Wait for the first digit (up to 5 seconds). */ 06723 res = ast_waitfordigit(chan, 5000); 06724 if (res <= 0) break; 06725 dtmfbuf[0] = res; 06726 /* fall through intentionally */ 06727 case SIG_FEATDMF: 06728 case SIG_E911: 06729 case SIG_FGC_CAMAMF: 06730 case SIG_SF_FEATDMF: 06731 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06732 /* if international caca, do it again to get real ANO */ 06733 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06734 { 06735 if (dahdi_wink(p, idx)) goto quit; 06736 dtmfbuf[0] = 0; 06737 /* Wait for the first digit (up to 5 seconds). */ 06738 res = ast_waitfordigit(chan, 5000); 06739 if (res <= 0) break; 06740 dtmfbuf[0] = res; 06741 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06742 } 06743 if (res > 0) { 06744 /* if E911, take off hook */ 06745 if (p->sig == SIG_E911) 06746 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06747 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06748 } 06749 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06750 break; 06751 case SIG_FEATB: 06752 case SIG_SF_FEATB: 06753 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06754 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06755 break; 06756 case SIG_EMWINK: 06757 /* if we received a '*', we are actually receiving Feature Group D 06758 dial syntax, so use that mode; otherwise, fall through to normal 06759 mode 06760 */ 06761 if (res == '*') { 06762 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06763 if (res > 0) 06764 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06765 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06766 break; 06767 } 06768 default: 06769 /* If we got the first digit, get the rest */ 06770 len = 1; 06771 dtmfbuf[len] = '\0'; 06772 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06773 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06774 timeout = matchdigittimeout; 06775 } else { 06776 timeout = gendigittimeout; 06777 } 06778 res = ast_waitfordigit(chan, timeout); 06779 if (res < 0) { 06780 ast_debug(1, "waitfordigit returned < 0...\n"); 06781 ast_hangup(chan); 06782 goto quit; 06783 } else if (res) { 06784 dtmfbuf[len++] = res; 06785 dtmfbuf[len] = '\0'; 06786 } else { 06787 break; 06788 } 06789 } 06790 break; 06791 } 06792 } 06793 if (res == -1) { 06794 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06795 ast_hangup(chan); 06796 goto quit; 06797 } else if (res < 0) { 06798 ast_debug(1, "Got hung up before digits finished\n"); 06799 ast_hangup(chan); 06800 goto quit; 06801 } 06802 06803 if (p->sig == SIG_FGC_CAMA) { 06804 char anibuf[100]; 06805 06806 if (ast_safe_sleep(chan,1000) == -1) { 06807 ast_hangup(chan); 06808 goto quit; 06809 } 06810 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06811 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06812 res = my_getsigstr(chan, anibuf, "#", 10000); 06813 if ((res > 0) && (strlen(anibuf) > 2)) { 06814 if (anibuf[strlen(anibuf) - 1] == '#') 06815 anibuf[strlen(anibuf) - 1] = 0; 06816 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06817 } 06818 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06819 } 06820 06821 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06822 if (ast_strlen_zero(exten)) 06823 ast_copy_string(exten, "s", sizeof(exten)); 06824 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06825 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06826 if (exten[0] == '*') { 06827 char *stringp=NULL; 06828 ast_copy_string(exten2, exten, sizeof(exten2)); 06829 /* Parse out extension and callerid */ 06830 stringp=exten2 +1; 06831 s1 = strsep(&stringp, "*"); 06832 s2 = strsep(&stringp, "*"); 06833 if (s2) { 06834 if (!ast_strlen_zero(p->cid_num)) 06835 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06836 else 06837 ast_set_callerid(chan, s1, NULL, s1); 06838 ast_copy_string(exten, s2, sizeof(exten)); 06839 } else 06840 ast_copy_string(exten, s1, sizeof(exten)); 06841 } else if (p->sig == SIG_FEATD) 06842 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06843 } 06844 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06845 if (exten[0] == '*') { 06846 char *stringp=NULL; 06847 ast_copy_string(exten2, exten, sizeof(exten2)); 06848 /* Parse out extension and callerid */ 06849 stringp=exten2 +1; 06850 s1 = strsep(&stringp, "#"); 06851 s2 = strsep(&stringp, "#"); 06852 if (s2) { 06853 if (!ast_strlen_zero(p->cid_num)) 06854 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06855 else 06856 if (*(s1 + 2)) 06857 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06858 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06859 } else 06860 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06861 } else 06862 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06863 } 06864 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06865 if (exten[0] == '*') { 06866 char *stringp=NULL; 06867 ast_copy_string(exten2, exten, sizeof(exten2)); 06868 /* Parse out extension and callerid */ 06869 stringp=exten2 +1; 06870 s1 = strsep(&stringp, "#"); 06871 s2 = strsep(&stringp, "#"); 06872 if (s2 && (*(s2 + 1) == '0')) { 06873 if (*(s2 + 2)) 06874 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06875 } 06876 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06877 else ast_copy_string(exten, "911", sizeof(exten)); 06878 } else 06879 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06880 } 06881 if (p->sig == SIG_FEATB) { 06882 if (exten[0] == '*') { 06883 char *stringp=NULL; 06884 ast_copy_string(exten2, exten, sizeof(exten2)); 06885 /* Parse out extension and callerid */ 06886 stringp=exten2 +1; 06887 s1 = strsep(&stringp, "#"); 06888 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06889 } else 06890 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06891 } 06892 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06893 dahdi_wink(p, idx); 06894 /* some switches require a minimum guard time between 06895 the last FGD wink and something that answers 06896 immediately. This ensures it */ 06897 if (ast_safe_sleep(chan,100)) goto quit; 06898 } 06899 dahdi_enable_ec(p); 06900 if (NEED_MFDETECT(p)) { 06901 if (p->dsp) { 06902 if (!p->hardwaredtmf) 06903 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06904 else { 06905 ast_dsp_free(p->dsp); 06906 p->dsp = NULL; 06907 } 06908 } 06909 } 06910 06911 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06912 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06913 if (p->dsp) ast_dsp_digitreset(p->dsp); 06914 res = ast_pbx_run(chan); 06915 if (res) { 06916 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06917 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06918 } 06919 goto quit; 06920 } else { 06921 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06922 sleep(2); 06923 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 06924 if (res < 0) 06925 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06926 else 06927 sleep(1); 06928 res = ast_streamfile(chan, "ss-noservice", chan->language); 06929 if (res >= 0) 06930 ast_waitstream(chan, ""); 06931 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06932 ast_hangup(chan); 06933 goto quit; 06934 } 06935 break; 06936 case SIG_FXOLS: 06937 case SIG_FXOGS: 06938 case SIG_FXOKS: 06939 /* Read the first digit */ 06940 timeout = firstdigittimeout; 06941 /* If starting a threeway call, never timeout on the first digit so someone 06942 can use flash-hook as a "hold" feature */ 06943 if (p->subs[SUB_THREEWAY].owner) 06944 timeout = 999999; 06945 while (len < AST_MAX_EXTENSION-1) { 06946 /* Read digit unless it's supposed to be immediate, in which case the 06947 only answer is 's' */ 06948 if (p->immediate) 06949 res = 's'; 06950 else 06951 res = ast_waitfordigit(chan, timeout); 06952 timeout = 0; 06953 if (res < 0) { 06954 ast_debug(1, "waitfordigit returned < 0...\n"); 06955 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06956 ast_hangup(chan); 06957 goto quit; 06958 } else if (res) { 06959 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 06960 exten[len++]=res; 06961 exten[len] = '\0'; 06962 } 06963 if (!ast_ignore_pattern(chan->context, exten)) 06964 tone_zone_play_tone(p->subs[idx].dfd, -1); 06965 else 06966 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06967 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06968 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06969 if (getforward) { 06970 /* Record this as the forwarding extension */ 06971 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06972 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06973 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 06974 if (res) 06975 break; 06976 usleep(500000); 06977 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06978 sleep(1); 06979 memset(exten, 0, sizeof(exten)); 06980 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06981 len = 0; 06982 getforward = 0; 06983 } else { 06984 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06985 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06986 if (!ast_strlen_zero(p->cid_num)) { 06987 if (!p->hidecallerid) 06988 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06989 else 06990 ast_set_callerid(chan, NULL, NULL, p->cid_num); 06991 } 06992 if (!ast_strlen_zero(p->cid_name)) { 06993 if (!p->hidecallerid) 06994 ast_set_callerid(chan, NULL, p->cid_name, NULL); 06995 } 06996 ast_setstate(chan, AST_STATE_RING); 06997 dahdi_enable_ec(p); 06998 res = ast_pbx_run(chan); 06999 if (res) { 07000 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07001 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07002 } 07003 goto quit; 07004 } 07005 } else { 07006 /* It's a match, but they just typed a digit, and there is an ambiguous match, 07007 so just set the timeout to matchdigittimeout and wait some more */ 07008 timeout = matchdigittimeout; 07009 } 07010 } else if (res == 0) { 07011 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 07012 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07013 dahdi_wait_event(p->subs[idx].dfd); 07014 ast_hangup(chan); 07015 goto quit; 07016 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07017 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 07018 /* Disable call waiting if enabled */ 07019 p->callwaiting = 0; 07020 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07021 if (res) { 07022 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07023 chan->name, strerror(errno)); 07024 } 07025 len = 0; 07026 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 07027 memset(exten, 0, sizeof(exten)); 07028 timeout = firstdigittimeout; 07029 07030 } else if (!strcmp(exten,ast_pickup_ext())) { 07031 /* Scan all channels and see if there are any 07032 * ringing channels that have call groups 07033 * that equal this channels pickup group 07034 */ 07035 if (idx == SUB_REAL) { 07036 /* Switch us from Third call to Call Wait */ 07037 if (p->subs[SUB_THREEWAY].owner) { 07038 /* If you make a threeway call and the *8# a call, it should actually 07039 look like a callwait */ 07040 alloc_sub(p, SUB_CALLWAIT); 07041 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07042 unalloc_sub(p, SUB_THREEWAY); 07043 } 07044 dahdi_enable_ec(p); 07045 if (ast_pickup_call(chan)) { 07046 ast_debug(1, "No call pickup possible...\n"); 07047 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07048 dahdi_wait_event(p->subs[idx].dfd); 07049 } 07050 ast_hangup(chan); 07051 goto quit; 07052 } else { 07053 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07054 ast_hangup(chan); 07055 goto quit; 07056 } 07057 07058 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07059 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 07060 /* Disable Caller*ID if enabled */ 07061 p->hidecallerid = 1; 07062 if (chan->cid.cid_num) 07063 ast_free(chan->cid.cid_num); 07064 chan->cid.cid_num = NULL; 07065 if (chan->cid.cid_name) 07066 ast_free(chan->cid.cid_name); 07067 chan->cid.cid_name = NULL; 07068 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07069 if (res) { 07070 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07071 chan->name, strerror(errno)); 07072 } 07073 len = 0; 07074 memset(exten, 0, sizeof(exten)); 07075 timeout = firstdigittimeout; 07076 } else if (p->callreturn && !strcmp(exten, "*69")) { 07077 res = 0; 07078 if (!ast_strlen_zero(p->lastcid_num)) { 07079 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07080 } 07081 if (!res) 07082 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07083 break; 07084 } else if (!strcmp(exten, "*78")) { 07085 dahdi_dnd(p, 1); 07086 /* Do not disturb */ 07087 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07088 getforward = 0; 07089 memset(exten, 0, sizeof(exten)); 07090 len = 0; 07091 } else if (!strcmp(exten, "*79")) { 07092 dahdi_dnd(p, 0); 07093 /* Do not disturb */ 07094 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07095 getforward = 0; 07096 memset(exten, 0, sizeof(exten)); 07097 len = 0; 07098 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07099 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07100 getforward = 1; 07101 memset(exten, 0, sizeof(exten)); 07102 len = 0; 07103 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07104 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 07105 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07106 memset(p->call_forward, 0, sizeof(p->call_forward)); 07107 getforward = 0; 07108 memset(exten, 0, sizeof(exten)); 07109 len = 0; 07110 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07111 p->subs[SUB_THREEWAY].owner && 07112 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07113 /* This is a three way call, the main call being a real channel, 07114 and we're parking the first call. */ 07115 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07116 ast_verb(3, "Parking call to '%s'\n", chan->name); 07117 break; 07118 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07119 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); 07120 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07121 if (!res) { 07122 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07123 memset(exten, 0, sizeof(exten)); 07124 len = 0; 07125 } 07126 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07127 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 07128 /* Enable Caller*ID if enabled */ 07129 p->hidecallerid = 0; 07130 if (chan->cid.cid_num) 07131 ast_free(chan->cid.cid_num); 07132 chan->cid.cid_num = NULL; 07133 if (chan->cid.cid_name) 07134 ast_free(chan->cid.cid_name); 07135 chan->cid.cid_name = NULL; 07136 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07137 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07138 if (res) { 07139 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07140 chan->name, strerror(errno)); 07141 } 07142 len = 0; 07143 memset(exten, 0, sizeof(exten)); 07144 timeout = firstdigittimeout; 07145 } else if (!strcmp(exten, "*0")) { 07146 struct ast_channel *nbridge = 07147 p->subs[SUB_THREEWAY].owner; 07148 struct dahdi_pvt *pbridge = NULL; 07149 /* set up the private struct of the bridged one, if any */ 07150 if (nbridge && ast_bridged_channel(nbridge)) 07151 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07152 if (nbridge && pbridge && 07153 (nbridge->tech == &dahdi_tech) && 07154 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 07155 ISTRUNK(pbridge)) { 07156 int func = DAHDI_FLASH; 07157 /* Clear out the dial buffer */ 07158 p->dop.dialstr[0] = '\0'; 07159 /* flash hookswitch */ 07160 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07161 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07162 nbridge->name, strerror(errno)); 07163 } 07164 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07165 unalloc_sub(p, SUB_THREEWAY); 07166 p->owner = p->subs[SUB_REAL].owner; 07167 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07168 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07169 ast_hangup(chan); 07170 goto quit; 07171 } else { 07172 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07173 dahdi_wait_event(p->subs[idx].dfd); 07174 tone_zone_play_tone(p->subs[idx].dfd, -1); 07175 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07176 unalloc_sub(p, SUB_THREEWAY); 07177 p->owner = p->subs[SUB_REAL].owner; 07178 ast_hangup(chan); 07179 goto quit; 07180 } 07181 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07182 ((exten[0] != '*') || (strlen(exten) > 2))) { 07183 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); 07184 break; 07185 } 07186 if (!timeout) 07187 timeout = gendigittimeout; 07188 if (len && !ast_ignore_pattern(chan->context, exten)) 07189 tone_zone_play_tone(p->subs[idx].dfd, -1); 07190 } 07191 break; 07192 case SIG_FXSLS: 07193 case SIG_FXSGS: 07194 case SIG_FXSKS: 07195 #ifdef HAVE_PRI 07196 if (p->pri) { 07197 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07198 struct ast_frame *f; 07199 int res; 07200 time_t start; 07201 07202 time(&start); 07203 ast_setstate(chan, AST_STATE_RING); 07204 while (time(NULL) < start + 3) { 07205 res = ast_waitfor(chan, 1000); 07206 if (res) { 07207 f = ast_read(chan); 07208 if (!f) { 07209 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07210 ast_hangup(chan); 07211 goto quit; 07212 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07213 res = 1; 07214 } else 07215 res = 0; 07216 ast_frfree(f); 07217 if (res) { 07218 ast_debug(1, "Got ring!\n"); 07219 res = 0; 07220 break; 07221 } 07222 } 07223 } 07224 } 07225 #endif 07226 /* check for SMDI messages */ 07227 if (p->use_smdi && p->smdi_iface) { 07228 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07229 07230 if (smdi_msg != NULL) { 07231 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07232 07233 if (smdi_msg->type == 'B') 07234 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07235 else if (smdi_msg->type == 'N') 07236 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07237 07238 ast_debug(1, "Received SMDI message on %s\n", chan->name); 07239 } else { 07240 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07241 } 07242 } 07243 07244 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07245 number = smdi_msg->calling_st; 07246 07247 /* If we want caller id, we're in a prering state due to a polarity reversal 07248 * and we're set to use a polarity reversal to trigger the start of caller id, 07249 * grab the caller id and wait for ringing to start... */ 07250 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { 07251 /* If set to use DTMF CID signalling, listen for DTMF */ 07252 if (p->cid_signalling == CID_SIG_DTMF) { 07253 int k = 0; 07254 cs = NULL; 07255 ast_debug(1, "Receiving DTMF cid on " 07256 "channel %s\n", chan->name); 07257 dahdi_setlinear(p->subs[idx].dfd, 0); 07258 res = 2000; 07259 for (;;) { 07260 struct ast_frame *f; 07261 res = ast_waitfor(chan, res); 07262 if (res <= 0) { 07263 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07264 "Exiting simple switch\n"); 07265 ast_hangup(chan); 07266 goto quit; 07267 } 07268 f = ast_read(chan); 07269 if (!f) 07270 break; 07271 if (f->frametype == AST_FRAME_DTMF) { 07272 dtmfbuf[k++] = f->subclass; 07273 ast_debug(1, "CID got digit '%c'\n", f->subclass); 07274 res = 2000; 07275 } 07276 ast_frfree(f); 07277 if (chan->_state == AST_STATE_RING || 07278 chan->_state == AST_STATE_RINGING) 07279 break; /* Got ring */ 07280 } 07281 dtmfbuf[k] = '\0'; 07282 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07283 /* Got cid and ring. */ 07284 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 07285 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07286 ast_debug(1, "CID is '%s', flags %d\n", 07287 dtmfcid, flags); 07288 /* If first byte is NULL, we have no cid */ 07289 if (!ast_strlen_zero(dtmfcid)) 07290 number = dtmfcid; 07291 else 07292 number = NULL; 07293 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07294 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07295 cs = callerid_new(p->cid_signalling); 07296 if (cs) { 07297 samples = 0; 07298 #if 1 07299 bump_gains(p); 07300 #endif 07301 /* Take out of linear mode for Caller*ID processing */ 07302 dahdi_setlinear(p->subs[idx].dfd, 0); 07303 07304 /* First we wait and listen for the Caller*ID */ 07305 for (;;) { 07306 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07307 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07308 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07309 callerid_free(cs); 07310 ast_hangup(chan); 07311 goto quit; 07312 } 07313 if (i & DAHDI_IOMUX_SIGEVENT) { 07314 res = dahdi_get_event(p->subs[idx].dfd); 07315 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07316 if (res == DAHDI_EVENT_NOALARM) { 07317 p->inalarm = 0; 07318 } 07319 07320 if (p->cid_signalling == CID_SIG_V23_JP) { 07321 if (res == DAHDI_EVENT_RINGBEGIN) { 07322 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07323 usleep(1); 07324 } 07325 } else { 07326 res = 0; 07327 break; 07328 } 07329 } else if (i & DAHDI_IOMUX_READ) { 07330 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07331 if (res < 0) { 07332 if (errno != ELAST) { 07333 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07334 callerid_free(cs); 07335 ast_hangup(chan); 07336 goto quit; 07337 } 07338 break; 07339 } 07340 samples += res; 07341 07342 if (p->cid_signalling == CID_SIG_V23_JP) { 07343 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07344 } else { 07345 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07346 } 07347 07348 if (res < 0) { 07349 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07350 break; 07351 } else if (res) 07352 break; 07353 else if (samples > (8000 * 10)) 07354 break; 07355 } 07356 } 07357 if (res == 1) { 07358 callerid_get(cs, &name, &number, &flags); 07359 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07360 } 07361 07362 if (p->cid_signalling == CID_SIG_V23_JP) { 07363 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07364 usleep(1); 07365 res = 4000; 07366 } else { 07367 07368 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07369 res = 2000; 07370 } 07371 07372 for (;;) { 07373 struct ast_frame *f; 07374 res = ast_waitfor(chan, res); 07375 if (res <= 0) { 07376 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07377 "Exiting simple switch\n"); 07378 ast_hangup(chan); 07379 goto quit; 07380 } 07381 if (!(f = ast_read(chan))) { 07382 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07383 ast_hangup(chan); 07384 goto quit; 07385 } 07386 ast_frfree(f); 07387 if (chan->_state == AST_STATE_RING || 07388 chan->_state == AST_STATE_RINGING) 07389 break; /* Got ring */ 07390 } 07391 07392 /* We must have a ring by now, so, if configured, lets try to listen for 07393 * distinctive ringing */ 07394 if (p->usedistinctiveringdetection) { 07395 len = 0; 07396 distMatches = 0; 07397 /* Clear the current ring data array so we dont have old data in it. */ 07398 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07399 curRingData[receivedRingT] = 0; 07400 receivedRingT = 0; 07401 counter = 0; 07402 counter1 = 0; 07403 /* Check to see if context is what it should be, if not set to be. */ 07404 if (strcmp(p->context,p->defcontext) != 0) { 07405 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07406 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07407 } 07408 07409 for (;;) { 07410 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07411 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07412 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07413 callerid_free(cs); 07414 ast_hangup(chan); 07415 goto quit; 07416 } 07417 if (i & DAHDI_IOMUX_SIGEVENT) { 07418 res = dahdi_get_event(p->subs[idx].dfd); 07419 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07420 if (res == DAHDI_EVENT_NOALARM) { 07421 p->inalarm = 0; 07422 } 07423 res = 0; 07424 /* Let us detect distinctive ring */ 07425 07426 curRingData[receivedRingT] = p->ringt; 07427 07428 if (p->ringt < p->ringt_base/2) 07429 break; 07430 /* Increment the ringT counter so we can match it against 07431 values in chan_dahdi.conf for distinctive ring */ 07432 if (++receivedRingT == ARRAY_LEN(curRingData)) 07433 break; 07434 } else if (i & DAHDI_IOMUX_READ) { 07435 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07436 if (res < 0) { 07437 if (errno != ELAST) { 07438 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07439 callerid_free(cs); 07440 ast_hangup(chan); 07441 goto quit; 07442 } 07443 break; 07444 } 07445 if (p->ringt) 07446 p->ringt--; 07447 if (p->ringt == 1) { 07448 res = -1; 07449 break; 07450 } 07451 } 07452 } 07453 /* this only shows up if you have n of the dring patterns filled in */ 07454 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07455 for (counter = 0; counter < 3; counter++) { 07456 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07457 channel */ 07458 distMatches = 0; 07459 for (counter1 = 0; counter1 < 3; counter1++) { 07460 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07461 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07462 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07463 curRingData[counter1]); 07464 distMatches++; 07465 } 07466 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07467 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07468 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07469 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07470 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07471 distMatches++; 07472 } 07473 } 07474 07475 if (distMatches == 3) { 07476 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07477 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07478 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07479 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07480 break; 07481 } 07482 } 07483 } 07484 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07485 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07486 #if 1 07487 restore_gains(p); 07488 #endif 07489 } else 07490 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07491 } else { 07492 ast_log(LOG_WARNING, "Channel %s in prering " 07493 "state, but I have nothing to do. " 07494 "Terminating simple switch, should be " 07495 "restarted by the actual ring.\n", 07496 chan->name); 07497 ast_hangup(chan); 07498 goto quit; 07499 } 07500 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07501 if (p->cid_signalling == CID_SIG_DTMF) { 07502 int k = 0; 07503 cs = NULL; 07504 dahdi_setlinear(p->subs[idx].dfd, 0); 07505 res = 2000; 07506 for (;;) { 07507 struct ast_frame *f; 07508 res = ast_waitfor(chan, res); 07509 if (res <= 0) { 07510 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07511 "Exiting simple switch\n"); 07512 ast_hangup(chan); 07513 return NULL; 07514 } 07515 f = ast_read(chan); 07516 if (f->frametype == AST_FRAME_DTMF) { 07517 dtmfbuf[k++] = f->subclass; 07518 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07519 res = 2000; 07520 } 07521 ast_frfree(f); 07522 07523 if (p->ringt_base == p->ringt) 07524 break; 07525 07526 } 07527 dtmfbuf[k] = '\0'; 07528 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07529 /* Got cid and ring. */ 07530 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07531 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07532 dtmfcid, flags); 07533 /* If first byte is NULL, we have no cid */ 07534 if (!ast_strlen_zero(dtmfcid)) 07535 number = dtmfcid; 07536 else 07537 number = NULL; 07538 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07539 } else { 07540 /* FSK Bell202 callerID */ 07541 cs = callerid_new(p->cid_signalling); 07542 if (cs) { 07543 #if 1 07544 bump_gains(p); 07545 #endif 07546 samples = 0; 07547 len = 0; 07548 distMatches = 0; 07549 /* Clear the current ring data array so we dont have old data in it. */ 07550 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07551 curRingData[receivedRingT] = 0; 07552 receivedRingT = 0; 07553 counter = 0; 07554 counter1 = 0; 07555 /* Check to see if context is what it should be, if not set to be. */ 07556 if (strcmp(p->context,p->defcontext) != 0) { 07557 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07558 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07559 } 07560 07561 /* Take out of linear mode for Caller*ID processing */ 07562 dahdi_setlinear(p->subs[idx].dfd, 0); 07563 for (;;) { 07564 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07565 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07566 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07567 callerid_free(cs); 07568 ast_hangup(chan); 07569 goto quit; 07570 } 07571 if (i & DAHDI_IOMUX_SIGEVENT) { 07572 res = dahdi_get_event(p->subs[idx].dfd); 07573 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07574 if (res == DAHDI_EVENT_NOALARM) { 07575 p->inalarm = 0; 07576 } 07577 /* If we get a PR event, they hung up while processing calerid */ 07578 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07579 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07580 p->polarity = POLARITY_IDLE; 07581 callerid_free(cs); 07582 ast_hangup(chan); 07583 goto quit; 07584 } 07585 res = 0; 07586 /* Let us detect callerid when the telco uses distinctive ring */ 07587 07588 curRingData[receivedRingT] = p->ringt; 07589 07590 if (p->ringt < p->ringt_base/2) 07591 break; 07592 /* Increment the ringT counter so we can match it against 07593 values in chan_dahdi.conf for distinctive ring */ 07594 if (++receivedRingT == ARRAY_LEN(curRingData)) 07595 break; 07596 } else if (i & DAHDI_IOMUX_READ) { 07597 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07598 if (res < 0) { 07599 if (errno != ELAST) { 07600 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07601 callerid_free(cs); 07602 ast_hangup(chan); 07603 goto quit; 07604 } 07605 break; 07606 } 07607 if (p->ringt) 07608 p->ringt--; 07609 if (p->ringt == 1) { 07610 res = -1; 07611 break; 07612 } 07613 samples += res; 07614 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07615 if (res < 0) { 07616 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07617 break; 07618 } else if (res) 07619 break; 07620 else if (samples > (8000 * 10)) 07621 break; 07622 } 07623 } 07624 if (res == 1) { 07625 callerid_get(cs, &name, &number, &flags); 07626 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07627 } 07628 if (distinctiveringaftercid == 1) { 07629 /* Clear the current ring data array so we dont have old data in it. */ 07630 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07631 curRingData[receivedRingT] = 0; 07632 } 07633 receivedRingT = 0; 07634 ast_verb(3, "Detecting post-CID distinctive ring\n"); 07635 for (;;) { 07636 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07637 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07638 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07639 callerid_free(cs); 07640 ast_hangup(chan); 07641 goto quit; 07642 } 07643 if (i & DAHDI_IOMUX_SIGEVENT) { 07644 res = dahdi_get_event(p->subs[idx].dfd); 07645 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07646 if (res == DAHDI_EVENT_NOALARM) { 07647 p->inalarm = 0; 07648 } 07649 res = 0; 07650 /* Let us detect callerid when the telco uses distinctive ring */ 07651 07652 curRingData[receivedRingT] = p->ringt; 07653 07654 if (p->ringt < p->ringt_base/2) 07655 break; 07656 /* Increment the ringT counter so we can match it against 07657 values in chan_dahdi.conf for distinctive ring */ 07658 if (++receivedRingT == ARRAY_LEN(curRingData)) 07659 break; 07660 } else if (i & DAHDI_IOMUX_READ) { 07661 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07662 if (res < 0) { 07663 if (errno != ELAST) { 07664 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07665 callerid_free(cs); 07666 ast_hangup(chan); 07667 goto quit; 07668 } 07669 break; 07670 } 07671 if (p->ringt) 07672 p->ringt--; 07673 if (p->ringt == 1) { 07674 res = -1; 07675 break; 07676 } 07677 } 07678 } 07679 } 07680 if (p->usedistinctiveringdetection) { 07681 /* this only shows up if you have n of the dring patterns filled in */ 07682 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07683 07684 for (counter = 0; counter < 3; counter++) { 07685 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07686 channel */ 07687 /* this only shows up if you have n of the dring patterns filled in */ 07688 ast_verb(3, "Checking %d,%d,%d\n", 07689 p->drings.ringnum[counter].ring[0], 07690 p->drings.ringnum[counter].ring[1], 07691 p->drings.ringnum[counter].ring[2]); 07692 distMatches = 0; 07693 for (counter1 = 0; counter1 < 3; counter1++) { 07694 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07695 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07696 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07697 curRingData[counter1]); 07698 distMatches++; 07699 } 07700 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07701 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07702 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07703 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07704 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07705 distMatches++; 07706 } 07707 } 07708 if (distMatches == 3) { 07709 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07710 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07711 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07712 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07713 break; 07714 } 07715 } 07716 } 07717 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07718 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07719 #if 1 07720 restore_gains(p); 07721 #endif 07722 if (res < 0) { 07723 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07724 } 07725 } else 07726 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07727 } 07728 } 07729 else 07730 cs = NULL; 07731 07732 if (number) 07733 ast_shrink_phone_number(number); 07734 ast_set_callerid(chan, number, name, number); 07735 07736 if (smdi_msg) 07737 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07738 07739 if (cs) 07740 callerid_free(cs); 07741 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 07742 if (flags & CID_MSGWAITING) { 07743 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel); 07744 notify_message(p->mailbox, 1); 07745 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07746 if (p->mwimonitor_rpas) { 07747 ast_hangup(chan); 07748 return NULL; 07749 } 07750 } else if (flags & CID_NOMSGWAITING) { 07751 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel); 07752 notify_message(p->mailbox, 0); 07753 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07754 if (p->mwimonitor_rpas) { 07755 ast_hangup(chan); 07756 return NULL; 07757 } 07758 } 07759 07760 ast_setstate(chan, AST_STATE_RING); 07761 chan->rings = 1; 07762 p->ringt = p->ringt_base; 07763 res = ast_pbx_run(chan); 07764 if (res) { 07765 ast_hangup(chan); 07766 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07767 } 07768 goto quit; 07769 default: 07770 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07771 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07772 if (res < 0) 07773 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07774 } 07775 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07776 if (res < 0) 07777 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07778 ast_hangup(chan); 07779 quit: 07780 ast_mutex_lock(&ss_thread_lock); 07781 ss_thread_count--; 07782 ast_cond_signal(&ss_thread_complete); 07783 ast_mutex_unlock(&ss_thread_lock); 07784 return NULL; 07785 }
| static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 12044 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().
12045 { 12046 int res, x; 12047 struct dahdi_params p; 12048 struct dahdi_bufferinfo bi; 12049 struct dahdi_spaninfo si; 12050 int i; 12051 12052 for (i = 0; i < NUM_DCHANS; i++) { 12053 if (!pri->dchannels[i]) 12054 break; 12055 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR); 12056 x = pri->dchannels[i]; 12057 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 12058 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 12059 return -1; 12060 } 12061 memset(&p, 0, sizeof(p)); 12062 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 12063 if (res) { 12064 dahdi_close_pri_fd(pri, i); 12065 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 12066 return -1; 12067 } 12068 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 12069 dahdi_close_pri_fd(pri, i); 12070 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 12071 return -1; 12072 } 12073 memset(&si, 0, sizeof(si)); 12074 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 12075 if (res) { 12076 dahdi_close_pri_fd(pri, i); 12077 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 12078 } 12079 if (!si.alarms) 12080 pri->dchanavail[i] |= DCHAN_NOTINALARM; 12081 else 12082 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 12083 memset(&bi, 0, sizeof(bi)); 12084 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 12085 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 12086 bi.numbufs = 32; 12087 bi.bufsize = 1024; 12088 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 12089 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 12090 dahdi_close_pri_fd(pri, i); 12091 return -1; 12092 } 12093 switch (pri->sig) { 12094 case SIG_BRI: 12095 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype); 12096 break; 12097 case SIG_BRI_PTMP: 12098 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype); 12099 break; 12100 default: 12101 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 12102 } 12103 /* Force overlap dial if we're doing GR-303! */ 12104 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 12105 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 12106 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 12107 #ifdef HAVE_PRI_INBANDDISCONNECT 12108 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 12109 #endif 12110 /* Enslave to master if appropriate */ 12111 if (i) 12112 pri_enslave(pri->dchans[0], pri->dchans[i]); 12113 if (!pri->dchans[i]) { 12114 dahdi_close_pri_fd(pri, i); 12115 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 12116 return -1; 12117 } 12118 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 12119 pri_set_nsf(pri->dchans[i], pri->nsf); 12120 #ifdef PRI_GETSET_TIMERS 12121 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12122 if (pritimers[x] != 0) 12123 pri_set_timer(pri->dchans[i], x, pritimers[x]); 12124 } 12125 #endif 12126 } 12127 /* Assume primary is the one we use */ 12128 pri->pri = pri->dchans[0]; 12129 pri->resetpos = -1; 12130 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 12131 for (i = 0; i < NUM_DCHANS; i++) { 12132 if (!pri->dchannels[i]) 12133 break; 12134 dahdi_close_pri_fd(pri, i); 12135 } 12136 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 12137 return -1; 12138 } 12139 return 0; 12140 }
| static void swap_subs | ( | struct dahdi_pvt * | p, | |
| int | a, | |||
| int | b | |||
| ) | [static] |
Definition at line 1409 of file chan_dahdi.c.
References ast_channel_set_fd(), ast_debug, dahdi_subchannel::chan, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01410 { 01411 int tchan; 01412 int tinthreeway; 01413 struct ast_channel *towner; 01414 01415 ast_debug(1, "Swapping %d and %d\n", a, b); 01416 01417 tchan = p->subs[a].chan; 01418 towner = p->subs[a].owner; 01419 tinthreeway = p->subs[a].inthreeway; 01420 01421 p->subs[a].chan = p->subs[b].chan; 01422 p->subs[a].owner = p->subs[b].owner; 01423 p->subs[a].inthreeway = p->subs[b].inthreeway; 01424 01425 p->subs[b].chan = tchan; 01426 p->subs[b].owner = towner; 01427 p->subs[b].inthreeway = tinthreeway; 01428 01429 if (p->subs[a].owner) 01430 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 01431 if (p->subs[b].owner) 01432 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 01433 wakeup_sub(p, a, NULL); 01434 wakeup_sub(p, b, NULL); 01435 }
| static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 1559 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.
Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01560 { 01561 if (!x) { 01562 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01563 return -1; 01564 } 01565 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 01566 dahdi_close_sub(p, x); 01567 p->subs[x].linear = 0; 01568 p->subs[x].chan = 0; 01569 p->subs[x].owner = NULL; 01570 p->subs[x].inthreeway = 0; 01571 p->polarity = POLARITY_IDLE; 01572 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01573 return 0; 01574 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 14135 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), linksets, lock, NUM_SPANS, and pris.
14136 { 14137 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14138 int y; 14139 #endif 14140 #ifdef HAVE_PRI 14141 for (y = 0; y < NUM_SPANS; y++) 14142 ast_mutex_destroy(&pris[y].lock); 14143 #endif 14144 #ifdef HAVE_SS7 14145 for (y = 0; y < NUM_SPANS; y++) 14146 ast_mutex_destroy(&linksets[y].lock); 14147 #endif /* HAVE_SS7 */ 14148 return __unload_module(); 14149 }
| static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1949 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().
01950 { 01951 int needconf = 0; 01952 int x; 01953 int useslavenative; 01954 struct dahdi_pvt *slave = NULL; 01955 01956 useslavenative = isslavenative(p, &slave); 01957 /* Start with the obvious, general stuff */ 01958 for (x = 0; x < 3; x++) { 01959 /* Look for three way calls */ 01960 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01961 conf_add(p, &p->subs[x], x, 0); 01962 needconf++; 01963 } else { 01964 conf_del(p, &p->subs[x], x); 01965 } 01966 } 01967 /* If we have a slave, add him to our conference now. or DAX 01968 if this is slave native */ 01969 for (x = 0; x < MAX_SLAVES; x++) { 01970 if (p->slaves[x]) { 01971 if (useslavenative) 01972 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01973 else { 01974 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01975 needconf++; 01976 } 01977 } 01978 } 01979 /* If we're supposed to be in there, do so now */ 01980 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01981 if (useslavenative) 01982 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01983 else { 01984 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01985 needconf++; 01986 } 01987 } 01988 /* If we have a master, add ourselves to his conference */ 01989 if (p->master) { 01990 if (isslavenative(p->master, NULL)) { 01991 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01992 } else { 01993 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01994 } 01995 } 01996 if (!needconf) { 01997 /* Nobody is left (or should be left) in our conference. 01998 Kill it. */ 01999 p->confno = -1; 02000 } 02001 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02002 return 0; 02003 }
Definition at line 1316 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_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().
01320 { 01321 #ifdef HAVE_PRI 01322 if (pri) 01323 ast_mutex_unlock(&pri->lock); 01324 #endif 01325 for (;;) { 01326 if (p->subs[a].owner) { 01327 if (ast_channel_trylock(p->subs[a].owner)) { 01328 DEADLOCK_AVOIDANCE(&p->lock); 01329 } else { 01330 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01331 ast_channel_unlock(p->subs[a].owner); 01332 break; 01333 } 01334 } else 01335 break; 01336 } 01337 #ifdef HAVE_PRI 01338 if (pri) 01339 ast_mutex_lock(&pri->lock); 01340 #endif 01341 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "DAHDI Telephony w/PRI & 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 15547 of file chan_dahdi.c.
| int alarm |
Definition at line 1714 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 1290 of file chan_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 15547 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1271 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 1282 of file chan_dahdi.c.
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 169 of file chan_dahdi.c.
int cur_adjpointcode = -1 [static] |
Definition at line 384 of file chan_dahdi.c.
int cur_cicbeginswith = -1 [static] |
Definition at line 383 of file chan_dahdi.c.
int cur_defaultdpc = -1 [static] |
Definition at line 386 of file chan_dahdi.c.
int cur_linkset = -1 [static] |
Definition at line 381 of file chan_dahdi.c.
int cur_networkindicator = -1 [static] |
Definition at line 385 of file chan_dahdi.c.
int cur_pointcode = -1 [static] |
Definition at line 382 of file chan_dahdi.c.
int cur_ss7type = -1 [static] |
Definition at line 380 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 13368 of file chan_dahdi.c.
struct ast_cli_entry dahdi_pri_cli[] [static] |
Definition at line 12499 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3253 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 3257 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3255 of file chan_dahdi.c.
struct ast_cli_entry dahdi_ss7_cli[] [static] |
Definition at line 14046 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1198 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 227 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 228 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 239 of file chan_dahdi.c.
char* events[] [static] |
Definition at line 1691 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 255 of file chan_dahdi.c.
Referenced by disa_exec().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 258 of file chan_dahdi.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 126 of file chan_dahdi.c.
Referenced by dahdi_new(), process_dahdi(), and setup_dahdi().
int ifcount = 0 [static] |
Definition at line 267 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 264 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), dahdi_hangup(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), and setup_dahdi().
struct ast_channel inuse [static] |
Definition at line 246 of file chan_dahdi.c.
Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), pri_dchannel(), and update_call_counter().
const char* lbostr[] [static] |
Definition at line 106 of file chan_dahdi.c.
Definition at line 378 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 261 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 279 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 275 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), and restart_monitor().
ast_cond_t mwi_thread_complete [static] |
Definition at line 280 of file chan_dahdi.c.
int mwi_thread_count = 0 [static] |
Definition at line 285 of file chan_dahdi.c.
ast_mutex_t mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 282 of file chan_dahdi.c.
Referenced by dahdi_restart(), and mwi_send_thread().
int mwilevel = 512 [static] |
Definition at line 243 of file chan_dahdi.c.
char mwimonitornotify[PATH_MAX] = "" [static] |
Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled
Definition at line 233 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 234 of file chan_dahdi.c.
| char* name |
Definition at line 1715 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1268 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 287 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 241 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 230 of file chan_dahdi.c.
Referenced by __find_callno(), ast_iax2_new(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), func_channel_write(), gtalk_load_config(), gtalk_new(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 250 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 270 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), handle_pri_show_debug(), and handle_pri_unset_debug_file().
char pridebugfilename[1024] = "" [static] |
Definition at line 251 of file chan_dahdi.c.
Definition at line 448 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().
char progzone[10] = "" [static] |
Definition at line 236 of file chan_dahdi.c.
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 284 of file chan_dahdi.c.
Referenced by dahdi_restart().
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 342 of file chan_dahdi.c.
| struct dahdi_pvt* round_robin[32] |
Definition at line 1225 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 281 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 286 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 283 of file chan_dahdi.c.
Referenced by dahdi_restart(), and ss_thread().
char* subnames[] [static] |
{
"Real",
"Callwait",
"Threeway"
}
Definition at line 487 of file chan_dahdi.c.
const char tdesc[] [static] |
Definition at line 160 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 238 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1269 of file chan_dahdi.c.
1.6.1