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 153 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), do_monitor(), mwi_send_thread(), mwi_thread(), send_cwcidspill(), and ss_thread().
| #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
Definition at line 224 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmfup(), and process_dahdi().
| #define CALLPROGRESS_FAX_INCOMING 4 |
Definition at line 223 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_FAX_OUTGOING 2 |
Definition at line 222 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_PROGRESS 1 |
Definition at line 221 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_new(), and process_dahdi().
| #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
| #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 329 of file chan_dahdi.c.
| #define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 1294 of file chan_dahdi.c.
Referenced by dahdi_new().
| #define CANPROGRESSDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 1295 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and dahdi_new().
| #define CHAN_PSEUDO -2 |
Definition at line 206 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), mkintf(), and process_dahdi().
| #define CHANNEL_PSEUDO -12 |
Definition at line 151 of file chan_dahdi.c.
| #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define CONF_USER_REAL (1 << 0) |
Definition at line 511 of file chan_dahdi.c.
| #define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 512 of file chan_dahdi.c.
| #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
Definition at line 218 of file chan_dahdi.c.
Referenced by process_dahdi(), and start_pri().
| #define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 217 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), pri_dchannel(), and process_dahdi().
| #define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 215 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 216 of file chan_dahdi.c.
Referenced by dahdi_read(), process_dahdi(), and start_pri().
| #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
Definition at line 212 of file chan_dahdi.c.
Referenced by pri_find_dchan(), and pri_is_up().
| #define DCHAN_NOTINALARM (1 << 1) |
Definition at line 209 of file chan_dahdi.c.
Referenced by build_status(), pri_dchannel(), and start_pri().
| #define DCHAN_PROVISIONED (1 << 0) |
Definition at line 208 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
| #define DCHAN_UP (1 << 2) |
Definition at line 210 of file chan_dahdi.c.
Referenced by build_status(), and pri_dchannel().
| #define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 149 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
| #define DEFAULT_PRI_DEBUG 0 |
Definition at line 452 of file chan_dahdi.c.
Referenced by start_pri().
| #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 333 of file chan_dahdi.c.
| #define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
| #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" |
| #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" |
| #define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1219 of file chan_dahdi.c.
Referenced by update_conf().
| #define HANGUP 1 |
Definition at line 13350 of file chan_dahdi.c.
Referenced by action_transferhangup(), and dahdi_fake_event().
| #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_information(), build_notify(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_status(), build_status_enquiry(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_timeout(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_information(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), parse_setup_acknowledge(), and parse_status().
| #define HEADER_MS 50 |
Referenced by dahdi_sendtext().
| #define ISTRUNK | ( | p | ) |
Definition at line 1291 of file chan_dahdi.c.
Referenced by dahdi_indicate(), and ss_thread().
| #define LINKSET_FLAG_EXPLICITACM (1 << 0) |
Definition at line 352 of file chan_dahdi.c.
Referenced by process_dahdi(), and ss7_start_call().
| #define LINKSTATE_DOWN (1 << 3) |
Definition at line 348 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_INALARM (1 << 0) |
Definition at line 345 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_STARTING (1 << 1) |
Definition at line 346 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define LINKSTATE_UP (1 << 2) |
Definition at line 347 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 326 of file chan_dahdi.c.
| #define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 327 of file chan_dahdi.c.
| #define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 14209 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 204 of file chan_dahdi.c.
Referenced by mkintf().
| #define MAX_SLAVES 4 |
Definition at line 514 of file chan_dahdi.c.
Referenced by dahdi_link(), dahdi_show_channel(), dahdi_unlink(), isslavenative(), and update_conf().
| #define MIN_MS_SINCE_FLASH ( (2000) ) |
| #define NEED_MFDETECT | ( | p | ) | (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB)) |
Signaling types that need to use MF detection should be placed in this macro.
Definition at line 157 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
| #define NUM_CADENCE_MAX 25 |
Definition at line 1266 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 203 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), and pri_is_up().
| #define NUM_SPANS 32 |
Definition at line 201 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_ss7_error(), dahdi_ss7_message(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_debug(), handle_ss7_no_debug(), handle_ss7_show_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), linkset_addsigchan(), load_module(), mkintf(), pri_create_trunkgroup(), pri_resolve_span(), process_dahdi(), setup_dahdi(), ss7_resolve_linkset(), and unload_module().
| #define POLARITY_IDLE 0 |
Definition at line 470 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), ss_thread(), and unalloc_sub().
| #define POLARITY_REV 1 |
Definition at line 471 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), handle_init_event(), and ss_thread().
| #define PRI_CHANNEL | ( | p | ) | ((p) & 0xff) |
Definition at line 391 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PRI_EXPLICIT | ( | p | ) | (((p) >> 16) & 0x01) |
Definition at line 393 of file chan_dahdi.c.
Referenced by pri_find_principle().
| #define PRI_SPAN | ( | p | ) | (((p) >> 8) & 0xff) |
Definition at line 392 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PROC_DAHDI_OPT_NOCHAN (1 << 0) |
process_dahdi() - ignore keyword 'channel' and similar
Definition at line 14263 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 14265 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi().
| #define PVT_TO_CHANNEL | ( | p | ) | (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
Definition at line 390 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), pri_check_restart(), and pri_dchannel().
| #define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 324 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().
| #define sig2str dahdi_sig2str |
Definition at line 1820 of file chan_dahdi.c.
Referenced by action_dahdishowchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
Definition at line 186 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 187 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 175 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM DAHDI_SIG_EM |
Definition at line 170 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 194 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 171 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 174 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 172 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 173 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 176 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 177 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 178 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 183 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 184 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 182 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 180 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
| #define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 181 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), process_dahdi(), and ss_thread().
| #define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 179 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 195 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 196 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 185 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF DAHDI_SIG_SF |
Definition at line 189 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 193 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 191 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 192 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 190 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 188 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SMDI_MD_WAIT_TIMEOUT 1500 |
Definition at line 104 of file chan_dahdi.c.
Referenced by ss_thread().
| #define SS7_NAI_DYNAMIC -1 |
Definition at line 350 of file chan_dahdi.c.
Referenced by dahdi_call(), and process_dahdi().
| #define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 466 of file chan_dahdi.c.
Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), dahdi_show_channel(), and ss_thread().
| #define SUB_REAL 0 |
Active call
Definition at line 465 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), build_device(), bump_gains(), chandup(), check_for_conference(), close_call(), close_client(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_loopback(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_restart(), dahdi_ring_phone(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_setoption(), dahdi_show_channel(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_send_thread(), mwi_thread(), pri_assign_bearer(), pri_dchannel(), pri_fixup_principle(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), ss7_linkset(), ss7_start_call(), ss_thread(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), unistim_senddigit_end(), and update_conf().
| #define SUB_THREEWAY 2 |
Three-way call
Definition at line 467 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), close_call(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), HandleCallOutgoing(), ss_thread(), TransferCallStep1(), unistim_answer(), and unistim_hangup().
| #define tdesc "DAHDI Telephony w/PRI & SS7" |
Definition at line 15499 of file chan_dahdi.c.
| #define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
| #define TRANSFER 0 |
Definition at line 13349 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 7915 of file chan_dahdi.c.
07915 { 07916 MWI_SEND_SA, 07917 MWI_SEND_SA_WAIT, 07918 MWI_SEND_PAUSE, 07919 MWI_SEND_SPILL, 07920 MWI_SEND_CLEANUP, 07921 MWI_SEND_DONE 07922 };
| static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5552 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().
05553 { 05554 struct dahdi_pvt *p = ast->tech_pvt; 05555 int res; 05556 int usedindex=-1; 05557 int idx; 05558 struct ast_frame *f; 05559 05560 05561 idx = dahdi_get_index(ast, p, 1); 05562 05563 p->subs[idx].f.frametype = AST_FRAME_NULL; 05564 p->subs[idx].f.datalen = 0; 05565 p->subs[idx].f.samples = 0; 05566 p->subs[idx].f.mallocd = 0; 05567 p->subs[idx].f.offset = 0; 05568 p->subs[idx].f.subclass = 0; 05569 p->subs[idx].f.delivery = ast_tv(0,0); 05570 p->subs[idx].f.src = "dahdi_exception"; 05571 p->subs[idx].f.data.ptr = NULL; 05572 05573 05574 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 05575 /* If nobody owns us, absorb the event appropriately, otherwise 05576 we loop indefinitely. This occurs when, during call waiting, the 05577 other end hangs up our channel so that it no longer exists, but we 05578 have neither FLASH'd nor ONHOOK'd to signify our desire to 05579 change to the other channel. */ 05580 if (p->fake_event) { 05581 res = p->fake_event; 05582 p->fake_event = 0; 05583 } else 05584 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 05585 /* Switch to real if there is one and this isn't something really silly... */ 05586 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 05587 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 05588 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 05589 p->owner = p->subs[SUB_REAL].owner; 05590 if (p->owner && ast_bridged_channel(p->owner)) 05591 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05592 p->subs[SUB_REAL].needunhold = 1; 05593 } 05594 switch (res) { 05595 case DAHDI_EVENT_ONHOOK: 05596 dahdi_disable_ec(p); 05597 if (p->owner) { 05598 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 05599 dahdi_ring_phone(p); 05600 p->callwaitingrepeat = 0; 05601 p->cidcwexpire = 0; 05602 } else 05603 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05604 update_conf(p); 05605 break; 05606 case DAHDI_EVENT_RINGOFFHOOK: 05607 dahdi_enable_ec(p); 05608 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05609 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 05610 p->subs[SUB_REAL].needanswer = 1; 05611 p->dialing = 0; 05612 } 05613 break; 05614 case DAHDI_EVENT_HOOKCOMPLETE: 05615 case DAHDI_EVENT_RINGERON: 05616 case DAHDI_EVENT_RINGEROFF: 05617 /* Do nothing */ 05618 break; 05619 case DAHDI_EVENT_WINKFLASH: 05620 p->flashtime = ast_tvnow(); 05621 if (p->owner) { 05622 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 05623 if (p->owner->_state != AST_STATE_UP) { 05624 /* Answer if necessary */ 05625 usedindex = dahdi_get_index(p->owner, p, 0); 05626 if (usedindex > -1) { 05627 p->subs[usedindex].needanswer = 1; 05628 } 05629 ast_setstate(p->owner, AST_STATE_UP); 05630 } 05631 p->callwaitingrepeat = 0; 05632 p->cidcwexpire = 0; 05633 if (ast_bridged_channel(p->owner)) 05634 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05635 p->subs[SUB_REAL].needunhold = 1; 05636 } else 05637 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 05638 update_conf(p); 05639 break; 05640 default: 05641 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 05642 } 05643 f = &p->subs[idx].f; 05644 return f; 05645 } 05646 if (!(p->radio || (p->oprmode < 0))) 05647 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 05648 /* If it's not us, return NULL immediately */ 05649 if (ast != p->owner) { 05650 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 05651 f = &p->subs[idx].f; 05652 return f; 05653 } 05654 f = dahdi_handle_event(ast); 05655 return f; 05656 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 15515 of file chan_dahdi.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 14026 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().
14027 { 14028 struct dahdi_pvt *p; 14029 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14030 int i, j; 14031 #endif 14032 14033 #ifdef HAVE_PRI 14034 for (i = 0; i < NUM_SPANS; i++) { 14035 if (pris[i].master != AST_PTHREADT_NULL) 14036 pthread_cancel(pris[i].master); 14037 } 14038 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 14039 ast_unregister_application(dahdi_send_keypad_facility_app); 14040 #endif 14041 #if defined(HAVE_SS7) 14042 for (i = 0; i < NUM_SPANS; i++) { 14043 if (linksets[i].master != AST_PTHREADT_NULL) 14044 pthread_cancel(linksets[i].master); 14045 } 14046 ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry)); 14047 #endif 14048 14049 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 14050 ast_manager_unregister( "DAHDIDialOffhook" ); 14051 ast_manager_unregister( "DAHDIHangup" ); 14052 ast_manager_unregister( "DAHDITransfer" ); 14053 ast_manager_unregister( "DAHDIDNDoff" ); 14054 ast_manager_unregister( "DAHDIDNDon" ); 14055 ast_manager_unregister("DAHDIShowChannels"); 14056 ast_manager_unregister("DAHDIRestart"); 14057 ast_channel_unregister(&dahdi_tech); 14058 ast_mutex_lock(&iflock); 14059 /* Hangup all interfaces if they have an owner */ 14060 p = iflist; 14061 while (p) { 14062 if (p->owner) 14063 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 14064 p = p->next; 14065 } 14066 ast_mutex_unlock(&iflock); 14067 ast_mutex_lock(&monlock); 14068 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14069 pthread_cancel(monitor_thread); 14070 pthread_kill(monitor_thread, SIGURG); 14071 pthread_join(monitor_thread, NULL); 14072 } 14073 monitor_thread = AST_PTHREADT_STOP; 14074 ast_mutex_unlock(&monlock); 14075 14076 destroy_all_channels(); 14077 14078 #if defined(HAVE_PRI) 14079 for (i = 0; i < NUM_SPANS; i++) { 14080 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 14081 pthread_join(pris[i].master, NULL); 14082 for (j = 0; j < NUM_DCHANS; j++) { 14083 dahdi_close_pri_fd(&(pris[i]), j); 14084 } 14085 } 14086 #endif 14087 14088 #if defined(HAVE_SS7) 14089 for (i = 0; i < NUM_SPANS; i++) { 14090 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 14091 pthread_join(linksets[i].master, NULL); 14092 for (j = 0; j < NUM_DCHANS; j++) { 14093 dahdi_close_ss7_fd(&(linksets[i]), j); 14094 } 14095 } 14096 #endif 14097 14098 ast_cond_destroy(&mwi_thread_complete); 14099 ast_cond_destroy(&ss_thread_complete); 14100 return 0; 14101 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 15515 of file chan_dahdi.c.
| static int action_dahdidialoffhook | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13456 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().
13457 { 13458 struct dahdi_pvt *p = NULL; 13459 const char *channel = astman_get_header(m, "DAHDIChannel"); 13460 const char *number = astman_get_header(m, "Number"); 13461 int i; 13462 13463 if (ast_strlen_zero(channel)) { 13464 astman_send_error(s, m, "No channel specified"); 13465 return 0; 13466 } 13467 if (ast_strlen_zero(number)) { 13468 astman_send_error(s, m, "No number specified"); 13469 return 0; 13470 } 13471 p = find_channel(atoi(channel)); 13472 if (!p) { 13473 astman_send_error(s, m, "No such channel"); 13474 return 0; 13475 } 13476 if (!p->owner) { 13477 astman_send_error(s, m, "Channel does not have it's owner"); 13478 return 0; 13479 } 13480 for (i = 0; i < strlen(number); i++) { 13481 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 13482 dahdi_queue_frame(p, &f, NULL); 13483 } 13484 astman_send_ack(s, m, "DAHDIDialOffhook"); 13485 return 0; 13486 }
| static int action_dahdidndoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13399 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().
13400 { 13401 struct dahdi_pvt *p = NULL; 13402 const char *channel = astman_get_header(m, "DAHDIChannel"); 13403 13404 if (ast_strlen_zero(channel)) { 13405 astman_send_error(s, m, "No channel specified"); 13406 return 0; 13407 } 13408 p = find_channel(atoi(channel)); 13409 if (!p) { 13410 astman_send_error(s, m, "No such channel"); 13411 return 0; 13412 } 13413 p->dnd = 0; 13414 astman_send_ack(s, m, "DND Disabled"); 13415 return 0; 13416 }
| static int action_dahdidndon | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13380 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().
13381 { 13382 struct dahdi_pvt *p = NULL; 13383 const char *channel = astman_get_header(m, "DAHDIChannel"); 13384 13385 if (ast_strlen_zero(channel)) { 13386 astman_send_error(s, m, "No channel specified"); 13387 return 0; 13388 } 13389 p = find_channel(atoi(channel)); 13390 if (!p) { 13391 astman_send_error(s, m, "No such channel"); 13392 return 0; 13393 } 13394 p->dnd = 1; 13395 astman_send_ack(s, m, "DND Enabled"); 13396 return 0; 13397 }
| static int action_dahdirestart | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 12673 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
12674 { 12675 if (dahdi_restart() != 0) { 12676 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 12677 return 1; 12678 } 12679 astman_send_ack(s, m, "DAHDIRestart: Success"); 12680 return 0; 12681 }
| static int action_dahdishowchannels | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13488 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().
13489 { 13490 struct dahdi_pvt *tmp = NULL; 13491 const char *id = astman_get_header(m, "ActionID"); 13492 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 13493 char idText[256] = ""; 13494 int channels = 0; 13495 int dahdichanquery = -1; 13496 if (!ast_strlen_zero(dahdichannel)) { 13497 dahdichanquery = atoi(dahdichannel); 13498 } 13499 13500 astman_send_ack(s, m, "DAHDI channel status will follow"); 13501 if (!ast_strlen_zero(id)) 13502 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 13503 13504 ast_mutex_lock(&iflock); 13505 13506 tmp = iflist; 13507 while (tmp) { 13508 if (tmp->channel > 0) { 13509 int alm = get_alarms(tmp); 13510 13511 /* If a specific channel is queried for, only deliver status for that channel */ 13512 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 13513 continue; 13514 13515 channels++; 13516 if (tmp->owner) { 13517 /* Add data if we have a current call */ 13518 astman_append(s, 13519 "Event: DAHDIShowChannels\r\n" 13520 "DAHDIChannel: %d\r\n" 13521 "Channel: %s\r\n" 13522 "Uniqueid: %s\r\n" 13523 "AccountCode: %s\r\n" 13524 "Signalling: %s\r\n" 13525 "SignallingCode: %d\r\n" 13526 "Context: %s\r\n" 13527 "DND: %s\r\n" 13528 "Alarm: %s\r\n" 13529 "%s" 13530 "\r\n", 13531 tmp->channel, 13532 tmp->owner->name, 13533 tmp->owner->uniqueid, 13534 tmp->owner->accountcode, 13535 sig2str(tmp->sig), 13536 tmp->sig, 13537 tmp->context, 13538 tmp->dnd ? "Enabled" : "Disabled", 13539 alarm2str(alm), idText); 13540 } else { 13541 astman_append(s, 13542 "Event: DAHDIShowChannels\r\n" 13543 "DAHDIChannel: %d\r\n" 13544 "Signalling: %s\r\n" 13545 "SignallingCode: %d\r\n" 13546 "Context: %s\r\n" 13547 "DND: %s\r\n" 13548 "Alarm: %s\r\n" 13549 "%s" 13550 "\r\n", 13551 tmp->channel, sig2str(tmp->sig), tmp->sig, 13552 tmp->context, 13553 tmp->dnd ? "Enabled" : "Disabled", 13554 alarm2str(alm), idText); 13555 } 13556 } 13557 13558 tmp = tmp->next; 13559 } 13560 13561 ast_mutex_unlock(&iflock); 13562 13563 astman_append(s, 13564 "Event: DAHDIShowChannelsComplete\r\n" 13565 "%s" 13566 "Items: %d\r\n" 13567 "\r\n", 13568 idText, 13569 channels); 13570 return 0; 13571 }
| static int action_transfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13418 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().
13419 { 13420 struct dahdi_pvt *p = NULL; 13421 const char *channel = astman_get_header(m, "DAHDIChannel"); 13422 13423 if (ast_strlen_zero(channel)) { 13424 astman_send_error(s, m, "No channel specified"); 13425 return 0; 13426 } 13427 p = find_channel(atoi(channel)); 13428 if (!p) { 13429 astman_send_error(s, m, "No such channel"); 13430 return 0; 13431 } 13432 dahdi_fake_event(p,TRANSFER); 13433 astman_send_ack(s, m, "DAHDITransfer"); 13434 return 0; 13435 }
| static int action_transferhangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 13437 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().
13438 { 13439 struct dahdi_pvt *p = NULL; 13440 const char *channel = astman_get_header(m, "DAHDIChannel"); 13441 13442 if (ast_strlen_zero(channel)) { 13443 astman_send_error(s, m, "No channel specified"); 13444 return 0; 13445 } 13446 p = find_channel(atoi(channel)); 13447 if (!p) { 13448 astman_send_error(s, m, "No such channel"); 13449 return 0; 13450 } 13451 dahdi_fake_event(p,HANGUP); 13452 astman_send_ack(s, m, "DAHDIHangup"); 13453 return 0; 13454 }
| static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 1725 of file chan_dahdi.c.
References alarm, alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
| static int alloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 1521 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), dahdi_open(), dahdi_subchannel::dfd, errno, LOG_WARNING, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().
01522 { 01523 struct dahdi_bufferinfo bi; 01524 int res; 01525 if (p->subs[x].dfd >= 0) { 01526 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01527 return -1; 01528 } 01529 01530 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 01531 if (p->subs[x].dfd <= -1) { 01532 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01533 return -1; 01534 } 01535 01536 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 01537 if (!res) { 01538 bi.txbufpolicy = p->buf_policy; 01539 bi.rxbufpolicy = p->buf_policy; 01540 bi.numbufs = p->buf_no; 01541 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01542 if (res < 0) { 01543 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01544 } 01545 } else 01546 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01547 01548 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01549 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01550 dahdi_close_sub(p, x); 01551 p->subs[x].dfd = -1; 01552 return -1; 01553 } 01554 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01555 return 0; 01556 }
| static void apply_plan_to_number | ( | char * | buf, | |
| size_t | size, | |||
| const struct dahdi_pri * | pri, | |||
| const char * | number, | |||
| const int | plan | |||
| ) | [static] |
Definition at line 10853 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().
10854 { 10855 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */ 10856 snprintf(buf, size, "%s", number); 10857 return; 10858 } 10859 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 10860 if (size) { 10861 *buf = '\0'; 10862 } 10863 return; 10864 } 10865 switch (plan) { 10866 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 10867 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 10868 break; 10869 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 10870 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 10871 break; 10872 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 10873 snprintf(buf, size, "%s%s", pri->localprefix, number); 10874 break; 10875 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 10876 snprintf(buf, size, "%s%s", pri->privateprefix, number); 10877 break; 10878 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 10879 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 10880 break; 10881 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 10882 snprintf(buf, size, "%s", number); 10883 break; 10884 } 10885 }
| static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4499 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().
04500 { 04501 /* In order to transfer, we need at least one of the channels to 04502 actually be in a call bridge. We can't conference two applications 04503 together (but then, why would we want to?) */ 04504 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04505 /* The three-way person we're about to transfer to could still be in MOH, so 04506 stop if now if appropriate */ 04507 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 04508 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 04509 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 04510 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 04511 } 04512 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 04513 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04514 } 04515 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 04516 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04517 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 04518 return -1; 04519 } 04520 /* Orphan the channel after releasing the lock */ 04521 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04522 unalloc_sub(p, SUB_THREEWAY); 04523 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04524 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04525 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 04526 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 04527 } 04528 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 04529 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04530 } 04531 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 04532 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 04533 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 04534 return -1; 04535 } 04536 /* Three-way is now the REAL */ 04537 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04538 ast_channel_unlock(p->subs[SUB_REAL].owner); 04539 unalloc_sub(p, SUB_THREEWAY); 04540 /* Tell the caller not to hangup */ 04541 return 1; 04542 } else { 04543 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 04544 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 04545 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04546 return -1; 04547 } 04548 return 0; 04549 }
| static int available | ( | struct dahdi_pvt * | p, | |
| int | channelmatch, | |||
| ast_group_t | groupmatch, | |||
| int * | busy, | |||
| int * | channelmatched, | |||
| int * | groupmatched | |||
| ) | [inline, static] |
Definition at line 9284 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().
09285 { 09286 int res; 09287 struct dahdi_params par; 09288 09289 /* First, check group matching */ 09290 if (groupmatch) { 09291 if ((p->group & groupmatch) != groupmatch) 09292 return 0; 09293 *groupmatched = 1; 09294 } 09295 /* Check to see if we have a channel match */ 09296 if (channelmatch != -1) { 09297 if (p->channel != channelmatch) 09298 return 0; 09299 *channelmatched = 1; 09300 } 09301 /* We're at least busy at this point */ 09302 if (busy) { 09303 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 09304 *busy = 1; 09305 } 09306 /* If do not disturb, definitely not */ 09307 if (p->dnd) 09308 return 0; 09309 /* If guard time, definitely not */ 09310 if (p->guardtime && (time(NULL) < p->guardtime)) 09311 return 0; 09312 09313 if (p->locallyblocked || p->remotelyblocked) 09314 return 0; 09315 09316 /* If no owner definitely available */ 09317 if (!p->owner) { 09318 #ifdef HAVE_PRI 09319 /* Trust PRI */ 09320 if (p->pri) { 09321 if (p->resetting || p->call) 09322 return 0; 09323 else 09324 return 1; 09325 } 09326 #endif 09327 #ifdef HAVE_SS7 09328 /* Trust SS7 */ 09329 if (p->ss7) { 09330 if (p->ss7call) 09331 return 0; 09332 else 09333 return 1; 09334 } 09335 #endif 09336 if (!(p->radio || (p->oprmode < 0))) 09337 { 09338 if (!p->sig || (p->sig == SIG_FXSLS)) 09339 return 1; 09340 /* Check hook state */ 09341 if (p->subs[SUB_REAL].dfd > -1) { 09342 memset(&par, 0, sizeof(par)); 09343 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 09344 } else { 09345 /* Assume not off hook on CVRS */ 09346 res = 0; 09347 par.rxisoffhook = 0; 09348 } 09349 if (res) { 09350 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 09351 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 09352 /* When "onhook" that means no battery on the line, and thus 09353 it is out of service..., if it's on a TDM card... If it's a channel 09354 bank, there is no telling... */ 09355 if (par.rxbits > -1) 09356 return 1; 09357 if (par.rxisoffhook) 09358 return 1; 09359 else 09360 return 0; 09361 } else if (par.rxisoffhook) { 09362 ast_debug(1, "Channel %d off hook, can't use\n", p->channel); 09363 /* Not available when the other end is off hook */ 09364 #ifdef DAHDI_CHECK_HOOKSTATE 09365 return 0; 09366 #else 09367 return 1; 09368 #endif 09369 } 09370 } 09371 return 1; 09372 } 09373 09374 /* If it's not an FXO, forget about call wait */ 09375 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 09376 return 0; 09377 09378 if (!p->callwaiting) { 09379 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 09380 return 0; 09381 } 09382 09383 if (p->subs[SUB_CALLWAIT].dfd > -1) { 09384 /* If there is already a call waiting call, then we can't take a second one */ 09385 return 0; 09386 } 09387 09388 if ((p->owner->_state != AST_STATE_UP) && 09389 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 09390 /* If the current call is not up, then don't allow the call */ 09391 return 0; 09392 } 09393 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 09394 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 09395 return 0; 09396 } 09397 /* We're cool */ 09398 return 1; 09399 }
| 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 14119 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().
14120 { 14121 char *c, *chan; 14122 int x, start, finish; 14123 struct dahdi_pvt *tmp; 14124 #ifdef HAVE_PRI 14125 struct dahdi_pri *pri; 14126 int trunkgroup, y; 14127 #endif 14128 14129 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 14130 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 14131 return -1; 14132 } 14133 14134 c = ast_strdupa(value); 14135 14136 #ifdef HAVE_PRI 14137 pri = NULL; 14138 if (iscrv) { 14139 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 14140 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno); 14141 return -1; 14142 } 14143 if (trunkgroup < 1) { 14144 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno); 14145 return -1; 14146 } 14147 c += y; 14148 for (y = 0; y < NUM_SPANS; y++) { 14149 if (pris[y].trunkgroup == trunkgroup) { 14150 pri = pris + y; 14151 break; 14152 } 14153 } 14154 if (!pri) { 14155 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno); 14156 return -1; 14157 } 14158 } 14159 #endif 14160 14161 while ((chan = strsep(&c, ","))) { 14162 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 14163 /* Range */ 14164 } else if (sscanf(chan, "%30d", &start)) { 14165 /* Just one */ 14166 finish = start; 14167 } else if (!strcasecmp(chan, "pseudo")) { 14168 finish = start = CHAN_PSEUDO; 14169 if (found_pseudo) 14170 *found_pseudo = 1; 14171 } else { 14172 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 14173 return -1; 14174 } 14175 if (finish < start) { 14176 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 14177 x = finish; 14178 finish = start; 14179 start = x; 14180 } 14181 14182 for (x = start; x <= finish; x++) { 14183 #ifdef HAVE_PRI 14184 tmp = mkintf(x, conf, pri, reload); 14185 #else 14186 tmp = mkintf(x, conf, NULL, reload); 14187 #endif 14188 14189 if (tmp) { 14190 #ifdef HAVE_PRI 14191 if (pri) 14192 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 14193 else 14194 #endif 14195 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 14196 } else { 14197 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 14198 (reload == 1) ? "reconfigure" : "register", value); 14199 return -1; 14200 } 14201 } 14202 } 14203 14204 return 0; 14205 }
| static void build_status | ( | char * | s, | |
| size_t | len, | |||
| int | status, | |||
| int | active | |||
| ) | [static] |
Definition at line 12304 of file chan_dahdi.c.
References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
12305 { 12306 if (!s || len < 1) { 12307 return; 12308 } 12309 s[0] = '\0'; 12310 if (status & DCHAN_PROVISIONED) 12311 strncat(s, "Provisioned, ", len - strlen(s) - 1); 12312 if (!(status & DCHAN_NOTINALARM)) 12313 strncat(s, "In Alarm, ", len - strlen(s) - 1); 12314 if (status & DCHAN_UP) 12315 strncat(s, "Up", len - strlen(s) - 1); 12316 else 12317 strncat(s, "Down", len - strlen(s) - 1); 12318 if (active) 12319 strncat(s, ", Active", len - strlen(s) - 1); 12320 else 12321 strncat(s, ", Standby", len - strlen(s) - 1); 12322 s[len - 1] = '\0'; 12323 }
| static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2180 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::cid_rxgain, dahdi_subchannel::dfd, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by mwi_thread(), and ss_thread().
02181 { 02182 int res; 02183 02184 /* Bump receive gain by value stored in cid_rxgain */ 02185 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law); 02186 if (res) { 02187 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02188 return -1; 02189 } 02190 02191 return 0; 02192 }
| static int calc_energy | ( | const unsigned char * | buf, | |
| int | len, | |||
| int | law | |||
| ) | [static] |
Definition at line 7767 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by do_monitor(), and mwi_thread().
Definition at line 9401 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().
09402 { 09403 struct dahdi_pvt *p; 09404 struct dahdi_bufferinfo bi; 09405 int res; 09406 09407 if ((p = ast_malloc(sizeof(*p)))) { 09408 memcpy(p, src, sizeof(struct dahdi_pvt)); 09409 ast_mutex_init(&p->lock); 09410 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 09411 /* Allocate a dahdi structure */ 09412 if (p->subs[SUB_REAL].dfd < 0) { 09413 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 09414 destroy_dahdi_pvt(&p); 09415 return NULL; 09416 } 09417 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09418 if (!res) { 09419 bi.txbufpolicy = src->buf_policy; 09420 bi.rxbufpolicy = src->buf_policy; 09421 bi.numbufs = src->buf_no; 09422 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09423 if (res < 0) { 09424 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 09425 } 09426 } else 09427 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 09428 } 09429 p->destroy = 1; 09430 p->next = iflist; 09431 p->prev = NULL; 09432 iflist = p; 09433 if (iflist->next) 09434 iflist->next->prev = p; 09435 return p; 09436 }
| static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4551 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().
04552 { 04553 struct dahdi_confinfo ci; 04554 /* Fine if we already have a master, etc */ 04555 if (p->master || (p->confno > -1)) 04556 return 0; 04557 memset(&ci, 0, sizeof(ci)); 04558 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 04559 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 04560 return 0; 04561 } 04562 /* If we have no master and don't have a confno, then 04563 if we're in a conference, it's probably a MeetMe room or 04564 some such, so don't let us 3-way out! */ 04565 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 04566 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 04567 return 1; 04568 } 04569 return 0; 04570 }
| static unsigned char cid_pres2ss7pres | ( | int | cid_pres | ) | [static] |
Definition at line 2432 of file chan_dahdi.c.
Referenced by dahdi_call().
| static unsigned char cid_pres2ss7screen | ( | int | cid_pres | ) | [static] |
Definition at line 2437 of file chan_dahdi.c.
Referenced by dahdi_call().
| static char* complete_span_4 | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 12129 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
12130 { 12131 return complete_span_helper(line,word,pos,state,3); 12132 }
| static char* complete_span_5 | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 12134 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_no_debug(), and handle_pri_really_debug().
12135 { 12136 return complete_span_helper(line,word,pos,state,4); 12137 }
| static char* complete_span_helper | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state, | |||
| int | rpos | |||
| ) | [static] |
Definition at line 12110 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().
12111 { 12112 int which, span; 12113 char *ret = NULL; 12114 12115 if (pos != rpos) 12116 return ret; 12117 12118 for (which = span = 0; span < NUM_SPANS; span++) { 12119 if (pris[span].pri && ++which > state) { 12120 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 12121 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 12122 } 12123 break; 12124 } 12125 } 12126 return ret; 12127 }
| static int conf_add | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx, | |||
| int | slavechannel | |||
| ) | [static] |
Definition at line 1822 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, and LOG_WARNING.
Referenced by update_conf().
01823 { 01824 /* If the conference already exists, and we're already in it 01825 don't bother doing anything */ 01826 struct dahdi_confinfo zi; 01827 01828 memset(&zi, 0, sizeof(zi)); 01829 zi.chan = 0; 01830 01831 if (slavechannel > 0) { 01832 /* If we have only one slave, do a digital mon */ 01833 zi.confmode = DAHDI_CONF_DIGITALMON; 01834 zi.confno = slavechannel; 01835 } else { 01836 if (!idx) { 01837 /* Real-side and pseudo-side both participate in conference */ 01838 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01839 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01840 } else 01841 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01842 zi.confno = p->confno; 01843 } 01844 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01845 return 0; 01846 if (c->dfd < 0) 01847 return 0; 01848 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01849 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01850 return -1; 01851 } 01852 if (slavechannel < 1) { 01853 p->confno = zi.confno; 01854 } 01855 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01856 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01857 return 0; 01858 }
| static int conf_del | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx | |||
| ) | [static] |
Definition at line 1871 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), and LOG_WARNING.
Referenced by dahdi_unlink(), and update_conf().
01872 { 01873 struct dahdi_confinfo zi; 01874 if (/* Can't delete if there's no dfd */ 01875 (c->dfd < 0) || 01876 /* Don't delete from the conference if it's not our conference */ 01877 !isourconf(p, c) 01878 /* Don't delete if we don't think it's conferenced at all (implied) */ 01879 ) return 0; 01880 memset(&zi, 0, sizeof(zi)); 01881 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01882 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01883 return -1; 01884 } 01885 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01886 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01887 return 0; 01888 }
| static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3739 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.
03740 { 03741 struct dahdi_pvt *p = ast->tech_pvt; 03742 int res = 0; 03743 int idx; 03744 int oldstate = ast->_state; 03745 ast_setstate(ast, AST_STATE_UP); 03746 ast_mutex_lock(&p->lock); 03747 idx = dahdi_get_index(ast, p, 0); 03748 if (idx < 0) 03749 idx = SUB_REAL; 03750 /* nothing to do if a radio channel */ 03751 if ((p->radio || (p->oprmode < 0))) { 03752 ast_mutex_unlock(&p->lock); 03753 return 0; 03754 } 03755 switch (p->sig) { 03756 case SIG_FXSLS: 03757 case SIG_FXSGS: 03758 case SIG_FXSKS: 03759 p->ringt = 0; 03760 /* Fall through */ 03761 case SIG_EM: 03762 case SIG_EM_E1: 03763 case SIG_EMWINK: 03764 case SIG_FEATD: 03765 case SIG_FEATDMF: 03766 case SIG_FEATDMF_TA: 03767 case SIG_E911: 03768 case SIG_FGC_CAMA: 03769 case SIG_FGC_CAMAMF: 03770 case SIG_FEATB: 03771 case SIG_SF: 03772 case SIG_SFWINK: 03773 case SIG_SF_FEATD: 03774 case SIG_SF_FEATDMF: 03775 case SIG_SF_FEATB: 03776 case SIG_FXOLS: 03777 case SIG_FXOGS: 03778 case SIG_FXOKS: 03779 /* Pick up the line */ 03780 ast_debug(1, "Took %s off hook\n", ast->name); 03781 if (p->hanguponpolarityswitch) { 03782 p->polaritydelaytv = ast_tvnow(); 03783 } 03784 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 03785 tone_zone_play_tone(p->subs[idx].dfd, -1); 03786 p->dialing = 0; 03787 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 03788 if (oldstate == AST_STATE_RINGING) { 03789 ast_debug(1, "Finally swapping real and threeway\n"); 03790 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 03791 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03792 p->owner = p->subs[SUB_REAL].owner; 03793 } 03794 } 03795 if (p->sig & __DAHDI_SIG_FXS) { 03796 dahdi_enable_ec(p); 03797 dahdi_train_ec(p); 03798 } 03799 break; 03800 #ifdef HAVE_PRI 03801 case SIG_BRI: 03802 case SIG_BRI_PTMP: 03803 case SIG_PRI: 03804 /* Send a pri acknowledge */ 03805 if (!pri_grab(p, p->pri)) { 03806 p->proceeding = 1; 03807 p->dialing = 0; 03808 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 03809 pri_rel(p->pri); 03810 } else { 03811 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03812 res = -1; 03813 } 03814 break; 03815 #endif 03816 #ifdef HAVE_SS7 03817 case SIG_SS7: 03818 if (!ss7_grab(p, p->ss7)) { 03819 p->proceeding = 1; 03820 res = isup_anm(p->ss7->ss7, p->ss7call); 03821 ss7_rel(p->ss7); 03822 } else { 03823 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 03824 res = -1; 03825 } 03826 break; 03827 #endif 03828 case 0: 03829 ast_mutex_unlock(&p->lock); 03830 return 0; 03831 default: 03832 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 03833 res = -1; 03834 } 03835 ast_mutex_unlock(&p->lock); 03836 return res; 03837 }
| 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 4151 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().
04152 { 04153 struct ast_channel *who; 04154 struct dahdi_pvt *p0, *p1, *op0, *op1; 04155 struct dahdi_pvt *master = NULL, *slave = NULL; 04156 struct ast_frame *f; 04157 int inconf = 0; 04158 int nothingok = 1; 04159 int ofd0, ofd1; 04160 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 04161 int os0 = -1, os1 = -1; 04162 int priority = 0; 04163 struct ast_channel *oc0, *oc1; 04164 enum ast_bridge_result res; 04165 04166 #ifdef PRI_2BCT 04167 int triedtopribridge = 0; 04168 q931_call *q931c0 = NULL, *q931c1 = NULL; 04169 #endif 04170 04171 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 04172 There is code below to handle it properly until DTMF is actually seen, 04173 but due to currently unresolved issues it's ignored... 04174 */ 04175 04176 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 04177 return AST_BRIDGE_FAILED_NOWARN; 04178 04179 ast_channel_lock(c0); 04180 while (ast_channel_trylock(c1)) { 04181 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04182 } 04183 04184 p0 = c0->tech_pvt; 04185 p1 = c1->tech_pvt; 04186 /* cant do pseudo-channels here */ 04187 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 04188 ast_channel_unlock(c0); 04189 ast_channel_unlock(c1); 04190 return AST_BRIDGE_FAILED_NOWARN; 04191 } 04192 04193 oi0 = dahdi_get_index(c0, p0, 0); 04194 oi1 = dahdi_get_index(c1, p1, 0); 04195 if ((oi0 < 0) || (oi1 < 0)) { 04196 ast_channel_unlock(c0); 04197 ast_channel_unlock(c1); 04198 return AST_BRIDGE_FAILED; 04199 } 04200 04201 op0 = p0 = c0->tech_pvt; 04202 op1 = p1 = c1->tech_pvt; 04203 ofd0 = c0->fds[0]; 04204 ofd1 = c1->fds[0]; 04205 oc0 = p0->owner; 04206 oc1 = p1->owner; 04207 04208 if (ast_mutex_trylock(&p0->lock)) { 04209 /* Don't block, due to potential for deadlock */ 04210 ast_channel_unlock(c0); 04211 ast_channel_unlock(c1); 04212 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04213 return AST_BRIDGE_RETRY; 04214 } 04215 if (ast_mutex_trylock(&p1->lock)) { 04216 /* Don't block, due to potential for deadlock */ 04217 ast_mutex_unlock(&p0->lock); 04218 ast_channel_unlock(c0); 04219 ast_channel_unlock(c1); 04220 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 04221 return AST_BRIDGE_RETRY; 04222 } 04223 04224 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04225 if (p0->owner && p1->owner) { 04226 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 04227 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 04228 master = p0; 04229 slave = p1; 04230 inconf = 1; 04231 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 04232 master = p1; 04233 slave = p0; 04234 inconf = 1; 04235 } else { 04236 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 04237 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 04238 p0->channel, 04239 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04240 p0->subs[SUB_REAL].inthreeway, p0->channel, 04241 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 04242 p1->subs[SUB_REAL].inthreeway); 04243 } 04244 nothingok = 0; 04245 } 04246 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 04247 if (p1->subs[SUB_THREEWAY].inthreeway) { 04248 master = p1; 04249 slave = p0; 04250 nothingok = 0; 04251 } 04252 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 04253 if (p0->subs[SUB_THREEWAY].inthreeway) { 04254 master = p0; 04255 slave = p1; 04256 nothingok = 0; 04257 } 04258 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 04259 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 04260 don't put us in anything */ 04261 if (p1->subs[SUB_CALLWAIT].inthreeway) { 04262 master = p1; 04263 slave = p0; 04264 nothingok = 0; 04265 } 04266 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 04267 /* Same as previous */ 04268 if (p0->subs[SUB_CALLWAIT].inthreeway) { 04269 master = p0; 04270 slave = p1; 04271 nothingok = 0; 04272 } 04273 } 04274 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 04275 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 04276 if (master && slave) { 04277 /* Stop any tones, or play ringtone as appropriate. If they're bridged 04278 in an active threeway call with a channel that is ringing, we should 04279 indicate ringing. */ 04280 if ((oi1 == SUB_THREEWAY) && 04281 p1->subs[SUB_THREEWAY].inthreeway && 04282 p1->subs[SUB_REAL].owner && 04283 p1->subs[SUB_REAL].inthreeway && 04284 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04285 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 04286 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 04287 os1 = p1->subs[SUB_REAL].owner->_state; 04288 } else { 04289 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 04290 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 04291 } 04292 if ((oi0 == SUB_THREEWAY) && 04293 p0->subs[SUB_THREEWAY].inthreeway && 04294 p0->subs[SUB_REAL].owner && 04295 p0->subs[SUB_REAL].inthreeway && 04296 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 04297 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 04298 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 04299 os0 = p0->subs[SUB_REAL].owner->_state; 04300 } else { 04301 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 04302 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 04303 } 04304 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 04305 if (!p0->echocanbridged || !p1->echocanbridged) { 04306 /* Disable echo cancellation if appropriate */ 04307 dahdi_disable_ec(p0); 04308 dahdi_disable_ec(p1); 04309 } 04310 } 04311 dahdi_link(slave, master); 04312 master->inconference = inconf; 04313 } else if (!nothingok) 04314 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 04315 04316 update_conf(p0); 04317 update_conf(p1); 04318 t0 = p0->subs[SUB_REAL].inthreeway; 04319 t1 = p1->subs[SUB_REAL].inthreeway; 04320 04321 ast_mutex_unlock(&p0->lock); 04322 ast_mutex_unlock(&p1->lock); 04323 04324 ast_channel_unlock(c0); 04325 ast_channel_unlock(c1); 04326 04327 /* Native bridge failed */ 04328 if ((!master || !slave) && !nothingok) { 04329 dahdi_enable_ec(p0); 04330 dahdi_enable_ec(p1); 04331 return AST_BRIDGE_FAILED; 04332 } 04333 04334 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 04335 04336 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04337 disable_dtmf_detect(op0); 04338 04339 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04340 disable_dtmf_detect(op1); 04341 04342 for (;;) { 04343 struct ast_channel *c0_priority[2] = {c0, c1}; 04344 struct ast_channel *c1_priority[2] = {c1, c0}; 04345 04346 /* Here's our main loop... Start by locking things, looking for private parts, 04347 and then balking if anything is wrong */ 04348 04349 ast_channel_lock(c0); 04350 while (ast_channel_trylock(c1)) { 04351 CHANNEL_DEADLOCK_AVOIDANCE(c0); 04352 } 04353 04354 p0 = c0->tech_pvt; 04355 p1 = c1->tech_pvt; 04356 04357 if (op0 == p0) 04358 i0 = dahdi_get_index(c0, p0, 1); 04359 if (op1 == p1) 04360 i1 = dahdi_get_index(c1, p1, 1); 04361 04362 ast_channel_unlock(c0); 04363 ast_channel_unlock(c1); 04364 04365 if (!timeoutms || 04366 (op0 != p0) || 04367 (op1 != p1) || 04368 (ofd0 != c0->fds[0]) || 04369 (ofd1 != c1->fds[0]) || 04370 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 04371 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 04372 (oc0 != p0->owner) || 04373 (oc1 != p1->owner) || 04374 (t0 != p0->subs[SUB_REAL].inthreeway) || 04375 (t1 != p1->subs[SUB_REAL].inthreeway) || 04376 (oi0 != i0) || 04377 (oi1 != i1)) { 04378 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 04379 op0->channel, oi0, op1->channel, oi1); 04380 res = AST_BRIDGE_RETRY; 04381 goto return_from_bridge; 04382 } 04383 04384 #ifdef PRI_2BCT 04385 q931c0 = p0->call; 04386 q931c1 = p1->call; 04387 if (p0->transfer && p1->transfer 04388 && q931c0 && q931c1 04389 && !triedtopribridge) { 04390 pri_channel_bridge(q931c0, q931c1); 04391 triedtopribridge = 1; 04392 } 04393 #endif 04394 04395 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 04396 if (!who) { 04397 ast_debug(1, "Ooh, empty read...\n"); 04398 continue; 04399 } 04400 f = ast_read(who); 04401 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 04402 *fo = f; 04403 *rc = who; 04404 res = AST_BRIDGE_COMPLETE; 04405 goto return_from_bridge; 04406 } 04407 if (f->frametype == AST_FRAME_DTMF) { 04408 if ((who == c0) && p0->pulsedial) { 04409 ast_write(c1, f); 04410 } else if ((who == c1) && p1->pulsedial) { 04411 ast_write(c0, f); 04412 } else { 04413 *fo = f; 04414 *rc = who; 04415 res = AST_BRIDGE_COMPLETE; 04416 goto return_from_bridge; 04417 } 04418 } 04419 ast_frfree(f); 04420 04421 /* Swap who gets priority */ 04422 priority = !priority; 04423 } 04424 04425 return_from_bridge: 04426 if (op0 == p0) 04427 dahdi_enable_ec(p0); 04428 04429 if (op1 == p1) 04430 dahdi_enable_ec(p1); 04431 04432 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 04433 enable_dtmf_detect(op0); 04434 04435 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 04436 enable_dtmf_detect(op1); 04437 04438 dahdi_unlink(slave, master, 1); 04439 04440 return res; 04441 }
| static int dahdi_call | ( | struct ast_channel * | ast, | |
| char * | rdest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 2443 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::answeronpolarityswitch, ast_callerid_generate(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_tvnow(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_ref_pc, dahdi_ss7::called_nai, dahdi_ss7::calling_nai, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, dahdi_pvt::cic, ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, cid_pres2ss7pres(), cid_pres2ss7screen(), ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::dpc, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, dahdi_pvt::gen_add_nai, dahdi_pvt::gen_add_num_plan, dahdi_pvt::gen_add_pres_ind, dahdi_pvt::gen_add_type, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, dahdi_ss7::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::lspi_ident, MAX_CALLERID_SIZE, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), SS7_NAI_DYNAMIC, ss7_rel(), dahdi_pvt::ss7call, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, and dahdi_pvt::whichwink.
02444 { 02445 struct dahdi_pvt *p = ast->tech_pvt; 02446 int x, res, idx,mysig; 02447 char *c, *n, *l; 02448 #ifdef HAVE_PRI 02449 char *s = NULL; 02450 #endif 02451 char dest[256]; /* must be same length as p->dialdest */ 02452 ast_mutex_lock(&p->lock); 02453 ast_copy_string(dest, rdest, sizeof(dest)); 02454 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 02455 if ((ast->_state == AST_STATE_BUSY)) { 02456 p->subs[SUB_REAL].needbusy = 1; 02457 ast_mutex_unlock(&p->lock); 02458 return 0; 02459 } 02460 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 02461 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 02462 ast_mutex_unlock(&p->lock); 02463 return -1; 02464 } 02465 p->dialednone = 0; 02466 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 02467 { 02468 /* Special pseudo -- automatically up */ 02469 ast_setstate(ast, AST_STATE_UP); 02470 ast_mutex_unlock(&p->lock); 02471 return 0; 02472 } 02473 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 02474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 02475 if (res) 02476 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 02477 p->outgoing = 1; 02478 02479 if (IS_DIGITAL(ast->transfercapability)){ 02480 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 02481 } else { 02482 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02483 } 02484 02485 mysig = p->sig; 02486 if (p->outsigmod > -1) 02487 mysig = p->outsigmod; 02488 02489 switch (mysig) { 02490 case SIG_FXOLS: 02491 case SIG_FXOGS: 02492 case SIG_FXOKS: 02493 if (p->owner == ast) { 02494 /* Normal ring, on hook */ 02495 02496 /* Don't send audio while on hook, until the call is answered */ 02497 p->dialing = 1; 02498 if (p->use_callerid) { 02499 /* Generate the Caller-ID spill if desired */ 02500 if (p->cidspill) { 02501 ast_log(LOG_WARNING, "cidspill already exists??\n"); 02502 ast_free(p->cidspill); 02503 } 02504 p->callwaitcas = 0; 02505 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 02506 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 02507 p->cidpos = 0; 02508 send_callerid(p); 02509 } 02510 } 02511 /* Choose proper cadence */ 02512 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 02513 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 02514 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 02515 p->cidrings = cidrings[p->distinctivering - 1]; 02516 } else { 02517 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 02518 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 02519 p->cidrings = p->sendcalleridafter; 02520 } 02521 02522 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 02523 c = strchr(dest, '/'); 02524 if (c) 02525 c++; 02526 if (c && (strlen(c) < p->stripmsd)) { 02527 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02528 c = NULL; 02529 } 02530 if (c) { 02531 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02532 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 02533 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c); 02534 } else { 02535 p->dop.dialstr[0] = '\0'; 02536 } 02537 x = DAHDI_RING; 02538 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 02539 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 02540 ast_mutex_unlock(&p->lock); 02541 return -1; 02542 } 02543 p->dialing = 1; 02544 } else { 02545 /* Call waiting call */ 02546 p->callwaitrings = 0; 02547 if (ast->cid.cid_num) 02548 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 02549 else 02550 p->callwait_num[0] = '\0'; 02551 if (ast->cid.cid_name) 02552 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 02553 else 02554 p->callwait_name[0] = '\0'; 02555 /* Call waiting tone instead */ 02556 if (dahdi_callwait(ast)) { 02557 ast_mutex_unlock(&p->lock); 02558 return -1; 02559 } 02560 /* Make ring-back */ 02561 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 02562 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 02563 02564 } 02565 n = ast->cid.cid_name; 02566 l = ast->cid.cid_num; 02567 if (l) 02568 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 02569 else 02570 p->lastcid_num[0] = '\0'; 02571 if (n) 02572 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 02573 else 02574 p->lastcid_name[0] = '\0'; 02575 ast_setstate(ast, AST_STATE_RINGING); 02576 idx = dahdi_get_index(ast, p, 0); 02577 if (idx > -1) { 02578 p->subs[idx].needringing = 1; 02579 } 02580 break; 02581 case SIG_FXSLS: 02582 case SIG_FXSGS: 02583 case SIG_FXSKS: 02584 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 02585 ast_debug(1, "Ignore possible polarity reversal on line seizure\n"); 02586 p->polaritydelaytv = ast_tvnow(); 02587 } 02588 /* fall through */ 02589 case SIG_EMWINK: 02590 case SIG_EM: 02591 case SIG_EM_E1: 02592 case SIG_FEATD: 02593 case SIG_FEATDMF: 02594 case SIG_E911: 02595 case SIG_FGC_CAMA: 02596 case SIG_FGC_CAMAMF: 02597 case SIG_FEATB: 02598 case SIG_SFWINK: 02599 case SIG_SF: 02600 case SIG_SF_FEATD: 02601 case SIG_SF_FEATDMF: 02602 case SIG_FEATDMF_TA: 02603 case SIG_SF_FEATB: 02604 c = strchr(dest, '/'); 02605 if (c) 02606 c++; 02607 else 02608 c = ""; 02609 if (strlen(c) < p->stripmsd) { 02610 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02611 ast_mutex_unlock(&p->lock); 02612 return -1; 02613 } 02614 #ifdef HAVE_PRI 02615 /* Start the trunk, if not GR-303 */ 02616 if (!p->pri) { 02617 #endif 02618 x = DAHDI_START; 02619 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02620 if (res < 0) { 02621 if (errno != EINPROGRESS) { 02622 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02623 ast_mutex_unlock(&p->lock); 02624 return -1; 02625 } 02626 } 02627 #ifdef HAVE_PRI 02628 } 02629 #endif 02630 ast_debug(1, "Dialing '%s'\n", c); 02631 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02632 02633 c += p->stripmsd; 02634 02635 switch (mysig) { 02636 case SIG_FEATD: 02637 l = ast->cid.cid_num; 02638 if (l) 02639 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02640 else 02641 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02642 break; 02643 case SIG_FEATDMF: 02644 l = ast->cid.cid_num; 02645 if (l) 02646 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02647 else 02648 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02649 break; 02650 case SIG_FEATDMF_TA: 02651 { 02652 const char *cic, *ozz; 02653 02654 /* If you have to go through a Tandem Access point you need to use this */ 02655 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02656 if (!ozz) 02657 ozz = defaultozz; 02658 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02659 if (!cic) 02660 cic = defaultcic; 02661 if (!ozz || !cic) { 02662 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02663 ast_mutex_unlock(&p->lock); 02664 return -1; 02665 } 02666 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02667 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02668 p->whichwink = 0; 02669 } 02670 break; 02671 case SIG_E911: 02672 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02673 break; 02674 case SIG_FGC_CAMA: 02675 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02676 break; 02677 case SIG_FGC_CAMAMF: 02678 case SIG_FEATB: 02679 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02680 break; 02681 default: 02682 if (p->pulse) 02683 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02684 else 02685 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02686 break; 02687 } 02688 02689 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02690 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02691 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02692 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02693 p->echobreak = 1; 02694 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02695 } else 02696 p->echobreak = 0; 02697 if (!res) { 02698 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02699 int saveerr = errno; 02700 02701 x = DAHDI_ONHOOK; 02702 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02703 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02704 ast_mutex_unlock(&p->lock); 02705 return -1; 02706 } 02707 } else 02708 ast_debug(1, "Deferring dialing...\n"); 02709 02710 p->dialing = 1; 02711 if (ast_strlen_zero(c)) 02712 p->dialednone = 1; 02713 ast_setstate(ast, AST_STATE_DIALING); 02714 break; 02715 case 0: 02716 /* Special pseudo -- automatically up*/ 02717 ast_setstate(ast, AST_STATE_UP); 02718 break; 02719 case SIG_PRI: 02720 case SIG_BRI: 02721 case SIG_BRI_PTMP: 02722 case SIG_SS7: 02723 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02724 p->dialdest[0] = '\0'; 02725 p->dialing = 1; 02726 break; 02727 default: 02728 ast_debug(1, "not yet implemented\n"); 02729 ast_mutex_unlock(&p->lock); 02730 return -1; 02731 } 02732 #ifdef HAVE_SS7 02733 if (p->ss7) { 02734 char ss7_called_nai; 02735 int called_nai_strip; 02736 char ss7_calling_nai; 02737 int calling_nai_strip; 02738 const char *charge_str = NULL; 02739 const char *gen_address = NULL; 02740 const char *gen_digits = NULL; 02741 const char *gen_dig_type = NULL; 02742 const char *gen_dig_scheme = NULL; 02743 const char *gen_name = NULL; 02744 const char *jip_digits = NULL; 02745 const char *lspi_ident = NULL; 02746 const char *rlt_flag = NULL; 02747 const char *call_ref_id = NULL; 02748 const char *call_ref_pc = NULL; 02749 const char *send_far = NULL; 02750 02751 c = strchr(dest, '/'); 02752 if (c) { 02753 c++; 02754 } else { 02755 c = ""; 02756 } 02757 if (strlen(c) < p->stripmsd) { 02758 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02759 ast_mutex_unlock(&p->lock); 02760 return -1; 02761 } 02762 02763 if (!p->hidecallerid) { 02764 l = ast->cid.cid_num; 02765 } else { 02766 l = NULL; 02767 } 02768 02769 if (ss7_grab(p, p->ss7)) { 02770 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 02771 ast_mutex_unlock(&p->lock); 02772 return -1; 02773 } 02774 p->digital = IS_DIGITAL(ast->transfercapability); 02775 p->ss7call = isup_new_call(p->ss7->ss7); 02776 02777 if (!p->ss7call) { 02778 ss7_rel(p->ss7); 02779 ast_mutex_unlock(&p->lock); 02780 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 02781 return -1; 02782 } 02783 02784 called_nai_strip = 0; 02785 ss7_called_nai = p->ss7->called_nai; 02786 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 02787 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02788 called_nai_strip = strlen(p->ss7->internationalprefix); 02789 ss7_called_nai = SS7_NAI_INTERNATIONAL; 02790 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02791 called_nai_strip = strlen(p->ss7->nationalprefix); 02792 ss7_called_nai = SS7_NAI_NATIONAL; 02793 } else { 02794 ss7_called_nai = SS7_NAI_SUBSCRIBER; 02795 } 02796 } 02797 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 02798 02799 calling_nai_strip = 0; 02800 ss7_calling_nai = p->ss7->calling_nai; 02801 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 02802 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 02803 calling_nai_strip = strlen(p->ss7->internationalprefix); 02804 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 02805 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 02806 calling_nai_strip = strlen(p->ss7->nationalprefix); 02807 ss7_calling_nai = SS7_NAI_NATIONAL; 02808 } else { 02809 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 02810 } 02811 } 02812 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 02813 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 02814 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED ); 02815 02816 isup_set_oli(p->ss7call, ast->cid.cid_ani2); 02817 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 02818 02819 ast_channel_lock(ast); 02820 /* Set the charge number if it is set */ 02821 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 02822 if (charge_str) 02823 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 02824 02825 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 02826 if (gen_address) 02827 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 */ 02828 02829 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 02830 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 02831 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 02832 if (gen_digits) 02833 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 02834 02835 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 02836 if (gen_name) 02837 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 02838 02839 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 02840 if (jip_digits) 02841 isup_set_jip_digits(p->ss7call, jip_digits); 02842 02843 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 02844 if (lspi_ident) 02845 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 02846 02847 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 02848 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 02849 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 02850 } 02851 02852 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 02853 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 02854 if (call_ref_id && call_ref_pc) { 02855 isup_set_callref(p->ss7call, atoi(call_ref_id), 02856 call_ref_pc ? atoi(call_ref_pc) : 0); 02857 } 02858 02859 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 02860 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 02861 (isup_far(p->ss7->ss7, p->ss7call)); 02862 02863 ast_channel_unlock(ast); 02864 02865 isup_iam(p->ss7->ss7, p->ss7call); 02866 ast_setstate(ast, AST_STATE_DIALING); 02867 ss7_rel(p->ss7); 02868 } 02869 #endif /* HAVE_SS7 */ 02870 #ifdef HAVE_PRI 02871 if (p->pri) { 02872 struct pri_sr *sr; 02873 #ifdef SUPPORT_USERUSER 02874 const char *useruser; 02875 #endif 02876 int pridialplan; 02877 int dp_strip; 02878 int prilocaldialplan; 02879 int ldp_strip; 02880 int exclusive; 02881 const char *rr_str; 02882 int redirect_reason; 02883 02884 c = strchr(dest, '/'); 02885 if (c) { 02886 c++; 02887 } else { 02888 c = ""; 02889 } 02890 02891 l = NULL; 02892 n = NULL; 02893 if (!p->hidecallerid) { 02894 l = ast->cid.cid_num; 02895 if (!p->hidecalleridname) { 02896 n = ast->cid.cid_name; 02897 } 02898 } 02899 02900 if (strlen(c) < p->stripmsd) { 02901 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02902 ast_mutex_unlock(&p->lock); 02903 return -1; 02904 } 02905 if (mysig != SIG_FXSKS) { 02906 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02907 s = strchr(c + p->stripmsd, 'w'); 02908 if (s) { 02909 if (strlen(s) > 1) 02910 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02911 else 02912 p->dop.dialstr[0] = '\0'; 02913 *s = '\0'; 02914 } else { 02915 p->dop.dialstr[0] = '\0'; 02916 } 02917 } 02918 if (pri_grab(p, p->pri)) { 02919 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02920 ast_mutex_unlock(&p->lock); 02921 return -1; 02922 } 02923 if (!(p->call = pri_new_call(p->pri->pri))) { 02924 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02925 pri_rel(p->pri); 02926 ast_mutex_unlock(&p->lock); 02927 return -1; 02928 } 02929 if (!(sr = pri_sr_new())) { 02930 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02931 pri_rel(p->pri); 02932 ast_mutex_unlock(&p->lock); 02933 } 02934 if (p->bearer || (mysig == SIG_FXSKS)) { 02935 if (p->bearer) { 02936 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 02937 p->bearer->call = p->call; 02938 } else 02939 ast_debug(1, "I'm being setup with no bearer right now...\n"); 02940 02941 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02942 } 02943 p->digital = IS_DIGITAL(ast->transfercapability); 02944 02945 /* Should the picked channel be used exclusively? */ 02946 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 02947 exclusive = 1; 02948 } else { 02949 exclusive = 0; 02950 } 02951 02952 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02953 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02954 (p->digital ? -1 : 02955 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02956 if (p->pri->facilityenable) 02957 pri_facility_enable(p->pri->pri); 02958 02959 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02960 dp_strip = 0; 02961 pridialplan = p->pri->dialplan - 1; 02962 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */ 02963 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02964 if (pridialplan == -2) { 02965 dp_strip = strlen(p->pri->internationalprefix); 02966 } 02967 pridialplan = PRI_INTERNATIONAL_ISDN; 02968 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02969 if (pridialplan == -2) { 02970 dp_strip = strlen(p->pri->nationalprefix); 02971 } 02972 pridialplan = PRI_NATIONAL_ISDN; 02973 } else { 02974 pridialplan = PRI_LOCAL_ISDN; 02975 } 02976 } 02977 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') { 02978 switch (c[p->stripmsd]) { 02979 case 'U': 02980 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf); 02981 break; 02982 case 'I': 02983 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf); 02984 break; 02985 case 'N': 02986 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf); 02987 break; 02988 case 'L': 02989 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf); 02990 break; 02991 case 'S': 02992 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf); 02993 break; 02994 case 'V': 02995 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf); 02996 break; 02997 case 'R': 02998 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf); 02999 break; 03000 case 'u': 03001 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0); 03002 break; 03003 case 'e': 03004 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0); 03005 break; 03006 case 'x': 03007 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0); 03008 break; 03009 case 'f': 03010 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0); 03011 break; 03012 case 'n': 03013 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0); 03014 break; 03015 case 'p': 03016 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0); 03017 break; 03018 case 'r': 03019 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0); 03020 break; 03021 default: 03022 if (isalpha(c[p->stripmsd])) { 03023 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", 03024 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]); 03025 } 03026 break; 03027 } 03028 c++; 03029 } 03030 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03031 03032 ldp_strip = 0; 03033 prilocaldialplan = p->pri->localdialplan - 1; 03034 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */ 03035 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03036 if (prilocaldialplan == -2) { 03037 ldp_strip = strlen(p->pri->internationalprefix); 03038 } 03039 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03040 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03041 if (prilocaldialplan == -2) { 03042 ldp_strip = strlen(p->pri->nationalprefix); 03043 } 03044 prilocaldialplan = PRI_NATIONAL_ISDN; 03045 } else { 03046 prilocaldialplan = PRI_LOCAL_ISDN; 03047 } 03048 } 03049 if (l != NULL) { 03050 while (*l > '9' && *l != '*' && *l != '#') { 03051 switch (*l) { 03052 case 'U': 03053 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf); 03054 break; 03055 case 'I': 03056 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf); 03057 break; 03058 case 'N': 03059 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf); 03060 break; 03061 case 'L': 03062 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf); 03063 break; 03064 case 'S': 03065 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf); 03066 break; 03067 case 'V': 03068 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf); 03069 break; 03070 case 'R': 03071 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf); 03072 break; 03073 case 'u': 03074 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0); 03075 break; 03076 case 'e': 03077 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0); 03078 break; 03079 case 'x': 03080 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0); 03081 break; 03082 case 'f': 03083 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0); 03084 break; 03085 case 'n': 03086 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0); 03087 break; 03088 case 'p': 03089 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0); 03090 break; 03091 case 'r': 03092 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0); 03093 break; 03094 default: 03095 if (isalpha(*l)) { 03096 ast_log(LOG_WARNING, 03097 "Unrecognized prilocaldialplan %s modifier: %c\n", 03098 *l > 'Z' ? "NPI" : "TON", *l); 03099 } 03100 break; 03101 } 03102 l++; 03103 } 03104 } 03105 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03106 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03107 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03108 if (!strcasecmp(rr_str, "UNKNOWN")) 03109 redirect_reason = 0; 03110 else if (!strcasecmp(rr_str, "BUSY")) 03111 redirect_reason = 1; 03112 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER")) 03113 /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */ 03114 redirect_reason = 2; 03115 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03116 redirect_reason = 15; 03117 else 03118 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03119 } else 03120 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03121 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03122 03123 #ifdef SUPPORT_USERUSER 03124 /* User-user info */ 03125 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03126 03127 if (useruser) 03128 pri_sr_set_useruser(sr, useruser); 03129 #endif 03130 03131 if (pri_setup(p->pri->pri, p->call, sr)) { 03132 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03133 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03134 pri_rel(p->pri); 03135 ast_mutex_unlock(&p->lock); 03136 pri_sr_free(sr); 03137 return -1; 03138 } 03139 pri_sr_free(sr); 03140 ast_setstate(ast, AST_STATE_DIALING); 03141 pri_rel(p->pri); 03142 } 03143 #endif 03144 ast_mutex_unlock(&p->lock); 03145 return 0; 03146 }
| static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2403 of file chan_dahdi.c.
References ast_free, ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.
Referenced by dahdi_call(), and dahdi_read().
02404 { 02405 struct dahdi_pvt *p = ast->tech_pvt; 02406 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 02407 if (p->cidspill) { 02408 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 02409 ast_free(p->cidspill); 02410 } 02411 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 02412 return -1; 02413 save_conference(p); 02414 /* Silence */ 02415 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 02416 if (!p->callwaitrings && p->callwaitingcallerid) { 02417 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 02418 p->callwaitcas = 1; 02419 p->cidlen = 2400 + 680 + READ_SIZE * 4; 02420 } else { 02421 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 02422 p->callwaitcas = 0; 02423 p->cidlen = 2400 + READ_SIZE * 4; 02424 } 02425 p->cidpos = 0; 02426 send_callerid(p); 02427 02428 return 0; 02429 }
| static struct dahdi_chan_conf dahdi_chan_conf_default | ( | void | ) | [static, read] |
returns a new dahdi_chan_conf with default values (by-value)
Definition at line 1093 of file chan_dahdi.c.
References CID_SIG_BELL, CID_START_RING, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.
Referenced by process_dahdi(), and setup_dahdi().
01093 { 01094 /* recall that if a field is not included here it is initialized 01095 * to 0 or equivalent 01096 */ 01097 struct dahdi_chan_conf conf = { 01098 #ifdef HAVE_PRI 01099 .pri = { 01100 .nsf = PRI_NSF_NONE, 01101 .switchtype = PRI_SWITCH_NI2, 01102 .dialplan = PRI_UNKNOWN + 1, 01103 .localdialplan = PRI_NATIONAL_ISDN + 1, 01104 .nodetype = PRI_CPE, 01105 01106 .minunused = 2, 01107 .idleext = "", 01108 .idledial = "", 01109 .internationalprefix = "", 01110 .nationalprefix = "", 01111 .localprefix = "", 01112 .privateprefix = "", 01113 .unknownprefix = "", 01114 .resetinterval = -1, 01115 }, 01116 #endif 01117 #ifdef HAVE_SS7 01118 .ss7 = { 01119 .called_nai = SS7_NAI_NATIONAL, 01120 .calling_nai = SS7_NAI_NATIONAL, 01121 .internationalprefix = "", 01122 .nationalprefix = "", 01123 .subscriberprefix = "", 01124 .unknownprefix = "" 01125 }, 01126 #endif 01127 .chan = { 01128 .context = "default", 01129 .cid_num = "", 01130 .cid_name = "", 01131 .mohinterpret = "default", 01132 .mohsuggest = "", 01133 .parkinglot = "", 01134 .transfertobusy = 1, 01135 01136 .cid_signalling = CID_SIG_BELL, 01137 .cid_start = CID_START_RING, 01138 .dahditrcallerid = 0, 01139 .use_callerid = 1, 01140 .sig = -1, 01141 .outsigmod = -1, 01142 01143 .cid_rxgain = +5.0, 01144 01145 .tonezone = -1, 01146 01147 .echocancel.head.tap_length = 1, 01148 01149 .busycount = 3, 01150 01151 .accountcode = "", 01152 01153 .mailbox = "", 01154 01155 01156 .polarityonanswerdelay = 600, 01157 01158 .sendcalleridafter = DEFAULT_CIDRINGS, 01159 01160 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01161 .buf_no = numbufs 01162 }, 01163 .timing = { 01164 .prewinktime = -1, 01165 .preflashtime = -1, 01166 .winktime = -1, 01167 .flashtime = -1, 01168 .starttime = -1, 01169 .rxwinktime = -1, 01170 .rxflashtime = -1, 01171 .debouncetime = -1 01172 }, 01173 .is_sig_auto = 1, 01174 .smdi_port = "/dev/ttyS0", 01175 }; 01176 01177 return conf; 01178 }
| static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 1483 of file chan_dahdi.c.
Referenced by dahdi_close_pri_fd(), dahdi_close_ss7_fd(), and dahdi_close_sub().
| static void dahdi_close_pri_fd | ( | struct dahdi_pri * | pri, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 1496 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
01497 { 01498 dahdi_close(pri->fds[fd_num]); 01499 pri->fds[fd_num] = -1; 01500 }
| static void dahdi_close_ss7_fd | ( | struct dahdi_ss7 * | ss7, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 1504 of file chan_dahdi.c.
References dahdi_close(), and dahdi_ss7::fds.
Referenced by __unload_module(), dahdi_restart(), and linkset_addsigchan().
01505 { 01506 dahdi_close(ss7->fds[fd_num]); 01507 ss7->fds[fd_num] = -1; 01508 }
| static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
| int | sub_num | |||
| ) | [static] |
Definition at line 1489 of file chan_dahdi.c.
References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by alloc_sub(), destroy_dahdi_pvt(), pri_fixup_principle(), and unalloc_sub().
01490 { 01491 dahdi_close(chan_pvt->subs[sub_num].dfd); 01492 chan_pvt->subs[sub_num].dfd = -1; 01493 }
| static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
| int | muted | |||
| ) | [inline, static] |
Definition at line 2224 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_dtmfup(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), and dahdi_read().
02225 { 02226 int x, y, res; 02227 x = muted; 02228 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 02229 y = 1; 02230 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02231 if (res) 02232 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02233 } 02234 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02235 if (res < 0) 02236 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02237 return res; 02238 }
| static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12481 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.
12482 { 12483 int channel; 12484 int ret; 12485 switch (cmd) { 12486 case CLI_INIT: 12487 e->command = "dahdi destroy channel"; 12488 e->usage = 12489 "Usage: dahdi destroy channel <chan num>\n" 12490 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 12491 return NULL; 12492 case CLI_GENERATE: 12493 return NULL; 12494 } 12495 if (a->argc != 4) 12496 return CLI_SHOWUSAGE; 12497 12498 channel = atoi(a->argv[3]); 12499 ret = dahdi_destroy_channel_bynum(channel); 12500 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 12501 }
| static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 8077 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().
08078 { 08079 struct dahdi_pvt *tmp = NULL; 08080 struct dahdi_pvt *prev = NULL; 08081 08082 tmp = iflist; 08083 while (tmp) { 08084 if (tmp->channel == channel) { 08085 int x = DAHDI_FLASH; 08086 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 */ 08087 destroy_channel(prev, tmp, 1); 08088 ast_module_unref(ast_module_info->self); 08089 return RESULT_SUCCESS; 08090 } 08091 prev = tmp; 08092 tmp = tmp->next; 08093 } 08094 return RESULT_FAILURE; 08095 }
| static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 1591 of file chan_dahdi.c.
References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::pulse, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01592 { 01593 struct dahdi_pvt *pvt; 01594 int idx; 01595 int dtmf = -1; 01596 01597 pvt = chan->tech_pvt; 01598 01599 ast_mutex_lock(&pvt->lock); 01600 01601 idx = dahdi_get_index(chan, pvt, 0); 01602 01603 if ((idx != SUB_REAL) || !pvt->owner) 01604 goto out; 01605 01606 #ifdef HAVE_PRI 01607 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01608 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01609 if (pvt->setup_ack) { 01610 if (!pri_grab(pvt, pvt->pri)) { 01611 pri_information(pvt->pri->pri, pvt->call, digit); 01612 pri_rel(pvt->pri); 01613 } else 01614 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01615 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01616 int res; 01617 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01618 res = strlen(pvt->dialdest); 01619 pvt->dialdest[res++] = digit; 01620 pvt->dialdest[res] = '\0'; 01621 } 01622 goto out; 01623 } 01624 #endif 01625 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01626 goto out; 01627 01628 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01629 int res; 01630 struct dahdi_dialoperation zo = { 01631 .op = DAHDI_DIAL_OP_APPEND, 01632 }; 01633 01634 zo.dialstr[0] = 'T'; 01635 zo.dialstr[1] = digit; 01636 zo.dialstr[2] = '\0'; 01637 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01638 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01639 else 01640 pvt->dialing = 1; 01641 } else { 01642 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 01643 pvt->dialing = 1; 01644 pvt->begindigit = digit; 01645 } 01646 01647 out: 01648 ast_mutex_unlock(&pvt->lock); 01649 01650 return 0; 01651 }
| static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 1653 of file chan_dahdi.c.
References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01654 { 01655 struct dahdi_pvt *pvt; 01656 int res = 0; 01657 int idx; 01658 int x; 01659 01660 pvt = chan->tech_pvt; 01661 01662 ast_mutex_lock(&pvt->lock); 01663 01664 idx = dahdi_get_index(chan, pvt, 0); 01665 01666 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 01667 goto out; 01668 01669 #ifdef HAVE_PRI 01670 /* This means that the digit was already sent via PRI signalling */ 01671 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 01672 && !pvt->begindigit) 01673 goto out; 01674 #endif 01675 01676 if (pvt->begindigit) { 01677 x = -1; 01678 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 01679 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01680 pvt->dialing = 0; 01681 pvt->begindigit = 0; 01682 } 01683 01684 out: 01685 ast_mutex_unlock(&pvt->lock); 01686 01687 return res; 01688 }
| static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2053 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocanon, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().
02054 { 02055 int res; 02056 02057 if (p->echocanon) { 02058 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 02059 02060 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 02061 02062 if (res) 02063 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02064 else 02065 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 02066 } 02067 02068 p->echocanon = 0; 02069 }
| static void dahdi_dnd | ( | struct dahdi_pvt * | dahdichan, | |
| int | on | |||
| ) | [static] |
enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
| dahdichan | "Physical" DAHDI channel (e.g: DAHDI/5) | |
| on | 1 to enable, 0 to disable |
chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.
Definition at line 6540 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().
06541 { 06542 /* Do not disturb */ 06543 dahdichan->dnd = on; 06544 ast_verb(3, "%s DND on channel %d\n", 06545 on? "Enabled" : "Disabled", 06546 dahdichan->channel); 06547 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06548 "Channel: DAHDI/%d\r\n" 06549 "Status: %s\r\n", dahdichan->channel, 06550 on? "enabled" : "disabled"); 06551 }
| static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2004 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_indicate(), dahdi_setoption(), handle_init_event(), pri_dchannel(), ss7_linkset(), ss7_start_call(), and ss_thread().
02005 { 02006 int x; 02007 int res; 02008 if (!p) 02009 return; 02010 if (p->echocanon) { 02011 ast_debug(1, "Echo cancellation already on\n"); 02012 return; 02013 } 02014 if (p->digital) { 02015 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 02016 return; 02017 } 02018 if (p->echocancel.head.tap_length) { 02019 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) { 02020 x = 1; 02021 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02022 if (res) 02023 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02024 } 02025 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 02026 if (res) { 02027 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02028 } else { 02029 p->echocanon = 1; 02030 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 02031 } 02032 } else 02033 ast_debug(1, "No echo cancellation requested\n"); 02034 }
| static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5658 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
05659 { 05660 struct dahdi_pvt *p = ast->tech_pvt; 05661 struct ast_frame *f; 05662 ast_mutex_lock(&p->lock); 05663 f = __dahdi_exception(ast); 05664 ast_mutex_unlock(&p->lock); 05665 return f; 05666 }
| static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
| int | mode | |||
| ) | [static] |
Definition at line 13352 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().
13353 { 13354 if (p) { 13355 switch (mode) { 13356 case TRANSFER: 13357 p->fake_event = DAHDI_EVENT_WINKFLASH; 13358 break; 13359 case HANGUP: 13360 p->fake_event = DAHDI_EVENT_ONHOOK; 13361 break; 13362 default: 13363 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 13364 } 13365 } 13366 return 0; 13367 }
| static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 4443 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().
04444 { 04445 struct dahdi_pvt *p = newchan->tech_pvt; 04446 int x; 04447 ast_mutex_lock(&p->lock); 04448 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 04449 if (p->owner == oldchan) { 04450 p->owner = newchan; 04451 } 04452 for (x = 0; x < 3; x++) 04453 if (p->subs[x].owner == oldchan) { 04454 if (!x) 04455 dahdi_unlink(NULL, p, 0); 04456 p->subs[x].owner = newchan; 04457 } 04458 if (newchan->_state == AST_STATE_RINGING) 04459 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 04460 update_conf(p); 04461 ast_mutex_unlock(&p->lock); 04462 return 0; 04463 }
| static int dahdi_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 4020 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.
04021 { 04022 struct dahdi_pvt *p = chan->tech_pvt; 04023 04024 if (!strcasecmp(data, "rxgain")) { 04025 ast_mutex_lock(&p->lock); 04026 snprintf(buf, len, "%f", p->rxgain); 04027 ast_mutex_unlock(&p->lock); 04028 } else if (!strcasecmp(data, "txgain")) { 04029 ast_mutex_lock(&p->lock); 04030 snprintf(buf, len, "%f", p->txgain); 04031 ast_mutex_unlock(&p->lock); 04032 } else { 04033 ast_copy_string(buf, "", len); 04034 } 04035 return 0; 04036 }
| static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 303 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), mwi_send_thread(), mwi_thread(), and ss_thread().
| static int dahdi_get_index | ( | struct ast_channel * | ast, | |
| struct dahdi_pvt * | p, | |||
| int | nullok | |||
| ) | [static] |
Definition at line 1297 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_subchannel::owner, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), dahdi_write(), and ss_thread().
01298 { 01299 int res; 01300 if (p->subs[SUB_REAL].owner == ast) 01301 res = 0; 01302 else if (p->subs[SUB_CALLWAIT].owner == ast) 01303 res = 1; 01304 else if (p->subs[SUB_THREEWAY].owner == ast) 01305 res = 2; 01306 else { 01307 res = -1; 01308 if (!nullok) 01309 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01310 } 01311 return res; 01312 }
| static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
| int | idx, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 4604 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().
04605 { 04606 struct dahdi_pvt *p = ast->tech_pvt; 04607 struct ast_frame *f = *dest; 04608 04609 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 04610 04611 if (p->confirmanswer) { 04612 ast_debug(1, "Confirm answer on %s!\n", ast->name); 04613 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 04614 of a DTMF digit */ 04615 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04616 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04617 *dest = &p->subs[idx].f; 04618 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 04619 p->confirmanswer = 0; 04620 } else if (p->callwaitcas) { 04621 if ((f->subclass == 'A') || (f->subclass == 'D')) { 04622 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 04623 if (p->cidspill) 04624 ast_free(p->cidspill); 04625 send_cwcidspill(p); 04626 } 04627 p->callwaitcas = 0; 04628 p->subs[idx].f.frametype = AST_FRAME_NULL; 04629 p->subs[idx].f.subclass = 0; 04630 *dest = &p->subs[idx].f; 04631 } else if (f->subclass == 'f') { 04632 /* Fax tone -- Handle and return NULL */ 04633 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 04634 p->faxhandled = 1; 04635 if (strcmp(ast->exten, "fax")) { 04636 const char *target_context = S_OR(ast->macrocontext, ast->context); 04637 04638 /* We need to unlock 'ast' here because ast_exists_extension has the 04639 * potential to start autoservice on the channel. Such action is prone 04640 * to deadlock. 04641 */ 04642 ast_mutex_unlock(&p->lock); 04643 ast_channel_unlock(ast); 04644 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 04645 ast_channel_lock(ast); 04646 ast_mutex_lock(&p->lock); 04647 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 04648 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 04649 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 04650 if (ast_async_goto(ast, target_context, "fax", 1)) 04651 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 04652 } else { 04653 ast_channel_lock(ast); 04654 ast_mutex_lock(&p->lock); 04655 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 04656 } 04657 } else { 04658 ast_debug(1, "Already in a fax extension, not redirecting\n"); 04659 } 04660 } else { 04661 ast_debug(1, "Fax already handled\n"); 04662 } 04663 dahdi_confmute(p, 0); 04664 p->subs[idx].f.frametype = AST_FRAME_NULL; 04665 p->subs[idx].f.subclass = 0; 04666 *dest = &p->subs[idx].f; 04667 } 04668 }
| 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 4681 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().
04682 { 04683 int res, x; 04684 int idx, mysig; 04685 char *c; 04686 struct dahdi_pvt *p = ast->tech_pvt; 04687 pthread_t threadid; 04688 struct ast_channel *chan; 04689 struct ast_frame *f; 04690 04691 idx = dahdi_get_index(ast, p, 0); 04692 mysig = p->sig; 04693 if (p->outsigmod > -1) 04694 mysig = p->outsigmod; 04695 p->subs[idx].f.frametype = AST_FRAME_NULL; 04696 p->subs[idx].f.subclass = 0; 04697 p->subs[idx].f.datalen = 0; 04698 p->subs[idx].f.samples = 0; 04699 p->subs[idx].f.mallocd = 0; 04700 p->subs[idx].f.offset = 0; 04701 p->subs[idx].f.src = "dahdi_handle_event"; 04702 p->subs[idx].f.data.ptr = NULL; 04703 f = &p->subs[idx].f; 04704 04705 if (idx < 0) 04706 return &p->subs[idx].f; 04707 if (p->fake_event) { 04708 res = p->fake_event; 04709 p->fake_event = 0; 04710 } else 04711 res = dahdi_get_event(p->subs[idx].dfd); 04712 04713 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 04714 04715 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 04716 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 04717 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 04718 #ifdef HAVE_PRI 04719 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 04720 /* absorb event */ 04721 } else { 04722 #endif 04723 dahdi_confmute(p, 0); 04724 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 04725 p->subs[idx].f.subclass = res & 0xff; 04726 #ifdef HAVE_PRI 04727 } 04728 #endif 04729 dahdi_handle_dtmfup(ast, idx, &f); 04730 return f; 04731 } 04732 04733 if (res & DAHDI_EVENT_DTMFDOWN) { 04734 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 04735 /* Mute conference */ 04736 dahdi_confmute(p, 1); 04737 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 04738 p->subs[idx].f.subclass = res & 0xff; 04739 return &p->subs[idx].f; 04740 } 04741 04742 switch (res) { 04743 case DAHDI_EVENT_EC_DISABLED: 04744 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); 04745 p->echocanon = 0; 04746 break; 04747 case DAHDI_EVENT_BITSCHANGED: 04748 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 04749 case DAHDI_EVENT_PULSE_START: 04750 /* Stop tone if there's a pulse start and the PBX isn't started */ 04751 if (!ast->pbx) 04752 tone_zone_play_tone(p->subs[idx].dfd, -1); 04753 break; 04754 case DAHDI_EVENT_DIALCOMPLETE: 04755 if (p->inalarm) break; 04756 if ((p->radio || (p->oprmode < 0))) break; 04757 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 04758 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 04759 return NULL; 04760 } 04761 if (!x) { /* if not still dialing in driver */ 04762 dahdi_enable_ec(p); 04763 if (p->echobreak) { 04764 dahdi_train_ec(p); 04765 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 04766 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04767 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04768 p->echobreak = 0; 04769 } else { 04770 p->dialing = 0; 04771 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 04772 /* if thru with dialing after offhook */ 04773 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 04774 ast_setstate(ast, AST_STATE_UP); 04775 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04776 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04777 break; 04778 } else { /* if to state wait for offhook to dial rest */ 04779 /* we now wait for off hook */ 04780 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 04781 } 04782 } 04783 if (ast->_state == AST_STATE_DIALING) { 04784 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 04785 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 04786 } 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)))) { 04787 ast_setstate(ast, AST_STATE_RINGING); 04788 } else if (!p->answeronpolarityswitch) { 04789 ast_setstate(ast, AST_STATE_UP); 04790 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04791 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 04792 /* If aops=0 and hops=1, this is necessary */ 04793 p->polarity = POLARITY_REV; 04794 } else { 04795 /* Start clean, so we can catch the change to REV polarity when party answers */ 04796 p->polarity = POLARITY_IDLE; 04797 } 04798 } 04799 } 04800 } 04801 break; 04802 case DAHDI_EVENT_ALARM: 04803 #ifdef HAVE_PRI 04804 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04805 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 04806 /* T309 is not enabled : hangup calls when alarm occurs */ 04807 if (p->call) { 04808 if (p->pri && p->pri->pri) { 04809 if (!pri_grab(p, p->pri)) { 04810 pri_hangup(p->pri->pri, p->call, -1); 04811 pri_destroycall(p->pri->pri, p->call); 04812 p->call = NULL; 04813 pri_rel(p->pri); 04814 } else 04815 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 04816 } else 04817 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 04818 } 04819 if (p->owner) 04820 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 04821 } 04822 } 04823 if (p->bearer) 04824 p->bearer->inalarm = 1; 04825 else 04826 #endif 04827 p->inalarm = 1; 04828 res = get_alarms(p); 04829 handle_alarms(p, res); 04830 #ifdef HAVE_PRI 04831 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 04832 /* fall through intentionally */ 04833 } else { 04834 break; 04835 } 04836 #endif 04837 #ifdef HAVE_SS7 04838 if (p->sig == SIG_SS7) 04839 break; 04840 #endif 04841 case DAHDI_EVENT_ONHOOK: 04842 if (p->radio) { 04843 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04844 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 04845 break; 04846 } 04847 if (p->oprmode < 0) 04848 { 04849 if (p->oprmode != -1) break; 04850 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04851 { 04852 /* Make sure it starts ringing */ 04853 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04854 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 04855 save_conference(p->oprpeer); 04856 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04857 } 04858 break; 04859 } 04860 switch (p->sig) { 04861 case SIG_FXOLS: 04862 case SIG_FXOGS: 04863 case SIG_FXOKS: 04864 p->onhooktime = time(NULL); 04865 p->msgstate = -1; 04866 /* Check for some special conditions regarding call waiting */ 04867 if (idx == SUB_REAL) { 04868 /* The normal line was hung up */ 04869 if (p->subs[SUB_CALLWAIT].owner) { 04870 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 04871 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04872 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 04873 unalloc_sub(p, SUB_CALLWAIT); 04874 #if 0 04875 p->subs[idx].needanswer = 0; 04876 p->subs[idx].needringing = 0; 04877 #endif 04878 p->callwaitingrepeat = 0; 04879 p->cidcwexpire = 0; 04880 p->owner = NULL; 04881 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04882 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04883 p->dialing = 1; 04884 dahdi_ring_phone(p); 04885 } else if (p->subs[SUB_THREEWAY].owner) { 04886 unsigned int mssinceflash; 04887 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04888 the private structure -- not especially easy or clean */ 04889 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 04890 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04891 DLA_UNLOCK(&p->lock); 04892 CHANNEL_DEADLOCK_AVOIDANCE(ast); 04893 /* We can grab ast and p in that order, without worry. We should make sure 04894 nothing seriously bad has happened though like some sort of bizarre double 04895 masquerade! */ 04896 DLA_LOCK(&p->lock); 04897 if (p->owner != ast) { 04898 ast_log(LOG_WARNING, "This isn't good...\n"); 04899 return NULL; 04900 } 04901 } 04902 if (!p->subs[SUB_THREEWAY].owner) { 04903 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04904 return NULL; 04905 } 04906 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04907 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 04908 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04909 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04910 hanging up. Hangup both channels now */ 04911 if (p->subs[SUB_THREEWAY].owner) 04912 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 04913 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04914 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04915 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04916 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04917 if (p->transfer) { 04918 /* In any case this isn't a threeway call anymore */ 04919 p->subs[SUB_REAL].inthreeway = 0; 04920 p->subs[SUB_THREEWAY].inthreeway = 0; 04921 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04922 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04923 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04924 /* Swap subs and dis-own channel */ 04925 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04926 p->owner = NULL; 04927 /* Ring the phone */ 04928 dahdi_ring_phone(p); 04929 } else { 04930 if ((res = attempt_transfer(p)) < 0) { 04931 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04932 if (p->subs[SUB_THREEWAY].owner) 04933 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04934 } else if (res) { 04935 /* Don't actually hang up at this point */ 04936 if (p->subs[SUB_THREEWAY].owner) 04937 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04938 break; 04939 } 04940 } 04941 } else { 04942 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04943 if (p->subs[SUB_THREEWAY].owner) 04944 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04945 } 04946 } else { 04947 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 04948 /* Swap subs and dis-own channel */ 04949 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04950 p->owner = NULL; 04951 /* Ring the phone */ 04952 dahdi_ring_phone(p); 04953 } 04954 } 04955 } else { 04956 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 04957 } 04958 /* Fall through */ 04959 default: 04960 dahdi_disable_ec(p); 04961 return NULL; 04962 } 04963 break; 04964 case DAHDI_EVENT_RINGOFFHOOK: 04965 if (p->inalarm) break; 04966 if (p->oprmode < 0) 04967 { 04968 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04969 { 04970 /* Make sure it stops ringing */ 04971 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04972 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04973 restore_conference(p->oprpeer); 04974 } 04975 break; 04976 } 04977 if (p->radio) 04978 { 04979 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 04980 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 04981 break; 04982 } 04983 /* for E911, its supposed to wait for offhook then dial 04984 the second half of the dial string */ 04985 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04986 c = strchr(p->dialdest, '/'); 04987 if (c) 04988 c++; 04989 else 04990 c = p->dialdest; 04991 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 04992 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 04993 if (strlen(p->dop.dialstr) > 4) { 04994 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 04995 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 04996 p->echorest[sizeof(p->echorest) - 1] = '\0'; 04997 p->echobreak = 1; 04998 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 04999 } else 05000 p->echobreak = 0; 05001 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 05002 int saveerr = errno; 05003 05004 x = DAHDI_ONHOOK; 05005 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05006 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 05007 return NULL; 05008 } 05009 p->dialing = 1; 05010 return &p->subs[idx].f; 05011 } 05012 switch (p->sig) { 05013 case SIG_FXOLS: 05014 case SIG_FXOGS: 05015 case SIG_FXOKS: 05016 switch (ast->_state) { 05017 case AST_STATE_RINGING: 05018 dahdi_enable_ec(p); 05019 dahdi_train_ec(p); 05020 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05021 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05022 /* Make sure it stops ringing */ 05023 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05024 ast_debug(1, "channel %d answered\n", p->channel); 05025 if (p->cidspill) { 05026 /* Cancel any running CallerID spill */ 05027 ast_free(p->cidspill); 05028 p->cidspill = NULL; 05029 } 05030 p->dialing = 0; 05031 p->callwaitcas = 0; 05032 if (p->confirmanswer) { 05033 /* Ignore answer if "confirm answer" is enabled */ 05034 p->subs[idx].f.frametype = AST_FRAME_NULL; 05035 p->subs[idx].f.subclass = 0; 05036 } else if (!ast_strlen_zero(p->dop.dialstr)) { 05037 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 05038 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05039 if (res < 0) { 05040 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05041 p->dop.dialstr[0] = '\0'; 05042 return NULL; 05043 } else { 05044 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 05045 p->subs[idx].f.frametype = AST_FRAME_NULL; 05046 p->subs[idx].f.subclass = 0; 05047 p->dialing = 1; 05048 } 05049 p->dop.dialstr[0] = '\0'; 05050 ast_setstate(ast, AST_STATE_DIALING); 05051 } else 05052 ast_setstate(ast, AST_STATE_UP); 05053 return &p->subs[idx].f; 05054 case AST_STATE_DOWN: 05055 ast_setstate(ast, AST_STATE_RING); 05056 ast->rings = 1; 05057 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05058 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK; 05059 ast_debug(1, "channel %d picked up\n", p->channel); 05060 return &p->subs[idx].f; 05061 case AST_STATE_UP: 05062 /* Make sure it stops ringing */ 05063 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 05064 /* Okay -- probably call waiting*/ 05065 if (ast_bridged_channel(p->owner)) 05066 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 05067 p->subs[idx].needunhold = 1; 05068 break; 05069 case AST_STATE_RESERVED: 05070 /* Start up dialtone */ 05071 if (has_voicemail(p)) 05072 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 05073 else 05074 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 05075 break; 05076 default: 05077 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 05078 } 05079 break; 05080 case SIG_FXSLS: 05081 case SIG_FXSGS: 05082 case SIG_FXSKS: 05083 if (ast->_state == AST_STATE_RING) { 05084 p->ringt = p->ringt_base; 05085 } 05086 05087 /* If we get a ring then we cannot be in 05088 * reversed polarity. So we reset to idle */ 05089 ast_debug(1, "Setting IDLE polarity due " 05090 "to ring. Old polarity was %d\n", 05091 p->polarity); 05092 p->polarity = POLARITY_IDLE; 05093 05094 /* Fall through */ 05095 case SIG_EM: 05096 case SIG_EM_E1: 05097 case SIG_EMWINK: 05098 case SIG_FEATD: 05099 case SIG_FEATDMF: 05100 case SIG_FEATDMF_TA: 05101 case SIG_E911: 05102 case SIG_FGC_CAMA: 05103 case SIG_FGC_CAMAMF: 05104 case SIG_FEATB: 05105 case SIG_SF: 05106 case SIG_SFWINK: 05107 case SIG_SF_FEATD: 05108 case SIG_SF_FEATDMF: 05109 case SIG_SF_FEATB: 05110 if (ast->_state == AST_STATE_PRERING) 05111 ast_setstate(ast, AST_STATE_RING); 05112 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 05113 ast_debug(1, "Ring detected\n"); 05114 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05115 p->subs[idx].f.subclass = AST_CONTROL_RING; 05116 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 05117 ast_debug(1, "Line answered\n"); 05118 if (p->confirmanswer) { 05119 p->subs[idx].f.frametype = AST_FRAME_NULL; 05120 p->subs[idx].f.subclass = 0; 05121 } else { 05122 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05123 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05124 ast_setstate(ast, AST_STATE_UP); 05125 } 05126 } else if (ast->_state != AST_STATE_RING) 05127 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 05128 break; 05129 default: 05130 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05131 } 05132 break; 05133 case DAHDI_EVENT_RINGBEGIN: 05134 switch (p->sig) { 05135 case SIG_FXSLS: 05136 case SIG_FXSGS: 05137 case SIG_FXSKS: 05138 if (ast->_state == AST_STATE_RING) { 05139 p->ringt = p->ringt_base; 05140 } 05141 break; 05142 } 05143 break; 05144 case DAHDI_EVENT_RINGEROFF: 05145 if (p->inalarm) break; 05146 if ((p->radio || (p->oprmode < 0))) break; 05147 ast->rings++; 05148 if ((ast->rings > p->cidrings) && (p->cidspill)) { 05149 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 05150 ast_free(p->cidspill); 05151 p->cidspill = NULL; 05152 p->callwaitcas = 0; 05153 } 05154 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05155 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05156 break; 05157 case DAHDI_EVENT_RINGERON: 05158 break; 05159 case DAHDI_EVENT_NOALARM: 05160 p->inalarm = 0; 05161 #ifdef HAVE_PRI 05162 /* Extremely unlikely but just in case */ 05163 if (p->bearer) 05164 p->bearer->inalarm = 0; 05165 #endif 05166 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 05167 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 05168 "Channel: %d\r\n", p->channel); 05169 break; 05170 case DAHDI_EVENT_WINKFLASH: 05171 if (p->inalarm) break; 05172 if (p->radio) break; 05173 if (p->oprmode < 0) break; 05174 if (p->oprmode > 1) 05175 { 05176 struct dahdi_params par; 05177 05178 memset(&par, 0, sizeof(par)); 05179 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 05180 { 05181 if (!par.rxisoffhook) 05182 { 05183 /* Make sure it stops ringing */ 05184 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05185 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 05186 save_conference(p); 05187 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05188 } 05189 } 05190 break; 05191 } 05192 /* Remember last time we got a flash-hook */ 05193 p->flashtime = ast_tvnow(); 05194 switch (mysig) { 05195 case SIG_FXOLS: 05196 case SIG_FXOGS: 05197 case SIG_FXOKS: 05198 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 05199 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 05200 p->callwaitcas = 0; 05201 05202 if (idx != SUB_REAL) { 05203 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 05204 goto winkflashdone; 05205 } 05206 05207 if (p->subs[SUB_CALLWAIT].owner) { 05208 /* Swap to call-wait */ 05209 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 05210 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 05211 p->owner = p->subs[SUB_REAL].owner; 05212 ast_debug(1, "Making %s the new owner\n", p->owner->name); 05213 if (p->owner->_state == AST_STATE_RINGING) { 05214 ast_setstate(p->owner, AST_STATE_UP); 05215 p->subs[SUB_REAL].needanswer = 1; 05216 } 05217 p->callwaitingrepeat = 0; 05218 p->cidcwexpire = 0; 05219 /* Start music on hold if appropriate */ 05220 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 05221 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 05222 S_OR(p->mohsuggest, NULL), 05223 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05224 } 05225 p->subs[SUB_CALLWAIT].needhold = 1; 05226 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05227 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 05228 S_OR(p->mohsuggest, NULL), 05229 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05230 } 05231 p->subs[SUB_REAL].needunhold = 1; 05232 } else if (!p->subs[SUB_THREEWAY].owner) { 05233 if (!p->threewaycalling) { 05234 /* Just send a flash if no 3-way calling */ 05235 p->subs[SUB_REAL].needflash = 1; 05236 goto winkflashdone; 05237 } else if (!check_for_conference(p)) { 05238 char cid_num[256]; 05239 char cid_name[256]; 05240 05241 cid_num[0] = 0; 05242 cid_name[0] = 0; 05243 if (p->dahditrcallerid && p->owner) { 05244 if (p->owner->cid.cid_num) 05245 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 05246 if (p->owner->cid.cid_name) 05247 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 05248 } 05249 /* XXX This section needs much more error checking!!! XXX */ 05250 /* Start a 3-way call if feasible */ 05251 if (!((ast->pbx) || 05252 (ast->_state == AST_STATE_UP) || 05253 (ast->_state == AST_STATE_RING))) { 05254 ast_debug(1, "Flash when call not up or ringing\n"); 05255 goto winkflashdone; 05256 } 05257 if (alloc_sub(p, SUB_THREEWAY)) { 05258 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 05259 goto winkflashdone; 05260 } 05261 /* Make new channel */ 05262 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 05263 if (p->dahditrcallerid) { 05264 if (!p->origcid_num) 05265 p->origcid_num = ast_strdup(p->cid_num); 05266 if (!p->origcid_name) 05267 p->origcid_name = ast_strdup(p->cid_name); 05268 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 05269 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 05270 } 05271 /* Swap things around between the three-way and real call */ 05272 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05273 /* Disable echo canceller for better dialing */ 05274 dahdi_disable_ec(p); 05275 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 05276 if (res) 05277 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 05278 p->owner = chan; 05279 if (!chan) { 05280 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 05281 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 05282 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 05283 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 05284 dahdi_enable_ec(p); 05285 ast_hangup(chan); 05286 } else { 05287 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05288 int way3bridge = 0, cdr3way = 0; 05289 05290 if (!other) { 05291 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05292 } else 05293 way3bridge = 1; 05294 05295 if (p->subs[SUB_THREEWAY].owner->cdr) 05296 cdr3way = 1; 05297 05298 ast_verb(3, "Started three way call on channel %d\n", p->channel); 05299 05300 /* Start music on hold if appropriate */ 05301 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05302 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 05303 S_OR(p->mohsuggest, NULL), 05304 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 05305 } 05306 p->subs[SUB_THREEWAY].needhold = 1; 05307 } 05308 } 05309 } else { 05310 /* Already have a 3 way call */ 05311 if (p->subs[SUB_THREEWAY].inthreeway) { 05312 /* Call is already up, drop the last person */ 05313 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 05314 /* If the primary call isn't answered yet, use it */ 05315 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 05316 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 05317 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05318 p->owner = p->subs[SUB_REAL].owner; 05319 } 05320 /* Drop the last call and stop the conference */ 05321 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 05322 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05323 p->subs[SUB_REAL].inthreeway = 0; 05324 p->subs[SUB_THREEWAY].inthreeway = 0; 05325 } else { 05326 /* Lets see what we're up to */ 05327 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 05328 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 05329 int otherindex = SUB_THREEWAY; 05330 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 05331 int way3bridge = 0, cdr3way = 0; 05332 05333 if (!other) { 05334 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 05335 } else 05336 way3bridge = 1; 05337 05338 if (p->subs[SUB_THREEWAY].owner->cdr) 05339 cdr3way = 1; 05340 05341 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 05342 /* Put them in the threeway, and flip */ 05343 p->subs[SUB_THREEWAY].inthreeway = 1; 05344 p->subs[SUB_REAL].inthreeway = 1; 05345 if (ast->_state == AST_STATE_UP) { 05346 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05347 otherindex = SUB_REAL; 05348 } 05349 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 05350 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 05351 p->subs[otherindex].needunhold = 1; 05352 p->owner = p->subs[SUB_REAL].owner; 05353 if (ast->_state == AST_STATE_RINGING) { 05354 ast_debug(1, "Enabling ringtone on real and threeway\n"); 05355 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05356 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05357 } 05358 } else { 05359 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 05360 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05361 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05362 p->owner = p->subs[SUB_REAL].owner; 05363 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 05364 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05365 p->subs[SUB_REAL].needunhold = 1; 05366 dahdi_enable_ec(p); 05367 } 05368 05369 } 05370 } 05371 winkflashdone: 05372 update_conf(p); 05373 break; 05374 case SIG_EM: 05375 case SIG_EM_E1: 05376 case SIG_FEATD: 05377 case SIG_SF: 05378 case SIG_SFWINK: 05379 case SIG_SF_FEATD: 05380 case SIG_FXSLS: 05381 case SIG_FXSGS: 05382 if (option_debug) { 05383 if (p->dialing) 05384 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 05385 else 05386 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 05387 } 05388 break; 05389 case SIG_FEATDMF_TA: 05390 switch (p->whichwink) { 05391 case 0: 05392 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05393 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 05394 break; 05395 case 1: 05396 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 05397 break; 05398 case 2: 05399 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 05400 return NULL; 05401 } 05402 p->whichwink++; 05403 /* Fall through */ 05404 case SIG_FEATDMF: 05405 case SIG_E911: 05406 case SIG_FGC_CAMAMF: 05407 case SIG_FGC_CAMA: 05408 case SIG_FEATB: 05409 case SIG_SF_FEATDMF: 05410 case SIG_SF_FEATB: 05411 case SIG_EMWINK: 05412 /* FGD MF and EMWINK *Must* wait for wink */ 05413 if (!ast_strlen_zero(p->dop.dialstr)) { 05414 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05415 if (res < 0) { 05416 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05417 p->dop.dialstr[0] = '\0'; 05418 return NULL; 05419 } else 05420 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05421 } 05422 p->dop.dialstr[0] = '\0'; 05423 break; 05424 default: 05425 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 05426 } 05427 break; 05428 case DAHDI_EVENT_HOOKCOMPLETE: 05429 if (p->inalarm) break; 05430 if ((p->radio || (p->oprmode < 0))) break; 05431 switch (mysig) { 05432 case SIG_FXSLS: /* only interesting for FXS */ 05433 case SIG_FXSGS: 05434 case SIG_FXSKS: 05435 case SIG_EM: 05436 case SIG_EM_E1: 05437 case SIG_EMWINK: 05438 case SIG_FEATD: 05439 case SIG_SF: 05440 case SIG_SFWINK: 05441 case SIG_SF_FEATD: 05442 if (!ast_strlen_zero(p->dop.dialstr)) { 05443 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05444 if (res < 0) { 05445 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 05446 p->dop.dialstr[0] = '\0'; 05447 return NULL; 05448 } else 05449 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 05450 } 05451 p->dop.dialstr[0] = '\0'; 05452 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05453 break; 05454 case SIG_FEATDMF: 05455 case SIG_FEATDMF_TA: 05456 case SIG_E911: 05457 case SIG_FGC_CAMA: 05458 case SIG_FGC_CAMAMF: 05459 case SIG_FEATB: 05460 case SIG_SF_FEATDMF: 05461 case SIG_SF_FEATB: 05462 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 05463 break; 05464 default: 05465 break; 05466 } 05467 break; 05468 case DAHDI_EVENT_POLARITY: 05469 /* 05470 * If we get a Polarity Switch event, this could be 05471 * due to line seizure, remote end connect or remote end disconnect. 05472 * 05473 * Check to see if we should change the polarity state and 05474 * mark the channel as UP or if this is an indication 05475 * of remote end disconnect. 05476 */ 05477 05478 if (p->polarityonanswerdelay > 0) { 05479 /* check if event is not too soon after OffHook or Answer */ 05480 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 05481 switch (ast->_state) { 05482 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05483 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05484 if (p->answeronpolarityswitch) { 05485 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel); 05486 ast_setstate(p->owner, AST_STATE_UP); 05487 p->polarity = POLARITY_REV; 05488 if (p->hanguponpolarityswitch) { 05489 p->polaritydelaytv = ast_tvnow(); 05490 } 05491 } else { 05492 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel); 05493 } 05494 break; 05495 case AST_STATE_UP: /*!< Line is up */ 05496 case AST_STATE_RING: /*!< Line is ringing */ 05497 if (p->hanguponpolarityswitch) { 05498 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel); 05499 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 05500 p->polarity = POLARITY_IDLE; 05501 } else { 05502 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel); 05503 } 05504 break; 05505 05506 case AST_STATE_DOWN: /*!< Channel is down and available */ 05507 case AST_STATE_RESERVED: /*!< Channel is down, but reserved */ 05508 case AST_STATE_OFFHOOK: /*!< Channel is off hook */ 05509 case AST_STATE_BUSY: /*!< Line is busy */ 05510 case AST_STATE_DIALING_OFFHOOK: /*!< Digits (or equivalent) have been dialed while offhook */ 05511 case AST_STATE_PRERING: /*!< Channel has detected an incoming call and is waiting for ring */ 05512 default: 05513 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05514 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state); 05515 } 05516 05517 } 05518 05519 } else { 05520 /* event is too soon after OffHook or Answer */ 05521 switch (ast->_state) { 05522 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 05523 case AST_STATE_RINGING: /*!< Remote end is ringing */ 05524 if (p->answeronpolarityswitch) { 05525 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state); 05526 } 05527 break; 05528 05529 case AST_STATE_UP: /*!< Line is up */ 05530 case AST_STATE_RING: /*!< Line is ringing */ 05531 if (p->hanguponpolarityswitch) { 05532 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); 05533 } 05534 break; 05535 05536 default: 05537 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 05538 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state); 05539 } 05540 } 05541 } 05542 } 05543 /* Added more log_debug information below to provide a better indication of what is going on */ 05544 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) ); 05545 break; 05546 default: 05547 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 05548 } 05549 return &p->subs[idx].f; 05550 }
| static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3379 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().
03380 { 03381 int res; 03382 int idx,x, law; 03383 /*static int restore_gains(struct dahdi_pvt *p);*/ 03384 struct dahdi_pvt *p = ast->tech_pvt; 03385 struct dahdi_pvt *tmp = NULL; 03386 struct dahdi_pvt *prev = NULL; 03387 struct dahdi_params par; 03388 03389 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 03390 if (!ast->tech_pvt) { 03391 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 03392 return 0; 03393 } 03394 03395 ast_mutex_lock(&p->lock); 03396 03397 idx = dahdi_get_index(ast, p, 1); 03398 03399 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03400 x = 1; 03401 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03402 p->cid_num[0] = '\0'; 03403 p->cid_name[0] = '\0'; 03404 } 03405 03406 x = 0; 03407 dahdi_confmute(p, 0); 03408 p->muting = 0; 03409 restore_gains(p); 03410 if (p->origcid_num) { 03411 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 03412 ast_free(p->origcid_num); 03413 p->origcid_num = NULL; 03414 } 03415 if (p->origcid_name) { 03416 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 03417 ast_free(p->origcid_name); 03418 p->origcid_name = NULL; 03419 } 03420 if (p->dsp) 03421 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03422 p->exten[0] = '\0'; 03423 03424 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 03425 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 03426 p->ignoredtmf = 0; 03427 03428 if (idx > -1) { 03429 /* Real channel, do some fixup */ 03430 p->subs[idx].owner = NULL; 03431 p->subs[idx].needanswer = 0; 03432 p->subs[idx].needflash = 0; 03433 p->subs[idx].needringing = 0; 03434 p->subs[idx].needbusy = 0; 03435 p->subs[idx].needcongestion = 0; 03436 p->subs[idx].linear = 0; 03437 p->subs[idx].needcallerid = 0; 03438 p->polarity = POLARITY_IDLE; 03439 dahdi_setlinear(p->subs[idx].dfd, 0); 03440 if (idx == SUB_REAL) { 03441 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 03442 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 03443 if (p->subs[SUB_CALLWAIT].inthreeway) { 03444 /* We had flipped over to answer a callwait and now it's gone */ 03445 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 03446 /* Move to the call-wait, but un-own us until they flip back. */ 03447 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03448 unalloc_sub(p, SUB_CALLWAIT); 03449 p->owner = NULL; 03450 } else { 03451 /* The three way hung up, but we still have a call wait */ 03452 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 03453 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03454 unalloc_sub(p, SUB_THREEWAY); 03455 if (p->subs[SUB_REAL].inthreeway) { 03456 /* This was part of a three way call. Immediately make way for 03457 another call */ 03458 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03459 p->owner = p->subs[SUB_REAL].owner; 03460 } else { 03461 /* This call hasn't been completed yet... Set owner to NULL */ 03462 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03463 p->owner = NULL; 03464 } 03465 p->subs[SUB_REAL].inthreeway = 0; 03466 } 03467 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 03468 /* Move to the call-wait and switch back to them. */ 03469 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03470 unalloc_sub(p, SUB_CALLWAIT); 03471 p->owner = p->subs[SUB_REAL].owner; 03472 if (p->owner->_state != AST_STATE_UP) 03473 p->subs[SUB_REAL].needanswer = 1; 03474 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 03475 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03476 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 03477 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03478 unalloc_sub(p, SUB_THREEWAY); 03479 if (p->subs[SUB_REAL].inthreeway) { 03480 /* This was part of a three way call. Immediately make way for 03481 another call */ 03482 ast_debug(1, "Call was complete, setting owner to former third call\n"); 03483 p->owner = p->subs[SUB_REAL].owner; 03484 } else { 03485 /* This call hasn't been completed yet... Set owner to NULL */ 03486 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 03487 p->owner = NULL; 03488 } 03489 p->subs[SUB_REAL].inthreeway = 0; 03490 } 03491 } else if (idx == SUB_CALLWAIT) { 03492 /* Ditch the holding callwait call, and immediately make it availabe */ 03493 if (p->subs[SUB_CALLWAIT].inthreeway) { 03494 /* This is actually part of a three way, placed on hold. Place the third part 03495 on music on hold now */ 03496 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03497 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 03498 S_OR(p->mohsuggest, NULL), 03499 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03500 } 03501 p->subs[SUB_THREEWAY].inthreeway = 0; 03502 /* Make it the call wait now */ 03503 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 03504 unalloc_sub(p, SUB_THREEWAY); 03505 } else 03506 unalloc_sub(p, SUB_CALLWAIT); 03507 } else if (idx == SUB_THREEWAY) { 03508 if (p->subs[SUB_CALLWAIT].inthreeway) { 03509 /* The other party of the three way call is currently in a call-wait state. 03510 Start music on hold for them, and take the main guy out of the third call */ 03511 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 03512 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 03513 S_OR(p->mohsuggest, NULL), 03514 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 03515 } 03516 p->subs[SUB_CALLWAIT].inthreeway = 0; 03517 } 03518 p->subs[SUB_REAL].inthreeway = 0; 03519 /* If this was part of a three way call index, let us make 03520 another three way call */ 03521 unalloc_sub(p, SUB_THREEWAY); 03522 } else { 03523 /* This wasn't any sort of call, but how are we an index? */ 03524 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 03525 } 03526 } 03527 03528 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 03529 p->owner = NULL; 03530 p->ringt = 0; 03531 p->distinctivering = 0; 03532 p->confirmanswer = 0; 03533 p->cidrings = 1; 03534 p->outgoing = 0; 03535 p->digital = 0; 03536 p->faxhandled = 0; 03537 p->pulsedial = 0; 03538 p->onhooktime = time(NULL); 03539 #if defined(HAVE_PRI) || defined(HAVE_SS7) 03540 p->proceeding = 0; 03541 p->dialing = 0; 03542 p->progress = 0; 03543 p->alerting = 0; 03544 p->setup_ack = 0; 03545 p->rlt = 0; 03546 #endif 03547 if (p->dsp) { 03548 ast_dsp_free(p->dsp); 03549 p->dsp = NULL; 03550 } 03551 03552 law = DAHDI_LAW_DEFAULT; 03553 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 03554 if (res < 0) 03555 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 03556 /* Perform low level hangup if no owner left */ 03557 #ifdef HAVE_SS7 03558 if (p->ss7) { 03559 if (p->ss7call) { 03560 if (!ss7_grab(p, p->ss7)) { 03561 if (!p->alreadyhungup) { 03562 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 03563 int icause = ast->hangupcause ? ast->hangupcause : -1; 03564 03565 if (cause) { 03566 if (atoi(cause)) 03567 icause = atoi(cause); 03568 } 03569 isup_rel(p->ss7->ss7, p->ss7call, icause); 03570 ss7_rel(p->ss7); 03571 p->alreadyhungup = 1; 03572 } else 03573 ast_log(LOG_WARNING, "Trying to hangup twice!\n"); 03574 } else { 03575 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic); 03576 res = -1; 03577 } 03578 } 03579 } 03580 #endif 03581 #ifdef HAVE_PRI 03582 if (p->pri) { 03583 #ifdef SUPPORT_USERUSER 03584 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 03585 #endif 03586 03587 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 03588 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 03589 if (!pri_grab(p, p->pri)) { 03590 if (p->alreadyhungup) { 03591 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n"); 03592 03593 #ifdef SUPPORT_USERUSER 03594 pri_call_set_useruser(p->call, useruser); 03595 #endif 03596 03597 pri_hangup(p->pri->pri, p->call, -1); 03598 p->call = NULL; 03599 if (p->bearer) 03600 p->bearer->call = NULL; 03601 } else { 03602 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 03603 int icause = ast->hangupcause ? ast->hangupcause : -1; 03604 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 03605 03606 #ifdef SUPPORT_USERUSER 03607 pri_call_set_useruser(p->call, useruser); 03608 #endif 03609 03610 p->alreadyhungup = 1; 03611 if (p->bearer) 03612 p->bearer->alreadyhungup = 1; 03613 if (cause) { 03614 if (atoi(cause)) 03615 icause = atoi(cause); 03616 } 03617 pri_hangup(p->pri->pri, p->call, icause); 03618 } 03619 if (res < 0) 03620 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 03621 pri_rel(p->pri); 03622 } else { 03623 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 03624 res = -1; 03625 } 03626 } else { 03627 if (p->bearer) 03628 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 03629 p->call = NULL; 03630 res = 0; 03631 } 03632 } 03633 #endif 03634 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP))) 03635 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 03636 if (res < 0) { 03637 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 03638 } 03639 switch (p->sig) { 03640 case SIG_FXOGS: 03641 case SIG_FXOLS: 03642 case SIG_FXOKS: 03643 memset(&par, 0, sizeof(par)); 03644 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 03645 if (!res) { 03646 #if 0 03647 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 03648 #endif 03649 /* If they're off hook, try playing congestion */ 03650 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 03651 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 03652 else 03653 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03654 } 03655 break; 03656 case SIG_FXSGS: 03657 case SIG_FXSLS: 03658 case SIG_FXSKS: 03659 /* Make sure we're not made available for at least two seconds assuming 03660 we were actually used for an inbound or outbound call. */ 03661 if (ast->_state != AST_STATE_RESERVED) { 03662 time(&p->guardtime); 03663 p->guardtime += 2; 03664 } 03665 break; 03666 default: 03667 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 03668 } 03669 if (p->cidspill) 03670 ast_free(p->cidspill); 03671 if (p->sig) 03672 dahdi_disable_ec(p); 03673 x = 0; 03674 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 03675 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 03676 p->didtdd = 0; 03677 p->cidspill = NULL; 03678 p->callwaitcas = 0; 03679 p->callwaiting = p->permcallwaiting; 03680 p->hidecallerid = p->permhidecallerid; 03681 p->dialing = 0; 03682 p->rdnis[0] = '\0'; 03683 update_conf(p); 03684 reset_conf(p); 03685 /* Restore data mode */ 03686 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 03687 x = 0; 03688 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 03689 } 03690 #ifdef HAVE_PRI 03691 if (p->bearer) { 03692 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel); 03693 /* Free up the bearer channel as well, and 03694 don't use its file descriptor anymore */ 03695 update_conf(p->bearer); 03696 reset_conf(p->bearer); 03697 p->bearer->owner = NULL; 03698 p->bearer->realcall = NULL; 03699 p->bearer = NULL; 03700 p->subs[SUB_REAL].dfd = -1; 03701 p->pri = NULL; 03702 } 03703 #endif 03704 if (num_restart_pending == 0) 03705 restart_monitor(); 03706 } 03707 03708 p->callwaitingrepeat = 0; 03709 p->cidcwexpire = 0; 03710 p->oprmode = 0; 03711 ast->tech_pvt = NULL; 03712 ast_mutex_unlock(&p->lock); 03713 ast_module_unref(ast_module_info->self); 03714 ast_verb(3, "Hungup '%s'\n", ast->name); 03715 03716 ast_mutex_lock(&iflock); 03717 03718 if (p->restartpending) { 03719 num_restart_pending--; 03720 } 03721 03722 tmp = iflist; 03723 prev = NULL; 03724 if (p->destroy) { 03725 while (tmp) { 03726 if (tmp == p) { 03727 destroy_channel(prev, tmp, 0); 03728 break; 03729 } else { 03730 prev = tmp; 03731 tmp = tmp->next; 03732 } 03733 } 03734 } 03735 ast_mutex_unlock(&iflock); 03736 return 0; 03737 }
| static int dahdi_indicate | ( | struct ast_channel * | chan, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 6075 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().
06076 { 06077 struct dahdi_pvt *p = chan->tech_pvt; 06078 int res=-1; 06079 int idx; 06080 int func = DAHDI_FLASH; 06081 ast_mutex_lock(&p->lock); 06082 idx = dahdi_get_index(chan, p, 0); 06083 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 06084 if (idx == SUB_REAL) { 06085 switch (condition) { 06086 case AST_CONTROL_BUSY: 06087 #ifdef HAVE_PRI 06088 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06089 chan->hangupcause = AST_CAUSE_USER_BUSY; 06090 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06091 res = 0; 06092 } else if (!p->progress && 06093 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06094 && p->pri && !p->outgoing) { 06095 if (p->pri->pri) { 06096 if (!pri_grab(p, p->pri)) { 06097 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06098 pri_rel(p->pri); 06099 } 06100 else 06101 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06102 } 06103 p->progress = 1; 06104 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06105 } else 06106 #endif 06107 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 06108 break; 06109 case AST_CONTROL_RINGING: 06110 #ifdef HAVE_PRI 06111 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06112 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06113 if (p->pri->pri) { 06114 if (!pri_grab(p, p->pri)) { 06115 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06116 pri_rel(p->pri); 06117 } 06118 else 06119 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06120 } 06121 p->alerting = 1; 06122 } 06123 06124 #endif 06125 #ifdef HAVE_SS7 06126 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { 06127 if (p->ss7->ss7) { 06128 ss7_grab(p, p->ss7); 06129 06130 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06131 p->rlt = 1; 06132 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ 06133 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 06134 p->alerting = 1; 06135 ss7_rel(p->ss7); 06136 } 06137 } 06138 #endif 06139 06140 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 06141 06142 if (chan->_state != AST_STATE_UP) { 06143 if ((chan->_state != AST_STATE_RING) || 06144 ((p->sig != SIG_FXSKS) && 06145 (p->sig != SIG_FXSLS) && 06146 (p->sig != SIG_FXSGS))) 06147 ast_setstate(chan, AST_STATE_RINGING); 06148 } 06149 break; 06150 case AST_CONTROL_PROCEEDING: 06151 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 06152 #ifdef HAVE_PRI 06153 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06154 && p->pri && !p->outgoing) { 06155 if (p->pri->pri) { 06156 if (!pri_grab(p, p->pri)) { 06157 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06158 pri_rel(p->pri); 06159 } 06160 else 06161 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06162 } 06163 p->proceeding = 1; 06164 p->dialing = 0; 06165 } 06166 #endif 06167 #ifdef HAVE_SS7 06168 /* This IF sends the FAR for an answered ALEG call */ 06169 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){ 06170 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 06171 p->rlt = 1; 06172 } 06173 06174 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) { 06175 if (p->ss7->ss7) { 06176 ss7_grab(p, p->ss7); 06177 isup_acm(p->ss7->ss7, p->ss7call); 06178 p->proceeding = 1; 06179 ss7_rel(p->ss7); 06180 06181 } 06182 } 06183 #endif 06184 /* don't continue in ast_indicate */ 06185 res = 0; 06186 break; 06187 case AST_CONTROL_PROGRESS: 06188 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 06189 #ifdef HAVE_PRI 06190 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 06191 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06192 && p->pri && !p->outgoing) { 06193 if (p->pri->pri) { 06194 if (!pri_grab(p, p->pri)) { 06195 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06196 pri_rel(p->pri); 06197 } 06198 else 06199 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06200 } 06201 p->progress = 1; 06202 } 06203 #endif 06204 #ifdef HAVE_SS7 06205 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) { 06206 if (p->ss7->ss7) { 06207 ss7_grab(p, p->ss7); 06208 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 06209 p->progress = 1; 06210 ss7_rel(p->ss7); 06211 /* enable echo canceler here on SS7 calls */ 06212 dahdi_enable_ec(p); 06213 06214 } 06215 } 06216 #endif 06217 /* don't continue in ast_indicate */ 06218 res = 0; 06219 break; 06220 case AST_CONTROL_CONGESTION: 06221 chan->hangupcause = AST_CAUSE_CONGESTION; 06222 #ifdef HAVE_PRI 06223 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 06224 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 06225 chan->_softhangup |= AST_SOFTHANGUP_DEV; 06226 res = 0; 06227 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 06228 && p->pri && !p->outgoing) { 06229 if (p->pri) { 06230 if (!pri_grab(p, p->pri)) { 06231 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 06232 pri_rel(p->pri); 06233 } else 06234 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06235 } 06236 p->progress = 1; 06237 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06238 } else 06239 #endif 06240 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06241 break; 06242 case AST_CONTROL_HOLD: 06243 #ifdef HAVE_PRI 06244 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06245 if (!pri_grab(p, p->pri)) { 06246 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 06247 pri_rel(p->pri); 06248 } else 06249 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06250 } else 06251 #endif 06252 ast_moh_start(chan, data, p->mohinterpret); 06253 break; 06254 case AST_CONTROL_UNHOLD: 06255 #ifdef HAVE_PRI 06256 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 06257 if (!pri_grab(p, p->pri)) { 06258 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 06259 pri_rel(p->pri); 06260 } else 06261 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06262 } else 06263 #endif 06264 ast_moh_stop(chan); 06265 break; 06266 case AST_CONTROL_RADIO_KEY: 06267 if (p->radio) 06268 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 06269 res = 0; 06270 break; 06271 case AST_CONTROL_RADIO_UNKEY: 06272 if (p->radio) 06273 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 06274 res = 0; 06275 break; 06276 case AST_CONTROL_FLASH: 06277 /* flash hookswitch */ 06278 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 06279 /* Clear out the dial buffer */ 06280 p->dop.dialstr[0] = '\0'; 06281 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06282 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06283 chan->name, strerror(errno)); 06284 } else 06285 res = 0; 06286 } else 06287 res = 0; 06288 break; 06289 case AST_CONTROL_SRCUPDATE: 06290 res = 0; 06291 break; 06292 case -1: 06293 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06294 break; 06295 } 06296 } else 06297 res = 0; 06298 ast_mutex_unlock(&p->lock); 06299 return res; 06300 }
Definition at line 4095 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().
04095 { 04096 int x; 04097 if (!slave || !master) { 04098 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 04099 return; 04100 } 04101 for (x = 0; x < MAX_SLAVES; x++) { 04102 if (!master->slaves[x]) { 04103 master->slaves[x] = slave; 04104 break; 04105 } 04106 } 04107 if (x >= MAX_SLAVES) { 04108 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 04109 master->slaves[MAX_SLAVES - 1] = slave; 04110 } 04111 if (slave->master) 04112 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 04113 slave->master = master; 04114 04115 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 04116 }
| static void dahdi_loopback | ( | struct dahdi_pvt * | p, | |
| int | enable | |||
| ) | [static] |
Definition at line 9816 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().
09817 { 09818 if (p->loopedback != enable) { 09819 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) { 09820 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno)); 09821 return; 09822 } 09823 p->loopedback = enable; 09824 } 09825 }
| 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 6302 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().
06303 { 06304 struct ast_channel *tmp; 06305 int deflaw; 06306 int res; 06307 int x,y; 06308 int features; 06309 struct ast_str *chan_name; 06310 struct ast_variable *v; 06311 struct dahdi_params ps; 06312 if (i->subs[idx].owner) { 06313 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 06314 return NULL; 06315 } 06316 y = 1; 06317 chan_name = ast_str_alloca(32); 06318 do { 06319 #ifdef HAVE_PRI 06320 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 06321 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y); 06322 else 06323 #endif 06324 if (i->channel == CHAN_PSEUDO) 06325 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 06326 else 06327 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 06328 for (x = 0; x < 3; x++) { 06329 if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6)) 06330 break; 06331 } 06332 y++; 06333 } while (x < 3); 06334 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); 06335 if (!tmp) 06336 return NULL; 06337 tmp->tech = &dahdi_tech; 06338 memset(&ps, 0, sizeof(ps)); 06339 ps.channo = i->channel; 06340 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 06341 if (res) { 06342 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 06343 ps.curlaw = DAHDI_LAW_MULAW; 06344 } 06345 if (ps.curlaw == DAHDI_LAW_ALAW) 06346 deflaw = AST_FORMAT_ALAW; 06347 else 06348 deflaw = AST_FORMAT_ULAW; 06349 if (law) { 06350 if (law == DAHDI_LAW_ALAW) 06351 deflaw = AST_FORMAT_ALAW; 06352 else 06353 deflaw = AST_FORMAT_ULAW; 06354 } 06355 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 06356 tmp->nativeformats = deflaw; 06357 /* Start out assuming ulaw since it's smaller :) */ 06358 tmp->rawreadformat = deflaw; 06359 tmp->readformat = deflaw; 06360 tmp->rawwriteformat = deflaw; 06361 tmp->writeformat = deflaw; 06362 i->subs[idx].linear = 0; 06363 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 06364 features = 0; 06365 if (idx == SUB_REAL) { 06366 if (i->busydetect && CANBUSYDETECT(i)) 06367 features |= DSP_FEATURE_BUSY_DETECT; 06368 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 06369 features |= DSP_FEATURE_CALL_PROGRESS; 06370 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 06371 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 06372 features |= DSP_FEATURE_FAX_DETECT; 06373 } 06374 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 06375 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 06376 i->hardwaredtmf = 0; 06377 features |= DSP_FEATURE_DIGIT_DETECT; 06378 } else if (NEED_MFDETECT(i)) { 06379 i->hardwaredtmf = 1; 06380 features |= DSP_FEATURE_DIGIT_DETECT; 06381 } 06382 } 06383 if (features) { 06384 if (i->dsp) { 06385 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 06386 } else { 06387 if (i->channel != CHAN_PSEUDO) 06388 i->dsp = ast_dsp_new(); 06389 else 06390 i->dsp = NULL; 06391 if (i->dsp) { 06392 i->dsp_features = features; 06393 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06394 /* We cannot do progress detection until receives PROGRESS message */ 06395 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) { 06396 /* Remember requested DSP features, don't treat 06397 talking as ANSWER */ 06398 i->dsp_features = features & ~DSP_PROGRESS_TALK; 06399 features = 0; 06400 } 06401 #endif 06402 ast_dsp_set_features(i->dsp, features); 06403 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 06404 if (!ast_strlen_zero(progzone)) 06405 ast_dsp_set_call_progress_zone(i->dsp, progzone); 06406 if (i->busydetect && CANBUSYDETECT(i)) { 06407 ast_dsp_set_busy_count(i->dsp, i->busycount); 06408 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength); 06409 } 06410 } 06411 } 06412 } 06413 06414 if (state == AST_STATE_RING) 06415 tmp->rings = 1; 06416 tmp->tech_pvt = i; 06417 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 06418 /* Only FXO signalled stuff can be picked up */ 06419 tmp->callgroup = i->callgroup; 06420 tmp->pickupgroup = i->pickupgroup; 06421 } 06422 if (!ast_strlen_zero(i->parkinglot)) 06423 ast_string_field_set(tmp, parkinglot, i->parkinglot); 06424 if (!ast_strlen_zero(i->language)) 06425 ast_string_field_set(tmp, language, i->language); 06426 if (!i->owner) 06427 i->owner = tmp; 06428 if (!ast_strlen_zero(i->accountcode)) 06429 ast_string_field_set(tmp, accountcode, i->accountcode); 06430 if (i->amaflags) 06431 tmp->amaflags = i->amaflags; 06432 i->subs[idx].owner = tmp; 06433 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 06434 ast_string_field_set(tmp, call_forward, i->call_forward); 06435 /* If we've been told "no ADSI" then enforce it */ 06436 if (!i->adsi) 06437 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 06438 if (!ast_strlen_zero(i->exten)) 06439 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 06440 if (!ast_strlen_zero(i->rdnis)) 06441 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 06442 if (!ast_strlen_zero(i->dnid)) 06443 tmp->cid.cid_dnid = ast_strdup(i->dnid); 06444 06445 /* Don't use ast_set_callerid() here because it will 06446 * generate a needless NewCallerID event */ 06447 #ifdef PRI_ANI 06448 if (!ast_strlen_zero(i->cid_ani)) 06449 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 06450 else 06451 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06452 #else 06453 tmp->cid.cid_ani = ast_strdup(i->cid_num); 06454 #endif 06455 tmp->cid.cid_pres = i->callingpres; 06456 tmp->cid.cid_ton = i->cid_ton; 06457 tmp->cid.cid_ani2 = i->cid_ani2; 06458 #if defined(HAVE_PRI) || defined(HAVE_SS7) 06459 tmp->transfercapability = transfercapability; 06460 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 06461 if (transfercapability & AST_TRANS_CAP_DIGITAL) 06462 i->digital = 1; 06463 /* Assume calls are not idle calls unless we're told differently */ 06464 i->isidlecall = 0; 06465 i->alreadyhungup = 0; 06466 #endif 06467 /* clear the fake event in case we posted one before we had ast_channel */ 06468 i->fake_event = 0; 06469 /* Assure there is no confmute on this channel */ 06470 dahdi_confmute(i, 0); 06471 i->muting = 0; 06472 /* Configure the new channel jb */ 06473 ast_jb_configure(tmp, &global_jbconf); 06474 06475 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name); 06476 06477 for (v = i->vars ; v ; v = v->next) 06478 pbx_builtin_setvar_helper(tmp, v->name, v->value); 06479 06480 if (startpbx) { 06481 if (ast_pbx_start(tmp)) { 06482 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 06483 ast_hangup(tmp); 06484 i->owner = NULL; 06485 return NULL; 06486 } 06487 } 06488 06489 ast_module_ref(ast_module_info->self); 06490 return tmp; 06491 }
| static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 1436 of file chan_dahdi.c.
References ast_log(), chan, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
01437 { 01438 int fd; 01439 int isnum; 01440 int chan = 0; 01441 int bs; 01442 int x; 01443 isnum = 1; 01444 for (x = 0; x < strlen(fn); x++) { 01445 if (!isdigit(fn[x])) { 01446 isnum = 0; 01447 break; 01448 } 01449 } 01450 if (isnum) { 01451 chan = atoi(fn); 01452 if (chan < 1) { 01453 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 01454 return -1; 01455 } 01456 fn = "/dev/dahdi/channel"; 01457 } 01458 fd = open(fn, O_RDWR | O_NONBLOCK); 01459 if (fd < 0) { 01460 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 01461 return -1; 01462 } 01463 if (chan) { 01464 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 01465 x = errno; 01466 close(fd); 01467 errno = x; 01468 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 01469 return -1; 01470 } 01471 } 01472 bs = READ_SIZE; 01473 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 01474 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 01475 x = errno; 01476 close(fd); 01477 errno = x; 01478 return -1; 01479 } 01480 return fd; 01481 }
| static void dahdi_pri_error | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 10755 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().
10756 { 10757 int x, y; 10758 int dchan = -1, span = -1; 10759 int dchancount = 0; 10760 10761 if (pri) { 10762 for (x = 0; x < NUM_SPANS; x++) { 10763 for (y = 0; y < NUM_DCHANS; y++) { 10764 if (pris[x].dchans[y]) 10765 dchancount++; 10766 10767 if (pris[x].dchans[y] == pri) 10768 dchan = y; 10769 } 10770 if (dchan >= 0) { 10771 span = x; 10772 break; 10773 } 10774 dchancount = 0; 10775 } 10776 if ((dchancount > 1) && (span > -1)) 10777 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 10778 else 10779 ast_log(LOG_ERROR, "%s", s); 10780 } else 10781 ast_log(LOG_ERROR, "%s", s); 10782 10783 ast_mutex_lock(&pridebugfdlock); 10784 10785 if (pridebugfd >= 0) { 10786 if (write(pridebugfd, s, strlen(s)) < 0) { 10787 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10788 } 10789 } 10790 10791 ast_mutex_unlock(&pridebugfdlock); 10792 }
| static void dahdi_pri_message | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 10716 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().
10717 { 10718 int x, y; 10719 int dchan = -1, span = -1; 10720 int dchancount = 0; 10721 10722 if (pri) { 10723 for (x = 0; x < NUM_SPANS; x++) { 10724 for (y = 0; y < NUM_DCHANS; y++) { 10725 if (pris[x].dchans[y]) 10726 dchancount++; 10727 10728 if (pris[x].dchans[y] == pri) 10729 dchan = y; 10730 } 10731 if (dchan >= 0) { 10732 span = x; 10733 break; 10734 } 10735 dchancount = 0; 10736 } 10737 if (dchancount > 1 && (span > -1)) 10738 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 10739 else 10740 ast_verbose("%s", s); 10741 } else 10742 ast_verbose("%s", s); 10743 10744 ast_mutex_lock(&pridebugfdlock); 10745 10746 if (pridebugfd >= 0) { 10747 if (write(pridebugfd, s, strlen(s)) < 0) { 10748 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 10749 } 10750 } 10751 10752 ast_mutex_unlock(&pridebugfdlock); 10753 }
Definition at line 1342 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_ss7::lock, dahdi_pri::lock, dahdi_pvt::owner, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, and dahdi_ss7::ss7.
Referenced by action_dahdidialoffhook(), pri_dchannel(), and ss7_linkset().
01343 { 01344 #ifdef HAVE_PRI 01345 struct dahdi_pri *pri = (struct dahdi_pri*) data; 01346 #endif 01347 #ifdef HAVE_SS7 01348 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data; 01349 #endif 01350 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01351 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01352 if (data) { 01353 switch (p->sig) { 01354 #ifdef HAVE_PRI 01355 case SIG_BRI: 01356 case SIG_BRI_PTMP: 01357 case SIG_PRI: 01358 ast_mutex_unlock(&pri->lock); 01359 break; 01360 #endif 01361 #ifdef HAVE_SS7 01362 case SIG_SS7: 01363 ast_mutex_unlock(&ss7->lock); 01364 break; 01365 #endif 01366 default: 01367 break; 01368 } 01369 } 01370 #endif 01371 for (;;) { 01372 if (p->owner) { 01373 if (ast_channel_trylock(p->owner)) { 01374 DEADLOCK_AVOIDANCE(&p->lock); 01375 } else { 01376 ast_queue_frame(p->owner, f); 01377 ast_channel_unlock(p->owner); 01378 break; 01379 } 01380 } else 01381 break; 01382 } 01383 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01384 if (data) { 01385 switch (p->sig) { 01386 #ifdef HAVE_PRI 01387 case SIG_BRI: 01388 case SIG_BRI_PTMP: 01389 case SIG_PRI: 01390 ast_mutex_lock(&pri->lock); 01391 break; 01392 #endif 01393 #ifdef HAVE_SS7 01394 case SIG_SS7: 01395 ast_mutex_lock(&ss7->lock); 01396 break; 01397 #endif 01398 default: 01399 break; 01400 } 01401 } 01402 01403 #endif 01404 }
| static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 5668 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.
05669 { 05670 struct dahdi_pvt *p = ast->tech_pvt; 05671 int res; 05672 int idx; 05673 void *readbuf; 05674 struct ast_frame *f; 05675 05676 while (ast_mutex_trylock(&p->lock)) { 05677 CHANNEL_DEADLOCK_AVOIDANCE(ast); 05678 } 05679 05680 idx = dahdi_get_index(ast, p, 0); 05681 05682 /* Hang up if we don't really exist */ 05683 if (idx < 0) { 05684 ast_log(LOG_WARNING, "We dont exist?\n"); 05685 ast_mutex_unlock(&p->lock); 05686 return NULL; 05687 } 05688 05689 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 05690 ast_mutex_unlock(&p->lock); 05691 return NULL; 05692 } 05693 05694 p->subs[idx].f.frametype = AST_FRAME_NULL; 05695 p->subs[idx].f.datalen = 0; 05696 p->subs[idx].f.samples = 0; 05697 p->subs[idx].f.mallocd = 0; 05698 p->subs[idx].f.offset = 0; 05699 p->subs[idx].f.subclass = 0; 05700 p->subs[idx].f.delivery = ast_tv(0,0); 05701 p->subs[idx].f.src = "dahdi_read"; 05702 p->subs[idx].f.data.ptr = NULL; 05703 05704 /* make sure it sends initial key state as first frame */ 05705 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 05706 { 05707 struct dahdi_params ps; 05708 05709 memset(&ps, 0, sizeof(ps)); 05710 ps.channo = p->channel; 05711 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 05712 ast_mutex_unlock(&p->lock); 05713 return NULL; 05714 } 05715 p->firstradio = 1; 05716 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05717 if (ps.rxisoffhook) 05718 { 05719 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 05720 } 05721 else 05722 { 05723 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 05724 } 05725 ast_mutex_unlock(&p->lock); 05726 return &p->subs[idx].f; 05727 } 05728 if (p->ringt == 1) { 05729 ast_mutex_unlock(&p->lock); 05730 return NULL; 05731 } 05732 else if (p->ringt > 0) 05733 p->ringt--; 05734 05735 if (p->subs[idx].needringing) { 05736 /* Send ringing frame if requested */ 05737 p->subs[idx].needringing = 0; 05738 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05739 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 05740 ast_setstate(ast, AST_STATE_RINGING); 05741 ast_mutex_unlock(&p->lock); 05742 return &p->subs[idx].f; 05743 } 05744 05745 if (p->subs[idx].needbusy) { 05746 /* Send busy frame if requested */ 05747 p->subs[idx].needbusy = 0; 05748 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05749 p->subs[idx].f.subclass = AST_CONTROL_BUSY; 05750 ast_mutex_unlock(&p->lock); 05751 return &p->subs[idx].f; 05752 } 05753 05754 if (p->subs[idx].needcongestion) { 05755 /* Send congestion frame if requested */ 05756 p->subs[idx].needcongestion = 0; 05757 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05758 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION; 05759 ast_mutex_unlock(&p->lock); 05760 return &p->subs[idx].f; 05761 } 05762 05763 if (p->subs[idx].needcallerid) { 05764 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 05765 S_OR(p->lastcid_name, NULL), 05766 S_OR(p->lastcid_num, NULL) 05767 ); 05768 p->subs[idx].needcallerid = 0; 05769 } 05770 05771 if (p->subs[idx].needanswer) { 05772 /* Send answer frame if requested */ 05773 p->subs[idx].needanswer = 0; 05774 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05775 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05776 ast_mutex_unlock(&p->lock); 05777 return &p->subs[idx].f; 05778 } 05779 05780 if (p->subs[idx].needflash) { 05781 /* Send answer frame if requested */ 05782 p->subs[idx].needflash = 0; 05783 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05784 p->subs[idx].f.subclass = AST_CONTROL_FLASH; 05785 ast_mutex_unlock(&p->lock); 05786 return &p->subs[idx].f; 05787 } 05788 05789 if (p->subs[idx].needhold) { 05790 /* Send answer frame if requested */ 05791 p->subs[idx].needhold = 0; 05792 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05793 p->subs[idx].f.subclass = AST_CONTROL_HOLD; 05794 ast_mutex_unlock(&p->lock); 05795 ast_debug(1, "Sending hold on '%s'\n", ast->name); 05796 return &p->subs[idx].f; 05797 } 05798 05799 if (p->subs[idx].needunhold) { 05800 /* Send answer frame if requested */ 05801 p->subs[idx].needunhold = 0; 05802 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05803 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD; 05804 ast_mutex_unlock(&p->lock); 05805 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 05806 return &p->subs[idx].f; 05807 } 05808 05809 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 05810 if (!p->subs[idx].linear) { 05811 p->subs[idx].linear = 1; 05812 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05813 if (res) 05814 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 05815 } 05816 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 05817 (ast->rawreadformat == AST_FORMAT_ALAW)) { 05818 if (p->subs[idx].linear) { 05819 p->subs[idx].linear = 0; 05820 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 05821 if (res) 05822 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 05823 } 05824 } else { 05825 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 05826 ast_mutex_unlock(&p->lock); 05827 return NULL; 05828 } 05829 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 05830 CHECK_BLOCKING(ast); 05831 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05832 ast_clear_flag(ast, AST_FLAG_BLOCKING); 05833 /* Check for hangup */ 05834 if (res < 0) { 05835 f = NULL; 05836 if (res == -1) { 05837 if (errno == EAGAIN) { 05838 /* Return "NULL" frame if there is nobody there */ 05839 ast_mutex_unlock(&p->lock); 05840 return &p->subs[idx].f; 05841 } else if (errno == ELAST) { 05842 f = __dahdi_exception(ast); 05843 } else 05844 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 05845 } 05846 ast_mutex_unlock(&p->lock); 05847 return f; 05848 } 05849 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 05850 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 05851 f = __dahdi_exception(ast); 05852 ast_mutex_unlock(&p->lock); 05853 return f; 05854 } 05855 if (p->tdd) { /* if in TDD mode, see if we receive that */ 05856 int c; 05857 05858 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 05859 if (c < 0) { 05860 ast_debug(1,"tdd_feed failed\n"); 05861 ast_mutex_unlock(&p->lock); 05862 return NULL; 05863 } 05864 if (c) { /* if a char to return */ 05865 p->subs[idx].f.subclass = 0; 05866 p->subs[idx].f.frametype = AST_FRAME_TEXT; 05867 p->subs[idx].f.mallocd = 0; 05868 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05869 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 05870 p->subs[idx].f.datalen = 1; 05871 *((char *) p->subs[idx].f.data.ptr) = c; 05872 ast_mutex_unlock(&p->lock); 05873 return &p->subs[idx].f; 05874 } 05875 } 05876 /* Ensure the CW timer decrements only on a single subchannel */ 05877 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 05878 p->callwaitingrepeat--; 05879 } 05880 if (p->cidcwexpire) 05881 p->cidcwexpire--; 05882 /* Repeat callwaiting */ 05883 if (p->callwaitingrepeat == 1) { 05884 p->callwaitrings++; 05885 dahdi_callwait(ast); 05886 } 05887 /* Expire CID/CW */ 05888 if (p->cidcwexpire == 1) { 05889 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 05890 restore_conference(p); 05891 } 05892 if (p->subs[idx].linear) { 05893 p->subs[idx].f.datalen = READ_SIZE * 2; 05894 } else 05895 p->subs[idx].f.datalen = READ_SIZE; 05896 05897 /* Handle CallerID Transmission */ 05898 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 05899 send_callerid(p); 05900 } 05901 05902 p->subs[idx].f.frametype = AST_FRAME_VOICE; 05903 p->subs[idx].f.subclass = ast->rawreadformat; 05904 p->subs[idx].f.samples = READ_SIZE; 05905 p->subs[idx].f.mallocd = 0; 05906 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 05907 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 05908 #if 0 05909 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 05910 #endif 05911 if (p->dialing || /* Transmitting something */ 05912 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 05913 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05914 ) { 05915 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05916 don't send anything */ 05917 p->subs[idx].f.frametype = AST_FRAME_NULL; 05918 p->subs[idx].f.subclass = 0; 05919 p->subs[idx].f.samples = 0; 05920 p->subs[idx].f.mallocd = 0; 05921 p->subs[idx].f.offset = 0; 05922 p->subs[idx].f.data.ptr = NULL; 05923 p->subs[idx].f.datalen= 0; 05924 } 05925 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) { 05926 /* Perform busy detection. etc on the dahdi line */ 05927 int mute; 05928 05929 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 05930 05931 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 05932 mute = ast_dsp_was_muted(p->dsp); 05933 if (p->muting != mute) { 05934 p->muting = mute; 05935 dahdi_confmute(p, mute); 05936 } 05937 05938 if (f) { 05939 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05940 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05941 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05942 a busy */ 05943 f = NULL; 05944 } 05945 } else if (f->frametype == AST_FRAME_DTMF) { 05946 #ifdef HAVE_PRI 05947 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 05948 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 05949 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 05950 /* Don't accept in-band DTMF when in overlap dial mode */ 05951 f->frametype = AST_FRAME_NULL; 05952 f->subclass = 0; 05953 } 05954 #endif 05955 /* DSP clears us of being pulse */ 05956 p->pulsedial = 0; 05957 } 05958 } 05959 } else 05960 f = &p->subs[idx].f; 05961 05962 if (f && (f->frametype == AST_FRAME_DTMF)) 05963 dahdi_handle_dtmfup(ast, idx, &f); 05964 05965 /* If we have a fake_event, trigger exception to handle it */ 05966 if (p->fake_event) 05967 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05968 05969 ast_mutex_unlock(&p->lock); 05970 return f; 05971 }
| static struct ast_channel * dahdi_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 9466 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().
09467 { 09468 ast_group_t groupmatch = 0; 09469 int channelmatch = -1; 09470 int roundrobin = 0; 09471 int callwait = 0; 09472 int busy = 0; 09473 struct dahdi_pvt *p; 09474 struct ast_channel *tmp = NULL; 09475 char *dest=NULL; 09476 int x; 09477 char *s; 09478 char opt=0; 09479 int res=0, y=0; 09480 int backwards = 0; 09481 #ifdef HAVE_PRI 09482 int crv; 09483 int bearer = -1; 09484 int trunkgroup; 09485 struct dahdi_pri *pri=NULL; 09486 #endif 09487 struct dahdi_pvt *exitpvt, *start, *end; 09488 ast_mutex_t *lock; 09489 int channelmatched = 0; 09490 int groupmatched = 0; 09491 09492 /* 09493 * data is ---v 09494 * Dial(DAHDI/pseudo[/extension]) 09495 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 09496 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 09497 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 09498 * 09499 * g - channel group allocation search forward 09500 * G - channel group allocation search backward 09501 * r - channel group allocation round robin search forward 09502 * R - channel group allocation round robin search backward 09503 * 09504 * c - Wait for DTMF digit to confirm answer 09505 * r<cadance#> - Set distintive ring cadance number 09506 * d - Force bearer capability for ISDN/SS7 call to digital. 09507 */ 09508 09509 /* Assume we're locking the iflock */ 09510 lock = &iflock; 09511 start = iflist; 09512 end = ifend; 09513 if (data) { 09514 dest = ast_strdupa((char *)data); 09515 } else { 09516 ast_log(LOG_WARNING, "Channel requested with no data\n"); 09517 return NULL; 09518 } 09519 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 09520 /* Retrieve the group number */ 09521 char *stringp; 09522 09523 stringp = dest + 1; 09524 s = strsep(&stringp, "/"); 09525 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09526 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 09527 return NULL; 09528 } 09529 groupmatch = ((ast_group_t) 1 << x); 09530 if (toupper(dest[0]) == 'G') { 09531 if (dest[0] == 'G') { 09532 backwards = 1; 09533 p = ifend; 09534 } else 09535 p = iflist; 09536 } else { 09537 if (dest[0] == 'R') { 09538 backwards = 1; 09539 p = round_robin[x]?round_robin[x]->prev:ifend; 09540 if (!p) 09541 p = ifend; 09542 } else { 09543 p = round_robin[x]?round_robin[x]->next:iflist; 09544 if (!p) 09545 p = iflist; 09546 } 09547 roundrobin = 1; 09548 } 09549 } else { 09550 char *stringp; 09551 09552 stringp = dest; 09553 s = strsep(&stringp, "/"); 09554 p = iflist; 09555 if (!strcasecmp(s, "pseudo")) { 09556 /* Special case for pseudo */ 09557 x = CHAN_PSEUDO; 09558 channelmatch = x; 09559 } 09560 #ifdef HAVE_PRI 09561 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 09562 if ((trunkgroup < 1) || (crv < 1)) { 09563 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 09564 return NULL; 09565 } 09566 res--; 09567 for (x = 0; x < NUM_SPANS; x++) { 09568 if (pris[x].trunkgroup == trunkgroup) { 09569 pri = pris + x; 09570 lock = &pri->lock; 09571 start = pri->crvs; 09572 end = pri->crvend; 09573 break; 09574 } 09575 } 09576 if (!pri) { 09577 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 09578 return NULL; 09579 } 09580 channelmatch = crv; 09581 p = pris[x].crvs; 09582 } 09583 #endif 09584 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 09585 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 09586 return NULL; 09587 } else { 09588 channelmatch = x; 09589 } 09590 } 09591 /* Search for an unowned channel */ 09592 ast_mutex_lock(lock); 09593 exitpvt = p; 09594 while (p && !tmp) { 09595 if (roundrobin) 09596 round_robin[x] = p; 09597 #if 0 09598 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 09599 #endif 09600 09601 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 09602 ast_debug(1, "Using channel %d\n", p->channel); 09603 if (p->inalarm) 09604 goto next; 09605 09606 callwait = (p->owner != NULL); 09607 #ifdef HAVE_PRI 09608 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 09609 if (p->sig != SIG_FXSKS) { 09610 /* Gotta find an actual channel to use for this 09611 CRV if this isn't a callwait */ 09612 bearer = pri_find_empty_chan(pri, 0); 09613 if (bearer < 0) { 09614 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 09615 p = NULL; 09616 break; 09617 } 09618 pri_assign_bearer(p, pri, pri->pvts[bearer]); 09619 } else { 09620 if (alloc_sub(p, 0)) { 09621 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 09622 p = NULL; 09623 break; 09624 } else 09625 ast_debug(1, "Allocated placeholder pseudo channel\n"); 09626 09627 p->pri = pri; 09628 } 09629 } 09630 #endif 09631 if (p->channel == CHAN_PSEUDO) { 09632 p = chandup(p); 09633 if (!p) { 09634 break; 09635 } 09636 } 09637 if (p->owner) { 09638 if (alloc_sub(p, SUB_CALLWAIT)) { 09639 p = NULL; 09640 break; 09641 } 09642 } 09643 p->outgoing = 1; 09644 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 09645 if (!tmp) { 09646 p->outgoing = 0; 09647 } 09648 #ifdef HAVE_PRI 09649 if (p->bearer) { 09650 /* Log owner to bearer channel, too */ 09651 p->bearer->owner = tmp; 09652 } 09653 #endif 09654 /* Make special notes */ 09655 if (res > 1) { 09656 if (opt == 'c') { 09657 /* Confirm answer */ 09658 p->confirmanswer = 1; 09659 } else if (opt == 'r') { 09660 /* Distinctive ring */ 09661 if (res < 3) 09662 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 09663 else 09664 p->distinctivering = y; 09665 } else if (opt == 'd') { 09666 /* If this is an ISDN call, make it digital */ 09667 p->digital = 1; 09668 if (tmp) 09669 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 09670 } else { 09671 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 09672 } 09673 } 09674 /* Note if the call is a call waiting call */ 09675 if (tmp && callwait) 09676 tmp->cdrflags |= AST_CDR_CALLWAIT; 09677 break; 09678 } 09679 next: 09680 if (backwards) { 09681 p = p->prev; 09682 if (!p) 09683 p = end; 09684 } else { 09685 p = p->next; 09686 if (!p) 09687 p = start; 09688 } 09689 /* stop when you roll to the one that we started from */ 09690 if (p == exitpvt) 09691 break; 09692 } 09693 ast_mutex_unlock(lock); 09694 restart_monitor(); 09695 if (callwait) 09696 *cause = AST_CAUSE_BUSY; 09697 else if (!tmp) { 09698 if (channelmatched) { 09699 if (busy) 09700 *cause = AST_CAUSE_BUSY; 09701 } else if (groupmatched) { 09702 *cause = AST_CAUSE_CONGESTION; 09703 } 09704 } 09705 09706 return tmp; 09707 }
| static int dahdi_restart | ( | void | ) | [static] |
Definition at line 12532 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().
12533 { 12534 #if defined(HAVE_PRI) || defined(HAVE_SS7) 12535 int i, j; 12536 #endif 12537 int cancel_code; 12538 struct dahdi_pvt *p; 12539 12540 ast_mutex_lock(&restart_lock); 12541 12542 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 12543 dahdi_softhangup_all(); 12544 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 12545 12546 #if defined(HAVE_PRI) 12547 for (i = 0; i < NUM_SPANS; i++) { 12548 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 12549 cancel_code = pthread_cancel(pris[i].master); 12550 pthread_kill(pris[i].master, SIGURG); 12551 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 12552 pthread_join(pris[i].master, NULL); 12553 ast_debug(4, "Joined thread of span %d\n", i); 12554 } 12555 } 12556 #endif 12557 12558 #if defined(HAVE_SS7) 12559 for (i = 0; i < NUM_SPANS; i++) { 12560 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) { 12561 cancel_code = pthread_cancel(linksets[i].master); 12562 pthread_kill(linksets[i].master, SIGURG); 12563 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code); 12564 pthread_join(linksets[i].master, NULL); 12565 ast_debug(4, "Joined thread of span %d\n", i); 12566 } 12567 } 12568 #endif 12569 12570 ast_mutex_lock(&monlock); 12571 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 12572 cancel_code = pthread_cancel(monitor_thread); 12573 pthread_kill(monitor_thread, SIGURG); 12574 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 12575 pthread_join(monitor_thread, NULL); 12576 ast_debug(4, "Joined monitor thread\n"); 12577 } 12578 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 12579 12580 ast_mutex_lock(&mwi_thread_lock); 12581 while (mwi_thread_count > 0) { 12582 ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count); 12583 ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock); 12584 } 12585 ast_mutex_unlock(&mwi_thread_lock); 12586 ast_mutex_lock(&ss_thread_lock); 12587 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 12588 int x = DAHDI_FLASH; 12589 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 12590 12591 for (p = iflist; p; p = p->next) { 12592 if (p->owner) 12593 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 */ 12594 } 12595 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 12596 } 12597 12598 /* ensure any created channels before monitor threads were stopped are hungup */ 12599 dahdi_softhangup_all(); 12600 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 12601 destroy_all_channels(); 12602 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 12603 12604 ast_mutex_unlock(&monlock); 12605 12606 #ifdef HAVE_PRI 12607 for (i = 0; i < NUM_SPANS; i++) { 12608 for (j = 0; j < NUM_DCHANS; j++) 12609 dahdi_close_pri_fd(&(pris[i]), j); 12610 } 12611 12612 memset(pris, 0, sizeof(pris)); 12613 for (i = 0; i < NUM_SPANS; i++) { 12614 ast_mutex_init(&pris[i].lock); 12615 pris[i].offset = -1; 12616 pris[i].master = AST_PTHREADT_NULL; 12617 for (j = 0; j < NUM_DCHANS; j++) 12618 pris[i].fds[j] = -1; 12619 } 12620 pri_set_error(dahdi_pri_error); 12621 pri_set_message(dahdi_pri_message); 12622 #endif 12623 #ifdef HAVE_SS7 12624 for (i = 0; i < NUM_SPANS; i++) { 12625 for (j = 0; j < NUM_DCHANS; j++) 12626 dahdi_close_ss7_fd(&(linksets[i]), j); 12627 } 12628 12629 memset(linksets, 0, sizeof(linksets)); 12630 for (i = 0; i < NUM_SPANS; i++) { 12631 ast_mutex_init(&linksets[i].lock); 12632 linksets[i].master = AST_PTHREADT_NULL; 12633 for (j = 0; j < NUM_DCHANS; j++) 12634 linksets[i].fds[j] = -1; 12635 } 12636 ss7_set_error(dahdi_ss7_error); 12637 ss7_set_message(dahdi_ss7_message); 12638 #endif 12639 12640 if (setup_dahdi(2) != 0) { 12641 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 12642 ast_mutex_unlock(&ss_thread_lock); 12643 return 1; 12644 } 12645 ast_mutex_unlock(&ss_thread_lock); 12646 ast_mutex_unlock(&restart_lock); 12647 return 0; 12648 }
| static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12650 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.
12651 { 12652 switch (cmd) { 12653 case CLI_INIT: 12654 e->command = "dahdi restart"; 12655 e->usage = 12656 "Usage: dahdi restart\n" 12657 " Restarts the DAHDI channels: destroys them all and then\n" 12658 " re-reads them from chan_dahdi.conf.\n" 12659 " Note that this will STOP any running CALL on DAHDI channels.\n" 12660 ""; 12661 return NULL; 12662 case CLI_GENERATE: 12663 return NULL; 12664 } 12665 if (a->argc != 2) 12666 return CLI_SHOWUSAGE; 12667 12668 if (dahdi_restart() != 0) 12669 return CLI_FAILURE; 12670 return CLI_SUCCESS; 12671 }
| static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4465 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().
04466 { 04467 int x; 04468 int res; 04469 /* Make sure our transmit state is on hook */ 04470 x = 0; 04471 x = DAHDI_ONHOOK; 04472 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04473 do { 04474 x = DAHDI_RING; 04475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04476 if (res) { 04477 switch (errno) { 04478 case EBUSY: 04479 case EINTR: 04480 /* Wait just in case */ 04481 usleep(10000); 04482 continue; 04483 case EINPROGRESS: 04484 res = 0; 04485 break; 04486 default: 04487 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 04488 res = 0; 04489 } 04490 } 04491 } while (res); 04492 return res; 04493 }
| static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3260 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().
03261 { 03262 /* Data will be our digit string */ 03263 struct dahdi_pvt *p; 03264 char *digits = (char *) data; 03265 03266 if (ast_strlen_zero(digits)) { 03267 ast_debug(1, "No digit string sent to application!\n"); 03268 return -1; 03269 } 03270 03271 p = (struct dahdi_pvt *)chan->tech_pvt; 03272 03273 if (!p) { 03274 ast_debug(1, "Unable to find technology private\n"); 03275 return -1; 03276 } 03277 03278 ast_mutex_lock(&p->lock); 03279 03280 if (!p->pri || !p->call) { 03281 ast_debug(1, "Unable to find pri or call on channel!\n"); 03282 ast_mutex_unlock(&p->lock); 03283 return -1; 03284 } 03285 03286 if (!pri_grab(p, p->pri)) { 03287 pri_keypad_facility(p->pri->pri, p->call, digits); 03288 pri_rel(p->pri); 03289 } else { 03290 ast_debug(1, "Unable to grab pri to send keypad facility!\n"); 03291 ast_mutex_unlock(&p->lock); 03292 return -1; 03293 } 03294 03295 ast_mutex_unlock(&p->lock); 03296 03297 return 0; 03298 }
| static int dahdi_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 15381 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.
15382 { 15383 #define END_SILENCE_LEN 400 15384 #define HEADER_MS 50 15385 #define TRAILER_MS 5 15386 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 15387 #define ASCII_BYTES_PER_CHAR 80 15388 15389 unsigned char *buf,*mybuf; 15390 struct dahdi_pvt *p = c->tech_pvt; 15391 struct pollfd fds[1]; 15392 int size,res,fd,len,x; 15393 int bytes=0; 15394 /* Initial carrier (imaginary) */ 15395 float cr = 1.0; 15396 float ci = 0.0; 15397 float scont = 0.0; 15398 int idx; 15399 15400 idx = dahdi_get_index(c, p, 0); 15401 if (idx < 0) { 15402 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 15403 return -1; 15404 } 15405 if (!text[0]) return(0); /* if nothing to send, dont */ 15406 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 15407 if (p->mate) 15408 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 15409 else 15410 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 15411 if (!buf) 15412 return -1; 15413 mybuf = buf; 15414 if (p->mate) { 15415 int codec = AST_LAW(p); 15416 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 15417 PUT_CLID_MARKMS; 15418 } 15419 /* Put actual message */ 15420 for (x = 0; text[x]; x++) { 15421 PUT_CLID(text[x]); 15422 } 15423 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 15424 PUT_CLID_MARKMS; 15425 } 15426 len = bytes; 15427 buf = mybuf; 15428 } else { 15429 len = tdd_generate(p->tdd, buf, text); 15430 if (len < 1) { 15431 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 15432 ast_free(mybuf); 15433 return -1; 15434 } 15435 } 15436 memset(buf + len, 0x7f, END_SILENCE_LEN); 15437 len += END_SILENCE_LEN; 15438 fd = p->subs[idx].dfd; 15439 while (len) { 15440 if (ast_check_hangup(c)) { 15441 ast_free(mybuf); 15442 return -1; 15443 } 15444 size = len; 15445 if (size > READ_SIZE) 15446 size = READ_SIZE; 15447 fds[0].fd = fd; 15448 fds[0].events = POLLOUT | POLLPRI; 15449 fds[0].revents = 0; 15450 res = poll(fds, 1, -1); 15451 if (!res) { 15452 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 15453 continue; 15454 } 15455 /* if got exception */ 15456 if (fds[0].revents & POLLPRI) { 15457 ast_free(mybuf); 15458 return -1; 15459 } 15460 if (!(fds[0].revents & POLLOUT)) { 15461 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 15462 continue; 15463 } 15464 res = write(fd, buf, size); 15465 if (res != size) { 15466 if (res == -1) { 15467 ast_free(mybuf); 15468 return -1; 15469 } 15470 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 15471 break; 15472 } 15473 len -= size; 15474 buf += size; 15475 } 15476 ast_free(mybuf); 15477 return(0); 15478 }
| static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13279 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.
13280 { 13281 int channel; 13282 int on; 13283 struct dahdi_pvt *dahdi_chan = NULL; 13284 13285 switch (cmd) { 13286 case CLI_INIT: 13287 e->command = "dahdi set dnd"; 13288 e->usage = 13289 "Usage: dahdi set dnd <chan#> <on|off>\n" 13290 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 13291 " Changes take effect immediately.\n" 13292 " <chan num> is the channel number\n" 13293 " <on|off> Enable or disable DND mode?\n" 13294 ; 13295 return NULL; 13296 case CLI_GENERATE: 13297 return NULL; 13298 } 13299 13300 if (a->argc != 5) 13301 return CLI_SHOWUSAGE; 13302 13303 if ((channel = atoi(a->argv[3])) <= 0) { 13304 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 13305 return CLI_SHOWUSAGE; 13306 } 13307 13308 if (ast_true(a->argv[4])) 13309 on = 1; 13310 else if (ast_false(a->argv[4])) 13311 on = 0; 13312 else { 13313 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 13314 return CLI_SHOWUSAGE; 13315 } 13316 13317 ast_mutex_lock(&iflock); 13318 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 13319 if (dahdi_chan->channel != channel) 13320 continue; 13321 13322 /* Found the channel. Actually set it */ 13323 dahdi_dnd(dahdi_chan, on); 13324 break; 13325 } 13326 ast_mutex_unlock(&iflock); 13327 13328 if (!dahdi_chan) { 13329 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13330 return CLI_FAILURE; 13331 } 13332 13333 return CLI_SUCCESS; 13334 }
| static int dahdi_set_hook | ( | int | fd, | |
| int | hs | |||
| ) | [inline, static] |
Definition at line 2207 of file chan_dahdi.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mkintf(), mwi_send_thread(), and ss_thread().
02208 { 02209 int x, res; 02210 02211 x = hs; 02212 res = ioctl(fd, DAHDI_HOOK, &x); 02213 02214 if (res < 0) { 02215 if (errno == EINPROGRESS) 02216 return 0; 02217 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02218 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02219 } 02220 02221 return res; 02222 }
| static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13136 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.
13137 { 13138 int channel; 13139 int gain; 13140 int tx; 13141 struct dahdi_hwgain hwgain; 13142 struct dahdi_pvt *tmp = NULL; 13143 13144 switch (cmd) { 13145 case CLI_INIT: 13146 e->command = "dahdi set hwgain"; 13147 e->usage = 13148 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 13149 " Sets the hardware gain on a a given channel, overriding the\n" 13150 " value provided at module loadtime, whether the channel is in\n" 13151 " use or not. Changes take effect immediately.\n" 13152 " <rx|tx> which direction do you want to change (relative to our module)\n" 13153 " <chan num> is the channel number relative to the device\n" 13154 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13155 return NULL; 13156 case CLI_GENERATE: 13157 return NULL; 13158 } 13159 13160 if (a->argc != 6) 13161 return CLI_SHOWUSAGE; 13162 13163 if (!strcasecmp("rx", a->argv[3])) 13164 tx = 0; /* rx */ 13165 else if (!strcasecmp("tx", a->argv[3])) 13166 tx = 1; /* tx */ 13167 else 13168 return CLI_SHOWUSAGE; 13169 13170 channel = atoi(a->argv[4]); 13171 gain = atof(a->argv[5])*10.0; 13172 13173 ast_mutex_lock(&iflock); 13174 13175 for (tmp = iflist; tmp; tmp = tmp->next) { 13176 13177 if (tmp->channel != channel) 13178 continue; 13179 13180 if (tmp->subs[SUB_REAL].dfd == -1) 13181 break; 13182 13183 hwgain.newgain = gain; 13184 hwgain.tx = tx; 13185 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 13186 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 13187 ast_mutex_unlock(&iflock); 13188 return CLI_FAILURE; 13189 } 13190 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 13191 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 13192 break; 13193 } 13194 13195 ast_mutex_unlock(&iflock); 13196 13197 if (tmp) 13198 return CLI_SUCCESS; 13199 13200 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13201 return CLI_FAILURE; 13202 13203 }
| static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13205 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.
13206 { 13207 int channel; 13208 float gain; 13209 int tx; 13210 int res; 13211 ast_mutex_t *lock; 13212 struct dahdi_pvt *tmp = NULL; 13213 13214 switch (cmd) { 13215 case CLI_INIT: 13216 e->command = "dahdi set swgain"; 13217 e->usage = 13218 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 13219 " Sets the software gain on a a given channel, overriding the\n" 13220 " value provided at module loadtime, whether the channel is in\n" 13221 " use or not. Changes take effect immediately.\n" 13222 " <rx|tx> which direction do you want to change (relative to our module)\n" 13223 " <chan num> is the channel number relative to the device\n" 13224 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 13225 return NULL; 13226 case CLI_GENERATE: 13227 return NULL; 13228 } 13229 13230 lock = &iflock; 13231 13232 if (a->argc != 6) 13233 return CLI_SHOWUSAGE; 13234 13235 if (!strcasecmp("rx", a->argv[3])) 13236 tx = 0; /* rx */ 13237 else if (!strcasecmp("tx", a->argv[3])) 13238 tx = 1; /* tx */ 13239 else 13240 return CLI_SHOWUSAGE; 13241 13242 channel = atoi(a->argv[4]); 13243 gain = atof(a->argv[5]); 13244 13245 ast_mutex_lock(lock); 13246 for (tmp = iflist; tmp; tmp = tmp->next) { 13247 13248 if (tmp->channel != channel) 13249 continue; 13250 13251 if (tmp->subs[SUB_REAL].dfd == -1) 13252 break; 13253 13254 if (tx) 13255 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13256 else 13257 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 13258 13259 if (res) { 13260 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 13261 ast_mutex_unlock(lock); 13262 return CLI_FAILURE; 13263 } 13264 13265 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 13266 tx ? "tx" : "rx", gain, channel); 13267 break; 13268 } 13269 ast_mutex_unlock(lock); 13270 13271 if (tmp) 13272 return CLI_SUCCESS; 13273 13274 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 13275 return CLI_FAILURE; 13276 13277 }
| static int dahdi_setlaw | ( | int | dfd, | |
| int | law | |||
| ) | [static] |
Definition at line 9710 of file chan_dahdi.c.
Referenced by pri_dchannel(), and ss7_start_call().
09711 { 09712 return ioctl(dfd, DAHDI_SETLAW, &law); 09713 }
| static int dahdi_setlinear | ( | int | dfd, | |
| int | linear | |||
| ) | [static] |
Definition at line 1511 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
| static int dahdi_setoption | ( | struct ast_channel * | chan, | |
| int | option, | |||
| void * | data, | |||
| int | datalen | |||
| ) | [static] |
Definition at line 3839 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.
03840 { 03841 char *cp; 03842 signed char *scp; 03843 int x; 03844 int idx; 03845 struct dahdi_pvt *p = chan->tech_pvt, *pp; 03846 struct oprmode *oprmode; 03847 03848 03849 /* all supported options require data */ 03850 if (!data || (datalen < 1)) { 03851 errno = EINVAL; 03852 return -1; 03853 } 03854 03855 switch (option) { 03856 case AST_OPTION_TXGAIN: 03857 scp = (signed char *) data; 03858 idx = dahdi_get_index(chan, p, 0); 03859 if (idx < 0) { 03860 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 03861 return -1; 03862 } 03863 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 03864 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law); 03865 case AST_OPTION_RXGAIN: 03866 scp = (signed char *) data; 03867 idx = dahdi_get_index(chan, p, 0); 03868 if (idx < 0) { 03869 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 03870 return -1; 03871 } 03872 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 03873 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law); 03874 case AST_OPTION_TONE_VERIFY: 03875 if (!p->dsp) 03876 break; 03877 cp = (char *) data; 03878 switch (*cp) { 03879 case 1: 03880 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 03881 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 03882 break; 03883 case 2: 03884 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 03885 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 03886 break; 03887 default: 03888 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 03889 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 03890 break; 03891 } 03892 break; 03893 case AST_OPTION_TDD: 03894 /* turn on or off TDD */ 03895 cp = (char *) data; 03896 p->mate = 0; 03897 if (!*cp) { /* turn it off */ 03898 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 03899 if (p->tdd) 03900 tdd_free(p->tdd); 03901 p->tdd = 0; 03902 break; 03903 } 03904 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 03905 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03906 dahdi_disable_ec(p); 03907 /* otherwise, turn it on */ 03908 if (!p->didtdd) { /* if havent done it yet */ 03909 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 03910 unsigned char *buf; 03911 int size, res, fd, len; 03912 struct pollfd fds[1]; 03913 03914 buf = mybuf; 03915 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03916 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03917 len = 40000; 03918 idx = dahdi_get_index(chan, p, 0); 03919 if (idx < 0) { 03920 ast_log(LOG_WARNING, "No index in TDD?\n"); 03921 return -1; 03922 } 03923 fd = p->subs[idx].dfd; 03924 while (len) { 03925 if (ast_check_hangup(chan)) 03926 return -1; 03927 size = len; 03928 if (size > READ_SIZE) 03929 size = READ_SIZE; 03930 fds[0].fd = fd; 03931 fds[0].events = POLLPRI | POLLOUT; 03932 fds[0].revents = 0; 03933 res = poll(fds, 1, -1); 03934 if (!res) { 03935 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 03936 continue; 03937 } 03938 /* if got exception */ 03939 if (fds[0].revents & POLLPRI) 03940 return -1; 03941 if (!(fds[0].revents & POLLOUT)) { 03942 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 03943 continue; 03944 } 03945 res = write(fd, buf, size); 03946 if (res != size) { 03947 if (res == -1) return -1; 03948 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03949 break; 03950 } 03951 len -= size; 03952 buf += size; 03953 } 03954 p->didtdd = 1; /* set to have done it now */ 03955 } 03956 if (*cp == 2) { /* Mate mode */ 03957 if (p->tdd) 03958 tdd_free(p->tdd); 03959 p->tdd = 0; 03960 p->mate = 1; 03961 break; 03962 } 03963 if (!p->tdd) { /* if we dont have one yet */ 03964 p->tdd = tdd_new(); /* allocate one */ 03965 } 03966 break; 03967 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03968 if (!p->dsp) 03969 break; 03970 cp = (char *) data; 03971 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03972 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03973 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 03974 break; 03975 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03976 cp = (char *) data; 03977 if (!*cp) { 03978 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03979 x = 0; 03980 dahdi_disable_ec(p); 03981 } else { 03982 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03983 x = 1; 03984 } 03985 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03986 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03987 break; 03988 case AST_OPTION_OPRMODE: /* Operator services mode */ 03989 oprmode = (struct oprmode *) data; 03990 pp = oprmode->peer->tech_pvt; 03991 p->oprmode = pp->oprmode = 0; 03992 /* setup peers */ 03993 p->oprpeer = pp; 03994 pp->oprpeer = p; 03995 /* setup modes, if any */ 03996 if (oprmode->mode) 03997 { 03998 pp->oprmode = oprmode->mode; 03999 p->oprmode = -oprmode->mode; 04000 } 04001 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 04002 oprmode->mode, chan->name,oprmode->peer->name); 04003 break; 04004 case AST_OPTION_ECHOCAN: 04005 cp = (char *) data; 04006 if (*cp) { 04007 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name); 04008 dahdi_enable_ec(p); 04009 } else { 04010 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name); 04011 dahdi_disable_ec(p); 04012 } 04013 break; 04014 } 04015 errno = 0; 04016 04017 return 0; 04018 }
| static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12807 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.
12808 { 12809 int channel; 12810 struct dahdi_pvt *tmp = NULL; 12811 struct dahdi_confinfo ci; 12812 struct dahdi_params ps; 12813 int x; 12814 ast_mutex_t *lock; 12815 struct dahdi_pvt *start; 12816 #ifdef HAVE_PRI 12817 char *c; 12818 int trunkgroup; 12819 struct dahdi_pri *pri=NULL; 12820 #endif 12821 switch (cmd) { 12822 case CLI_INIT: 12823 e->command = "dahdi show channel"; 12824 e->usage = 12825 "Usage: dahdi show channel <chan num>\n" 12826 " Detailed information about a given channel\n"; 12827 return NULL; 12828 case CLI_GENERATE: 12829 return NULL; 12830 } 12831 12832 lock = &iflock; 12833 start = iflist; 12834 12835 if (a->argc != 4) 12836 return CLI_SHOWUSAGE; 12837 #ifdef HAVE_PRI 12838 if ((c = strchr(a->argv[3], ':'))) { 12839 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 12840 return CLI_SHOWUSAGE; 12841 if ((trunkgroup < 1) || (channel < 1)) 12842 return CLI_SHOWUSAGE; 12843 for (x = 0; x < NUM_SPANS; x++) { 12844 if (pris[x].trunkgroup == trunkgroup) { 12845 pri = pris + x; 12846 break; 12847 } 12848 } 12849 if (pri) { 12850 start = pri->crvs; 12851 lock = &pri->lock; 12852 } else { 12853 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12854 return CLI_FAILURE; 12855 } 12856 } else 12857 #endif 12858 channel = atoi(a->argv[3]); 12859 12860 ast_mutex_lock(lock); 12861 tmp = start; 12862 while (tmp) { 12863 if (tmp->channel == channel) { 12864 #ifdef HAVE_PRI 12865 if (pri) 12866 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 12867 else 12868 #endif 12869 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 12870 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 12871 ast_cli(a->fd, "Span: %d\n", tmp->span); 12872 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 12873 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 12874 ast_cli(a->fd, "Context: %s\n", tmp->context); 12875 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 12876 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 12877 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 12878 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 12879 if (tmp->vars) { 12880 struct ast_variable *v; 12881 ast_cli(a->fd, "Variables:\n"); 12882 for (v = tmp->vars ; v ; v = v->next) 12883 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 12884 } 12885 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 12886 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 12887 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 12888 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 12889 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 12890 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)" : ""); 12891 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)" : ""); 12892 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)" : ""); 12893 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 12894 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 12895 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 12896 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 12897 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 12898 if (tmp->busydetect) { 12899 #if defined(BUSYDETECT_TONEONLY) 12900 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 12901 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 12902 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 12903 #endif 12904 #ifdef BUSYDETECT_DEBUG 12905 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 12906 #endif 12907 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 12908 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength); 12909 } 12910 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 12911 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 12912 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 12913 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 12914 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 12915 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 12916 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no"); 12917 ast_cli(a->fd, "Echo Cancellation:\n"); 12918 12919 if (tmp->echocancel.head.tap_length) { 12920 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 12921 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 12922 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 12923 } 12924 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 12925 } else { 12926 ast_cli(a->fd, "\tnone\n"); 12927 } 12928 if (tmp->master) 12929 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 12930 for (x = 0; x < MAX_SLAVES; x++) { 12931 if (tmp->slaves[x]) 12932 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 12933 } 12934 #ifdef HAVE_SS7 12935 if (tmp->ss7) { 12936 ast_cli(a->fd, "CIC: %d\n", tmp->cic); 12937 } 12938 #endif 12939 #ifdef HAVE_PRI 12940 if (tmp->pri) { 12941 ast_cli(a->fd, "PRI Flags: "); 12942 if (tmp->resetting) 12943 ast_cli(a->fd, "Resetting "); 12944 if (tmp->call) 12945 ast_cli(a->fd, "Call "); 12946 if (tmp->bearer) 12947 ast_cli(a->fd, "Bearer "); 12948 ast_cli(a->fd, "\n"); 12949 if (tmp->logicalspan) 12950 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 12951 else 12952 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 12953 } 12954 12955 #endif 12956 memset(&ci, 0, sizeof(ci)); 12957 ps.channo = tmp->channel; 12958 if (tmp->subs[SUB_REAL].dfd > -1) { 12959 memset(&ci, 0, sizeof(ci)); 12960 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 12961 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 12962 } 12963 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 12964 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 12965 } 12966 memset(&ps, 0, sizeof(ps)); 12967 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 12968 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 12969 } else { 12970 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 12971 } 12972 } 12973 ast_mutex_unlock(lock); 12974 return CLI_SUCCESS; 12975 } 12976 tmp = tmp->next; 12977 } 12978 12979 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 12980 ast_mutex_unlock(lock); 12981 return CLI_FAILURE; 12982 }
| static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12683 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.
12684 { 12685 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12686 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 12687 unsigned int targetnum = 0; 12688 int filtertype = 0; 12689 struct dahdi_pvt *tmp = NULL; 12690 char tmps[20] = ""; 12691 char statestr[20] = ""; 12692 char blockstr[20] = ""; 12693 ast_mutex_t *lock; 12694 struct dahdi_pvt *start; 12695 #ifdef HAVE_PRI 12696 int trunkgroup; 12697 struct dahdi_pri *pri = NULL; 12698 int x; 12699 #endif 12700 switch (cmd) { 12701 case CLI_INIT: 12702 e->command = "dahdi show channels [trunkgroup|group|context]"; 12703 e->usage = 12704 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n" 12705 " Shows a list of available channels with optional filtering\n" 12706 " <group> must be a number between 0 and 63\n"; 12707 return NULL; 12708 case CLI_GENERATE: 12709 return NULL; 12710 } 12711 12712 lock = &iflock; 12713 start = iflist; 12714 12715 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */ 12716 12717 if (!((a->argc == 3) || (a->argc == 5))) 12718 return CLI_SHOWUSAGE; 12719 12720 if (a->argc == 5) { 12721 #ifdef HAVE_PRI 12722 if (!strcasecmp(a->argv[3], "trunkgroup")) { 12723 /* this option requires no special handling, so leave filtertype to zero */ 12724 if ((trunkgroup = atoi(a->argv[4])) < 1) 12725 return CLI_SHOWUSAGE; 12726 for (x = 0; x < NUM_SPANS; x++) { 12727 if (pris[x].trunkgroup == trunkgroup) { 12728 pri = pris + x; 12729 break; 12730 } 12731 } 12732 if (pri) { 12733 start = pri->crvs; 12734 lock = &pri->lock; 12735 } else { 12736 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 12737 return CLI_FAILURE; 12738 } 12739 } else 12740 #endif 12741 if (!strcasecmp(a->argv[3], "group")) { 12742 targetnum = atoi(a->argv[4]); 12743 if ((targetnum < 0) || (targetnum > 63)) 12744 return CLI_SHOWUSAGE; 12745 targetnum = 1 << targetnum; 12746 filtertype = 1; 12747 } else if (!strcasecmp(a->argv[3], "context")) { 12748 filtertype = 2; 12749 } 12750 } 12751 12752 ast_mutex_lock(lock); 12753 #ifdef HAVE_PRI 12754 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12755 #else 12756 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 12757 #endif 12758 12759 tmp = start; 12760 while (tmp) { 12761 if (filtertype) { 12762 switch(filtertype) { 12763 case 1: /* dahdi show channels group <group> */ 12764 if (!(tmp->group & targetnum)) { 12765 tmp = tmp->next; 12766 continue; 12767 } 12768 break; 12769 case 2: /* dahdi show channels context <context> */ 12770 if (strcasecmp(tmp->context, a->argv[4])) { 12771 tmp = tmp->next; 12772 continue; 12773 } 12774 break; 12775 default: 12776 ; 12777 } 12778 } 12779 if (tmp->channel > 0) { 12780 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 12781 } else 12782 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 12783 12784 if (tmp->locallyblocked) 12785 blockstr[0] = 'L'; 12786 else 12787 blockstr[0] = ' '; 12788 12789 if (tmp->remotelyblocked) 12790 blockstr[1] = 'R'; 12791 else 12792 blockstr[1] = ' '; 12793 12794 blockstr[2] = '\0'; 12795 12796 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 12797 12798 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 12799 tmp = tmp->next; 12800 } 12801 ast_mutex_unlock(lock); 12802 return CLI_SUCCESS; 12803 #undef FORMAT 12804 #undef FORMAT2 12805 }
| static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13021 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.
13022 { 13023 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 13024 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 13025 int span; 13026 int res; 13027 char alarmstr[50]; 13028 13029 int ctl; 13030 struct dahdi_spaninfo s; 13031 13032 switch (cmd) { 13033 case CLI_INIT: 13034 e->command = "dahdi show status"; 13035 e->usage = 13036 "Usage: dahdi show status\n" 13037 " Shows a list of DAHDI cards with status\n"; 13038 return NULL; 13039 case CLI_GENERATE: 13040 return NULL; 13041 } 13042 ctl = open("/dev/dahdi/ctl", O_RDWR); 13043 if (ctl < 0) { 13044 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 13045 return CLI_FAILURE; 13046 } 13047 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 13048 13049 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 13050 s.spanno = span; 13051 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 13052 if (res) { 13053 continue; 13054 } 13055 alarmstr[0] = '\0'; 13056 if (s.alarms > 0) { 13057 if (s.alarms & DAHDI_ALARM_BLUE) 13058 strcat(alarmstr, "BLU/"); 13059 if (s.alarms & DAHDI_ALARM_YELLOW) 13060 strcat(alarmstr, "YEL/"); 13061 if (s.alarms & DAHDI_ALARM_RED) 13062 strcat(alarmstr, "RED/"); 13063 if (s.alarms & DAHDI_ALARM_LOOPBACK) 13064 strcat(alarmstr, "LB/"); 13065 if (s.alarms & DAHDI_ALARM_RECOVER) 13066 strcat(alarmstr, "REC/"); 13067 if (s.alarms & DAHDI_ALARM_NOTOPEN) 13068 strcat(alarmstr, "NOP/"); 13069 if (!strlen(alarmstr)) 13070 strcat(alarmstr, "UUU/"); 13071 if (strlen(alarmstr)) { 13072 /* Strip trailing / */ 13073 alarmstr[strlen(alarmstr) - 1] = '\0'; 13074 } 13075 } else { 13076 if (s.numchans) 13077 strcpy(alarmstr, "OK"); 13078 else 13079 strcpy(alarmstr, "UNCONFIGURED"); 13080 } 13081 13082 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count 13083 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 13084 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 13085 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 13086 "CAS" 13087 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 13088 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 13089 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 13090 "Unk" 13091 , s.lineconfig & DAHDI_CONFIG_CRC4 ? 13092 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL" 13093 , lbostr[s.lbo] 13094 ); 13095 } 13096 close(ctl); 13097 13098 return CLI_SUCCESS; 13099 #undef FORMAT 13100 #undef FORMAT2 13101 }
| static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13103 of file chan_dahdi.c.
References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, and ast_cli_entry::usage.
13104 { 13105 int pseudo_fd = -1; 13106 struct dahdi_versioninfo vi; 13107 13108 switch (cmd) { 13109 case CLI_INIT: 13110 e->command = "dahdi show version"; 13111 e->usage = 13112 "Usage: dahdi show version\n" 13113 " Shows the DAHDI version in use\n"; 13114 return NULL; 13115 case CLI_GENERATE: 13116 return NULL; 13117 } 13118 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 13119 ast_cli(a->fd, "Failed to open control file to get version.\n"); 13120 return CLI_SUCCESS; 13121 } 13122 13123 strcpy(vi.version, "Unknown"); 13124 strcpy(vi.echo_canceller, "Unknown"); 13125 13126 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 13127 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 13128 else 13129 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 13130 13131 close(pseudo_fd); 13132 13133 return CLI_SUCCESS; 13134 }
| static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1754 of file chan_dahdi.c.
References buf, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, and SIG_SS7.
01755 { 01756 static char buf[256]; 01757 switch (sig) { 01758 case SIG_EM: 01759 return "E & M Immediate"; 01760 case SIG_EMWINK: 01761 return "E & M Wink"; 01762 case SIG_EM_E1: 01763 return "E & M E1"; 01764 case SIG_FEATD: 01765 return "Feature Group D (DTMF)"; 01766 case SIG_FEATDMF: 01767 return "Feature Group D (MF)"; 01768 case SIG_FEATDMF_TA: 01769 return "Feature Groud D (MF) Tandem Access"; 01770 case SIG_FEATB: 01771 return "Feature Group B (MF)"; 01772 case SIG_E911: 01773 return "E911 (MF)"; 01774 case SIG_FGC_CAMA: 01775 return "FGC/CAMA (Dialpulse)"; 01776 case SIG_FGC_CAMAMF: 01777 return "FGC/CAMA (MF)"; 01778 case SIG_FXSLS: 01779 return "FXS Loopstart"; 01780 case SIG_FXSGS: 01781 return "FXS Groundstart"; 01782 case SIG_FXSKS: 01783 return "FXS Kewlstart"; 01784 case SIG_FXOLS: 01785 return "FXO Loopstart"; 01786 case SIG_FXOGS: 01787 return "FXO Groundstart"; 01788 case SIG_FXOKS: 01789 return "FXO Kewlstart"; 01790 case SIG_PRI: 01791 return "ISDN PRI"; 01792 case SIG_BRI: 01793 return "ISDN BRI Point to Point"; 01794 case SIG_BRI_PTMP: 01795 return "ISDN BRI Point to MultiPoint"; 01796 case SIG_SS7: 01797 return "SS7"; 01798 case SIG_SF: 01799 return "SF (Tone) Immediate"; 01800 case SIG_SFWINK: 01801 return "SF (Tone) Wink"; 01802 case SIG_SF_FEATD: 01803 return "SF (Tone) with Feature Group D (DTMF)"; 01804 case SIG_SF_FEATDMF: 01805 return "SF (Tone) with Feature Group D (MF)"; 01806 case SIG_SF_FEATB: 01807 return "SF (Tone) with Feature Group B (MF)"; 01808 case SIG_GR303FXOKS: 01809 return "GR-303 with FXOKS"; 01810 case SIG_GR303FXSKS: 01811 return "GR-303 with FXSKS"; 01812 case 0: 01813 return "Pseudo"; 01814 default: 01815 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01816 return buf; 01817 } 01818 }
| static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 12503 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().
12504 { 12505 struct dahdi_pvt *p; 12506 retry: 12507 ast_mutex_lock(&iflock); 12508 for (p = iflist; p; p = p->next) { 12509 ast_mutex_lock(&p->lock); 12510 if (p->owner && !p->restartpending) { 12511 if (ast_channel_trylock(p->owner)) { 12512 if (option_debug > 2) 12513 ast_verbose("Avoiding deadlock\n"); 12514 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 12515 ast_mutex_unlock(&p->lock); 12516 ast_mutex_unlock(&iflock); 12517 goto retry; 12518 } 12519 if (option_debug > 2) 12520 ast_verbose("Softhanging up on %s\n", p->owner->name); 12521 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 12522 p->restartpending = 1; 12523 num_restart_pending++; 12524 ast_channel_unlock(p->owner); 12525 } 12526 ast_mutex_unlock(&p->lock); 12527 } 12528 ast_mutex_unlock(&iflock); 12529 }
| static void dahdi_ss7_error | ( | struct ss7 * | ss7, | |
| char * | s | |||
| ) | [static] |
Definition at line 10524 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 10509 of file chan_dahdi.c.
References ast_verbose, linksets, and NUM_SPANS.
Referenced by dahdi_restart(), and load_module().
10510 { 10511 #if 0 10512 int i; 10513 10514 for (i = 0; i < NUM_SPANS; i++) 10515 if (linksets[i].ss7 == ss7) 10516 break; 10517 10518 ast_verbose("[%d] %s", i+1, s); 10519 #else 10520 ast_verbose("%s", s); 10521 #endif 10522 }
| static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2036 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, dahdi_pvt::echocanon, dahdi_pvt::echotraining, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_answer(), and dahdi_handle_event().
02037 { 02038 int x; 02039 int res; 02040 02041 if (p && p->echocanon && p->echotraining) { 02042 x = p->echotraining; 02043 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02044 if (res) 02045 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02046 else 02047 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 02048 } else { 02049 ast_debug(1, "No echo training requested\n"); 02050 } 02051 }
| static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
| struct dahdi_pvt * | master, | |||
| int | needlock | |||
| ) | [static] |
Definition at line 4039 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().
04040 { 04041 /* Unlink a specific slave or all slaves/masters from a given master */ 04042 int x; 04043 int hasslaves; 04044 if (!master) 04045 return; 04046 if (needlock) { 04047 ast_mutex_lock(&master->lock); 04048 if (slave) { 04049 while (ast_mutex_trylock(&slave->lock)) { 04050 DEADLOCK_AVOIDANCE(&master->lock); 04051 } 04052 } 04053 } 04054 hasslaves = 0; 04055 for (x = 0; x < MAX_SLAVES; x++) { 04056 if (master->slaves[x]) { 04057 if (!slave || (master->slaves[x] == slave)) { 04058 /* Take slave out of the conference */ 04059 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 04060 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 04061 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 04062 master->slaves[x]->master = NULL; 04063 master->slaves[x] = NULL; 04064 } else 04065 hasslaves = 1; 04066 } 04067 if (!hasslaves) 04068 master->inconference = 0; 04069 } 04070 if (!slave) { 04071 if (master->master) { 04072 /* Take master out of the conference */ 04073 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 04074 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 04075 hasslaves = 0; 04076 for (x = 0; x < MAX_SLAVES; x++) { 04077 if (master->master->slaves[x] == master) 04078 master->master->slaves[x] = NULL; 04079 else if (master->master->slaves[x]) 04080 hasslaves = 1; 04081 } 04082 if (!hasslaves) 04083 master->master->inconference = 0; 04084 } 04085 master->master = NULL; 04086 } 04087 update_conf(master); 04088 if (needlock) { 04089 if (slave) 04090 ast_mutex_unlock(&slave->lock); 04091 ast_mutex_unlock(&master->lock); 04092 } 04093 }
| static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 312 of file chan_dahdi.c.
Referenced by ss_thread().
| static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
| int | idx | |||
| ) | [static] |
Definition at line 6513 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
06514 { 06515 int j; 06516 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 06517 for (;;) 06518 { 06519 /* set bits of interest */ 06520 j = DAHDI_IOMUX_SIGEVENT; 06521 /* wait for some happening */ 06522 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 06523 /* exit loop if we have it */ 06524 if (j & DAHDI_IOMUX_SIGEVENT) break; 06525 } 06526 /* get the event info */ 06527 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 06528 return 0; 06529 }
| static int dahdi_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 5995 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.
05996 { 05997 struct dahdi_pvt *p = ast->tech_pvt; 05998 int res; 05999 int idx; 06000 idx = dahdi_get_index(ast, p, 0); 06001 if (idx < 0) { 06002 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 06003 return -1; 06004 } 06005 06006 #if 0 06007 #ifdef HAVE_PRI 06008 ast_mutex_lock(&p->lock); 06009 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 06010 if (p->pri->pri) { 06011 if (!pri_grab(p, p->pri)) { 06012 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 06013 pri_rel(p->pri); 06014 } else 06015 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 06016 } 06017 p->proceeding=1; 06018 } 06019 ast_mutex_unlock(&p->lock); 06020 #endif 06021 #endif 06022 /* Write a frame of (presumably voice) data */ 06023 if (frame->frametype != AST_FRAME_VOICE) { 06024 if (frame->frametype != AST_FRAME_IMAGE) 06025 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 06026 return 0; 06027 } 06028 if ((frame->subclass != AST_FORMAT_SLINEAR) && 06029 (frame->subclass != AST_FORMAT_ULAW) && 06030 (frame->subclass != AST_FORMAT_ALAW)) { 06031 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 06032 return -1; 06033 } 06034 if (p->dialing) { 06035 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 06036 return 0; 06037 } 06038 if (!p->owner) { 06039 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 06040 return 0; 06041 } 06042 if (p->cidspill) { 06043 ast_debug(1, "Dropping frame since I've still got a callerid spill\n"); 06044 return 0; 06045 } 06046 /* Return if it's not valid data */ 06047 if (!frame->data.ptr || !frame->datalen) 06048 return 0; 06049 06050 if (frame->subclass == AST_FORMAT_SLINEAR) { 06051 if (!p->subs[idx].linear) { 06052 p->subs[idx].linear = 1; 06053 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06054 if (res) 06055 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 06056 } 06057 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 06058 } else { 06059 /* x-law already */ 06060 if (p->subs[idx].linear) { 06061 p->subs[idx].linear = 0; 06062 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06063 if (res) 06064 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 06065 } 06066 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 06067 } 06068 if (res < 0) { 06069 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 06070 return -1; 06071 } 06072 return 0; 06073 }
| static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3221 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().
03222 { 03223 int x; 03224 struct dahdi_pvt *p, *pl; 03225 03226 while (num_restart_pending) { 03227 usleep(1); 03228 } 03229 03230 ast_mutex_lock(&iflock); 03231 /* Destroy all the interfaces and free their memory */ 03232 p = iflist; 03233 while (p) { 03234 /* Free any callerid */ 03235 if (p->cidspill) 03236 ast_free(p->cidspill); 03237 pl = p; 03238 p = p->next; 03239 x = pl->channel; 03240 /* Free associated memory */ 03241 if (pl) 03242 destroy_dahdi_pvt(&pl); 03243 if (option_verbose > 2) 03244 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03245 } 03246 iflist = NULL; 03247 ifcount = 0; 03248 ast_mutex_unlock(&iflock); 03249 }
Definition at line 3171 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().
03172 { 03173 int owned = 0; 03174 int i = 0; 03175 03176 if (!now) { 03177 if (cur->owner) { 03178 owned = 1; 03179 } 03180 03181 for (i = 0; i < 3; i++) { 03182 if (cur->subs[i].owner) { 03183 owned = 1; 03184 } 03185 } 03186 if (!owned) { 03187 if (prev) { 03188 prev->next = cur->next; 03189 if (prev->next) 03190 prev->next->prev = prev; 03191 else 03192 ifend = prev; 03193 } else { 03194 iflist = cur->next; 03195 if (iflist) 03196 iflist->prev = NULL; 03197 else 03198 ifend = NULL; 03199 } 03200 destroy_dahdi_pvt(&cur); 03201 } 03202 } else { 03203 if (prev) { 03204 prev->next = cur->next; 03205 if (prev->next) 03206 prev->next->prev = prev; 03207 else 03208 ifend = prev; 03209 } else { 03210 iflist = cur->next; 03211 if (iflist) 03212 iflist->prev = NULL; 03213 else 03214 ifend = NULL; 03215 } 03216 destroy_dahdi_pvt(&cur); 03217 } 03218 return 0; 03219 }
| static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3148 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().
03149 { 03150 struct dahdi_pvt *p = *pvt; 03151 /* Remove channel from the list */ 03152 if (p->prev) 03153 p->prev->next = p->next; 03154 if (p->next) 03155 p->next->prev = p->prev; 03156 if (p->use_smdi) 03157 ast_smdi_interface_unref(p->smdi_iface); 03158 if (p->mwi_event_sub) 03159 ast_event_unsubscribe(p->mwi_event_sub); 03160 if (p->vars) { 03161 ast_variables_destroy(p->vars); 03162 } 03163 ast_mutex_destroy(&p->lock); 03164 dahdi_close_sub(p, SUB_REAL); 03165 if (p->owner) 03166 p->owner->tech_pvt = NULL; 03167 free(p); 03168 *pvt = NULL; 03169 }
| static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1745 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
| static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1575 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01576 { 01577 if (isdigit(digit)) 01578 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01579 else if (digit >= 'A' && digit <= 'D') 01580 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01581 else if (digit >= 'a' && digit <= 'd') 01582 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01583 else if (digit == '*') 01584 return DAHDI_TONE_DTMF_s; 01585 else if (digit == '#') 01586 return DAHDI_TONE_DTMF_p; 01587 else 01588 return -1; 01589 }
| static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4118 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().
04119 { 04120 int val; 04121 04122 p->ignoredtmf = 1; 04123 04124 val = 0; 04125 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04126 04127 if (!p->hardwaredtmf && p->dsp) { 04128 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 04129 ast_dsp_set_features(p->dsp, p->dsp_features); 04130 } 04131 }
| static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 10665 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().
10666 { 10667 struct ast_channel *chan = vchan; 10668 struct dahdi_pvt *pvt = chan->tech_pvt; 10669 struct ast_frame *f; 10670 char ex[80]; 10671 /* Wait up to 30 seconds for an answer */ 10672 int newms, ms = 30000; 10673 ast_verb(3, "Initiating idle call on channel %s\n", chan->name); 10674 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 10675 if (ast_call(chan, ex, 0)) { 10676 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 10677 ast_hangup(chan); 10678 return NULL; 10679 } 10680 while ((newms = ast_waitfor(chan, ms)) > 0) { 10681 f = ast_read(chan); 10682 if (!f) { 10683 /* Got hangup */ 10684 break; 10685 } 10686 if (f->frametype == AST_FRAME_CONTROL) { 10687 switch (f->subclass) { 10688 case AST_CONTROL_ANSWER: 10689 /* Launch the PBX */ 10690 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 10691 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 10692 chan->priority = 1; 10693 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 10694 ast_pbx_run(chan); 10695 /* It's already hungup, return immediately */ 10696 return NULL; 10697 case AST_CONTROL_BUSY: 10698 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name); 10699 break; 10700 case AST_CONTROL_CONGESTION: 10701 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name); 10702 break; 10703 }; 10704 } 10705 ast_frfree(f); 10706 ms = newms; 10707 } 10708 /* Hangup the channel since nothing happend */ 10709 ast_hangup(chan); 10710 return NULL; 10711 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 8320 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().
08321 { 08322 int count, res, res2, spoint, pollres=0; 08323 struct dahdi_pvt *i; 08324 struct dahdi_pvt *last = NULL; 08325 struct dahdi_pvt *doomed; 08326 time_t thispass = 0, lastpass = 0; 08327 int found; 08328 char buf[1024]; 08329 struct pollfd *pfds=NULL; 08330 int lastalloc = -1; 08331 /* This thread monitors all the frame relay interfaces which are not yet in use 08332 (and thus do not have a separate thread) indefinitely */ 08333 /* From here on out, we die whenever asked */ 08334 #if 0 08335 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 08336 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 08337 return NULL; 08338 } 08339 ast_debug(1, "Monitor starting...\n"); 08340 #endif 08341 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08342 08343 for (;;) { 08344 /* Lock the interface list */ 08345 ast_mutex_lock(&iflock); 08346 if (!pfds || (lastalloc != ifcount)) { 08347 if (pfds) { 08348 ast_free(pfds); 08349 pfds = NULL; 08350 } 08351 if (ifcount) { 08352 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 08353 ast_mutex_unlock(&iflock); 08354 return NULL; 08355 } 08356 } 08357 lastalloc = ifcount; 08358 } 08359 /* Build the stuff we're going to poll on, that is the socket of every 08360 dahdi_pvt that does not have an associated owner channel */ 08361 count = 0; 08362 i = iflist; 08363 while (i) { 08364 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 08365 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) { 08366 /* This needs to be watched, as it lacks an owner */ 08367 pfds[count].fd = i->subs[SUB_REAL].dfd; 08368 pfds[count].events = POLLPRI; 08369 pfds[count].revents = 0; 08370 /* If we are monitoring for VMWI or sending CID, we need to 08371 read from the channel as well */ 08372 if (i->cidspill || i->mwimonitor_fsk) 08373 pfds[count].events |= POLLIN; 08374 count++; 08375 } 08376 } 08377 i = i->next; 08378 } 08379 /* Okay, now that we know what to do, release the interface lock */ 08380 ast_mutex_unlock(&iflock); 08381 08382 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 08383 pthread_testcancel(); 08384 /* Wait at least a second for something to happen */ 08385 res = poll(pfds, count, 1000); 08386 pthread_testcancel(); 08387 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 08388 08389 /* Okay, poll has finished. Let's see what happened. */ 08390 if (res < 0) { 08391 if ((errno != EAGAIN) && (errno != EINTR)) 08392 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 08393 continue; 08394 } 08395 /* Alright, lock the interface list again, and let's look and see what has 08396 happened */ 08397 ast_mutex_lock(&iflock); 08398 found = 0; 08399 spoint = 0; 08400 lastpass = thispass; 08401 thispass = time(NULL); 08402 i = iflist; 08403 doomed = NULL; 08404 for (i = iflist;; i = i->next) { 08405 if (doomed) { 08406 int res; 08407 res = dahdi_destroy_channel_bynum(doomed->channel); 08408 if (!res) { 08409 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 08410 } 08411 doomed = NULL; 08412 } 08413 if (!i) { 08414 break; 08415 } 08416 08417 if (thispass != lastpass) { 08418 if (!found && ((i == last) || ((i == iflist) && !last))) { 08419 last = i; 08420 if (last) { 08421 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) { 08422 res = has_voicemail(last); 08423 if (last->msgstate != res) { 08424 08425 /* This channel has a new voicemail state, 08426 * initiate a thread to send an MWI message 08427 */ 08428 pthread_attr_t attr; 08429 pthread_t threadid; 08430 struct mwi_thread_data *mtd; 08431 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 08432 if (res2) { 08433 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 08434 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 08435 } 08436 pthread_attr_init(&attr); 08437 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08438 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08439 last->msgstate = res; 08440 mtd->pvt = last; 08441 last->mwisendactive = 1; 08442 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) { 08443 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel); 08444 ast_free(mtd); 08445 last->mwisendactive = 0; 08446 } 08447 } 08448 found ++; 08449 } 08450 } 08451 last = last->next; 08452 } 08453 } 08454 } 08455 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 08456 if (i->radio && !i->owner) 08457 { 08458 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08459 if (res) 08460 { 08461 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 08462 /* Don't hold iflock while handling init events */ 08463 ast_mutex_unlock(&iflock); 08464 doomed = handle_init_event(i, res); 08465 ast_mutex_lock(&iflock); 08466 } 08467 continue; 08468 } 08469 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 08470 if (pollres & POLLIN) { 08471 if (i->owner || i->subs[SUB_REAL].owner) { 08472 #ifdef HAVE_PRI 08473 if (!i->pri) 08474 #endif 08475 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 08476 continue; 08477 } 08478 if (!i->cidspill && !i->mwimonitor_fsk) { 08479 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 08480 continue; 08481 } 08482 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 08483 if (res > 0) { 08484 if (i->mwimonitor_fsk) { 08485 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 08486 pthread_attr_t attr; 08487 pthread_t threadid; 08488 struct mwi_thread_data *mtd; 08489 08490 pthread_attr_init(&attr); 08491 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 08492 08493 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 08494 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 08495 mtd->pvt = i; 08496 memcpy(mtd->buf, buf, res); 08497 mtd->len = res; 08498 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 08499 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 08500 ast_free(mtd); 08501 } 08502 i->mwimonitoractive = 1; 08503 } 08504 } 08505 } 08506 } else { 08507 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 08508 } 08509 } 08510 if (pollres & POLLPRI) { 08511 if (i->owner || i->subs[SUB_REAL].owner) { 08512 #ifdef HAVE_PRI 08513 if (!i->pri) 08514 #endif 08515 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 08516 continue; 08517 } 08518 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 08519 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 08520 /* Don't hold iflock while handling init events */ 08521 ast_mutex_unlock(&iflock); 08522 doomed = handle_init_event(i, res); 08523 ast_mutex_lock(&iflock); 08524 } 08525 } 08526 } 08527 ast_mutex_unlock(&iflock); 08528 } 08529 /* Never reached */ 08530 return NULL; 08531 08532 }
| static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 4133 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().
04134 { 04135 int val; 04136 04137 if (p->channel == CHAN_PSEUDO) 04138 return; 04139 04140 p->ignoredtmf = 0; 04141 04142 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 04143 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 04144 04145 if (!p->hardwaredtmf && p->dsp) { 04146 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 04147 ast_dsp_set_features(p->dsp, p->dsp_features); 04148 } 04149 }
| static char* event2str | ( | int | event | ) | [static] |
Definition at line 1735 of file chan_dahdi.c.
References ARRAY_LEN, and buf.
Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), mwi_thread(), pri_dchannel(), and ss_thread().
| static void fill_rxgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2105 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02106 { 02107 int j; 02108 int k; 02109 float linear_gain = pow(10.0, gain / 20.0); 02110 02111 switch (law) { 02112 case DAHDI_LAW_ALAW: 02113 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02114 if (gain) { 02115 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02116 if (k > 32767) k = 32767; 02117 if (k < -32767) k = -32767; 02118 g->rxgain[j] = AST_LIN2A(k); 02119 } else { 02120 g->rxgain[j] = j; 02121 } 02122 } 02123 break; 02124 case DAHDI_LAW_MULAW: 02125 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02126 if (gain) { 02127 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02128 if (k > 32767) k = 32767; 02129 if (k < -32767) k = -32767; 02130 g->rxgain[j] = AST_LIN2MU(k); 02131 } else { 02132 g->rxgain[j] = j; 02133 } 02134 } 02135 break; 02136 } 02137 }
| static void fill_txgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2071 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02072 { 02073 int j; 02074 int k; 02075 float linear_gain = pow(10.0, gain / 20.0); 02076 02077 switch (law) { 02078 case DAHDI_LAW_ALAW: 02079 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02080 if (gain) { 02081 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02082 if (k > 32767) k = 32767; 02083 if (k < -32767) k = -32767; 02084 g->txgain[j] = AST_LIN2A(k); 02085 } else { 02086 g->txgain[j] = j; 02087 } 02088 } 02089 break; 02090 case DAHDI_LAW_MULAW: 02091 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02092 if (gain) { 02093 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02094 if (k > 32767) k = 32767; 02095 if (k < -32767) k = -32767; 02096 g->txgain[j] = AST_LIN2MU(k); 02097 } else { 02098 g->txgain[j] = j; 02099 } 02100 } 02101 break; 02102 } 02103 }
| static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 13368 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 4577 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().
04578 { 04579 int res; 04580 struct dahdi_spaninfo zi; 04581 struct dahdi_params params; 04582 04583 memset(&zi, 0, sizeof(zi)); 04584 zi.spanno = p->span; 04585 04586 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 04587 if (zi.alarms != DAHDI_ALARM_NONE) 04588 return zi.alarms; 04589 } else { 04590 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 04591 return 0; 04592 } 04593 04594 /* No alarms on the span. Check for channel alarms. */ 04595 memset(¶ms, 0, sizeof(params)); 04596 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 04597 return params.chan_alarms; 04598 04599 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 04600 04601 return DAHDI_ALARM_NONE; 04602 }
| static void handle_alarms | ( | struct dahdi_pvt * | p, | |
| int | alms | |||
| ) | [static] |
Definition at line 4670 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().
04671 { 04672 const char *alarm_str = alarm2str(alms); 04673 04674 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 04675 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 04676 "Alarm: %s\r\n" 04677 "Channel: %d\r\n", 04678 alarm_str, p->channel); 04679 }
| static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12984 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.
12985 { 12986 int i, j; 12987 switch (cmd) { 12988 case CLI_INIT: 12989 e->command = "dahdi show cadences"; 12990 e->usage = 12991 "Usage: dahdi show cadences\n" 12992 " Shows all cadences currently defined\n"; 12993 return NULL; 12994 case CLI_GENERATE: 12995 return NULL; 12996 } 12997 for (i = 0; i < num_cadence; i++) { 12998 char output[1024]; 12999 char tmp[16], tmp2[64]; 13000 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 13001 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 13002 13003 for (j = 0; j < 16; j++) { 13004 if (cadences[i].ringcadence[j] == 0) 13005 break; 13006 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 13007 if (cidrings[i] * 2 - 1 == j) 13008 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 13009 else 13010 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 13011 if (j != 0) 13012 strncat(output, ",", sizeof(output) - strlen(output) - 1); 13013 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 13014 } 13015 ast_cli(a->fd,"%s\n",output); 13016 } 13017 return CLI_SUCCESS; 13018 }
Definition at line 8097 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().
08098 { 08099 int res; 08100 pthread_t threadid; 08101 struct ast_channel *chan; 08102 08103 /* Handle an event on a given channel for the monitor thread. */ 08104 08105 switch (event) { 08106 case DAHDI_EVENT_NONE: 08107 case DAHDI_EVENT_BITSCHANGED: 08108 break; 08109 case DAHDI_EVENT_WINKFLASH: 08110 case DAHDI_EVENT_RINGOFFHOOK: 08111 if (i->inalarm) break; 08112 if (i->radio) break; 08113 /* Got a ring/answer. What kind of channel are we? */ 08114 switch (i->sig) { 08115 case SIG_FXOLS: 08116 case SIG_FXOGS: 08117 case SIG_FXOKS: 08118 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08119 if (res && (errno == EBUSY)) 08120 break; 08121 if (i->cidspill) { 08122 /* Cancel VMWI spill */ 08123 ast_free(i->cidspill); 08124 i->cidspill = NULL; 08125 } 08126 if (i->immediate) { 08127 dahdi_enable_ec(i); 08128 /* The channel is immediately up. Start right away */ 08129 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 08130 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 08131 if (!chan) { 08132 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 08133 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08134 if (res < 0) 08135 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08136 } 08137 } else { 08138 /* Check for callerid, digits, etc */ 08139 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 08140 if (chan) { 08141 if (has_voicemail(i)) 08142 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 08143 else 08144 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 08145 if (res < 0) 08146 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 08147 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08148 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08149 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08150 if (res < 0) 08151 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08152 ast_hangup(chan); 08153 } 08154 } else 08155 ast_log(LOG_WARNING, "Unable to create channel\n"); 08156 } 08157 break; 08158 case SIG_FXSLS: 08159 case SIG_FXSGS: 08160 case SIG_FXSKS: 08161 i->ringt = i->ringt_base; 08162 /* Fall through */ 08163 case SIG_EMWINK: 08164 case SIG_FEATD: 08165 case SIG_FEATDMF: 08166 case SIG_FEATDMF_TA: 08167 case SIG_E911: 08168 case SIG_FGC_CAMA: 08169 case SIG_FGC_CAMAMF: 08170 case SIG_FEATB: 08171 case SIG_EM: 08172 case SIG_EM_E1: 08173 case SIG_SFWINK: 08174 case SIG_SF_FEATD: 08175 case SIG_SF_FEATDMF: 08176 case SIG_SF_FEATB: 08177 case SIG_SF: 08178 /* Check for callerid, digits, etc */ 08179 if (i->cid_start == CID_START_POLARITY_IN) { 08180 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08181 } else { 08182 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 08183 } 08184 08185 if (!chan) { 08186 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08187 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08188 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08189 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08190 if (res < 0) { 08191 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08192 } 08193 ast_hangup(chan); 08194 } 08195 break; 08196 default: 08197 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08198 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08199 if (res < 0) 08200 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 08201 return NULL; 08202 } 08203 break; 08204 case DAHDI_EVENT_NOALARM: 08205 i->inalarm = 0; 08206 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 08207 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08208 "Channel: %d\r\n", i->channel); 08209 break; 08210 case DAHDI_EVENT_ALARM: 08211 i->inalarm = 1; 08212 res = get_alarms(i); 08213 handle_alarms(i, res); 08214 /* fall thru intentionally */ 08215 case DAHDI_EVENT_ONHOOK: 08216 if (i->radio) 08217 break; 08218 /* Back on hook. Hang up. */ 08219 switch (i->sig) { 08220 case SIG_FXOLS: 08221 case SIG_FXOGS: 08222 case SIG_FEATD: 08223 case SIG_FEATDMF: 08224 case SIG_FEATDMF_TA: 08225 case SIG_E911: 08226 case SIG_FGC_CAMA: 08227 case SIG_FGC_CAMAMF: 08228 case SIG_FEATB: 08229 case SIG_EM: 08230 case SIG_EM_E1: 08231 case SIG_EMWINK: 08232 case SIG_SF_FEATD: 08233 case SIG_SF_FEATDMF: 08234 case SIG_SF_FEATB: 08235 case SIG_SF: 08236 case SIG_SFWINK: 08237 case SIG_FXSLS: 08238 case SIG_FXSGS: 08239 case SIG_FXSKS: 08240 case SIG_GR303FXSKS: 08241 dahdi_disable_ec(i); 08242 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08243 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08244 break; 08245 case SIG_GR303FXOKS: 08246 case SIG_FXOKS: 08247 dahdi_disable_ec(i); 08248 /* Diddle the battery for the zhone */ 08249 #ifdef ZHONE_HACK 08250 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08251 usleep(1); 08252 #endif 08253 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08254 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08255 break; 08256 case SIG_PRI: 08257 case SIG_SS7: 08258 case SIG_BRI: 08259 case SIG_BRI_PTMP: 08260 dahdi_disable_ec(i); 08261 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08262 break; 08263 default: 08264 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 08265 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 08266 return NULL; 08267 } 08268 break; 08269 case DAHDI_EVENT_POLARITY: 08270 switch (i->sig) { 08271 case SIG_FXSLS: 08272 case SIG_FXSKS: 08273 case SIG_FXSGS: 08274 /* We have already got a PR before the channel was 08275 created, but it wasn't handled. We need polarity 08276 to be REV for remote hangup detection to work. 08277 At least in Spain */ 08278 if (i->hanguponpolarityswitch) 08279 i->polarity = POLARITY_REV; 08280 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 08281 i->polarity = POLARITY_REV; 08282 ast_verb(2, "Starting post polarity " 08283 "CID detection on channel %d\n", 08284 i->channel); 08285 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 08286 if (!chan) { 08287 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 08288 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08289 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 08290 } 08291 } 08292 break; 08293 default: 08294 ast_log(LOG_WARNING, "handle_init_event detected " 08295 "polarity reversal on non-FXO (SIG_FXS) " 08296 "interface %d\n", i->channel); 08297 } 08298 break; 08299 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 08300 ast_log(LOG_NOTICE, 08301 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 08302 i->channel); 08303 return i; 08304 case DAHDI_EVENT_NEONMWI_ACTIVE: 08305 if (i->mwimonitor_neon) { 08306 notify_message(i->mailbox, 1); 08307 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 08308 } 08309 break; 08310 case DAHDI_EVENT_NEONMWI_INACTIVE: 08311 if (i->mwimonitor_neon) { 08312 notify_message(i->mailbox, 0); 08313 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 08314 } 08315 break; 08316 } 08317 return NULL; 08318 }
| static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12196 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.
12197 { 12198 int span; 12199 int x; 12200 switch (cmd) { 12201 case CLI_INIT: 12202 e->command = "pri debug span"; 12203 e->usage = 12204 "Usage: pri debug span <span>\n" 12205 " Enables debugging on a given PRI span\n"; 12206 return NULL; 12207 case CLI_GENERATE: 12208 return complete_span_4(a->line, a->word, a->pos, a->n); 12209 } 12210 if (a->argc < 4) { 12211 return CLI_SHOWUSAGE; 12212 } 12213 span = atoi(a->argv[3]); 12214 if ((span < 1) || (span > NUM_SPANS)) { 12215 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 12216 return CLI_SUCCESS; 12217 } 12218 if (!pris[span-1].pri) { 12219 ast_cli(a->fd, "No PRI running on span %d\n", span); 12220 return CLI_SUCCESS; 12221 } 12222 for (x = 0; x < NUM_DCHANS; x++) { 12223 if (pris[span-1].dchans[x]) 12224 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12225 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12226 PRI_DEBUG_Q921_STATE); 12227 } 12228 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 12229 return CLI_SUCCESS; 12230 }
| static char* handle_pri_no_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12234 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.
12235 { 12236 int span; 12237 int x; 12238 switch (cmd) { 12239 case CLI_INIT: 12240 e->command = "pri no debug span"; 12241 e->usage = 12242 "Usage: pri no debug span <span>\n" 12243 " Disables debugging on a given PRI span\n"; 12244 return NULL; 12245 case CLI_GENERATE: 12246 return complete_span_5(a->line, a->word, a->pos, a->n); 12247 } 12248 if (a->argc < 5) 12249 return CLI_SHOWUSAGE; 12250 12251 span = atoi(a->argv[4]); 12252 if ((span < 1) || (span > NUM_SPANS)) { 12253 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12254 return CLI_SUCCESS; 12255 } 12256 if (!pris[span-1].pri) { 12257 ast_cli(a->fd, "No PRI running on span %d\n", span); 12258 return CLI_SUCCESS; 12259 } 12260 for (x = 0; x < NUM_DCHANS; x++) { 12261 if (pris[span-1].dchans[x]) 12262 pri_set_debug(pris[span-1].dchans[x], 0); 12263 } 12264 ast_cli(a->fd, "Disabled debugging on span %d\n", span); 12265 return CLI_SUCCESS; 12266 }
| static char* handle_pri_really_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12268 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.
12269 { 12270 int span; 12271 int x; 12272 switch (cmd) { 12273 case CLI_INIT: 12274 e->command = "pri intensive debug span"; 12275 e->usage = 12276 "Usage: pri intensive debug span <span>\n" 12277 " Enables debugging down to the Q.921 level\n"; 12278 return NULL; 12279 case CLI_GENERATE: 12280 return complete_span_5(a->line, a->word, a->pos, a->n); 12281 } 12282 12283 if (a->argc < 5) 12284 return CLI_SHOWUSAGE; 12285 span = atoi(a->argv[4]); 12286 if ((span < 1) || (span > NUM_SPANS)) { 12287 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS); 12288 return CLI_SUCCESS; 12289 } 12290 if (!pris[span-1].pri) { 12291 ast_cli(a->fd, "No PRI running on span %d\n", span); 12292 return CLI_SUCCESS; 12293 } 12294 for (x = 0; x < NUM_DCHANS; x++) { 12295 if (pris[span-1].dchans[x]) 12296 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 12297 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 12298 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 12299 } 12300 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span); 12301 return CLI_SUCCESS; 12302 }
| static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12160 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.
12161 { 12162 int myfd; 12163 switch (cmd) { 12164 case CLI_INIT: 12165 e->command = "pri set debug file"; 12166 e->usage = "Usage: pri set debug file [output-file]\n" 12167 " Sends PRI debug output to the specified output file\n"; 12168 return NULL; 12169 case CLI_GENERATE: 12170 return NULL; 12171 } 12172 if (a->argc < 5) 12173 return CLI_SHOWUSAGE; 12174 12175 if (ast_strlen_zero(a->argv[4])) 12176 return CLI_SHOWUSAGE; 12177 12178 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 12179 if (myfd < 0) { 12180 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 12181 return CLI_SUCCESS; 12182 } 12183 12184 ast_mutex_lock(&pridebugfdlock); 12185 12186 if (pridebugfd >= 0) 12187 close(pridebugfd); 12188 12189 pridebugfd = myfd; 12190 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 12191 ast_mutex_unlock(&pridebugfdlock); 12192 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 12193 return CLI_SUCCESS; 12194 }
| static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12408 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.
12409 { 12410 int x; 12411 int span; 12412 int count=0; 12413 int debug=0; 12414 12415 switch (cmd) { 12416 case CLI_INIT: 12417 e->command = "pri show debug"; 12418 e->usage = 12419 "Usage: pri show debug\n" 12420 " Show the debug state of pri spans\n"; 12421 return NULL; 12422 case CLI_GENERATE: 12423 return NULL; 12424 } 12425 12426 for (span = 0; span < NUM_SPANS; span++) { 12427 if (pris[span].pri) { 12428 for (x = 0; x < NUM_DCHANS; x++) { 12429 debug = 0; 12430 if (pris[span].dchans[x]) { 12431 debug = pri_get_debug(pris[span].dchans[x]); 12432 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" ); 12433 count++; 12434 } 12435 } 12436 } 12437 12438 } 12439 ast_mutex_lock(&pridebugfdlock); 12440 if (pridebugfd >= 0) 12441 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 12442 ast_mutex_unlock(&pridebugfdlock); 12443 12444 if (!count) 12445 ast_cli(a->fd, "No debug set or no PRI running\n"); 12446 return CLI_SUCCESS; 12447 }
| static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12358 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), 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.
12359 { 12360 int span; 12361 int x; 12362 char status[256]; 12363 switch (cmd) { 12364 case CLI_INIT: 12365 e->command = "pri show span"; 12366 e->usage = 12367 "Usage: pri show span <span>\n" 12368 " Displays PRI Information on a given PRI span\n"; 12369 return NULL; 12370 case CLI_GENERATE: 12371 return complete_span_4(a->line, a->word, a->pos, a->n); 12372 } 12373 12374 if (a->argc < 4) 12375 return CLI_SHOWUSAGE; 12376 span = atoi(a->argv[3]); 12377 if ((span < 1) || (span > NUM_SPANS)) { 12378 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 12379 return CLI_SUCCESS; 12380 } 12381 if (!pris[span-1].pri) { 12382 ast_cli(a->fd, "No PRI running on span %d\n", span); 12383 return CLI_SUCCESS; 12384 } 12385 for (x = 0; x < NUM_DCHANS; x++) { 12386 if (pris[span-1].dchannels[x]) { 12387 #ifdef PRI_DUMP_INFO_STR 12388 char *info_str = NULL; 12389 #endif 12390 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 12391 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 12392 ast_cli(a->fd, "Status: %s\n", status); 12393 #ifdef PRI_DUMP_INFO_STR 12394 info_str = pri_dump_info_str(pris[span-1].pri); 12395 if (info_str) { 12396 ast_cli(a->fd, "%s", info_str); 12397 ast_free(info_str); 12398 } 12399 #else 12400 pri_dump_info(pris[span-1].pri); 12401 #endif 12402 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 12403 } 12404 } 12405 return CLI_SUCCESS; 12406 }
| static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12325 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.
12326 { 12327 int span; 12328 int x; 12329 char status[256]; 12330 12331 switch (cmd) { 12332 case CLI_INIT: 12333 e->command = "pri show spans"; 12334 e->usage = 12335 "Usage: pri show spans\n" 12336 " Displays PRI Information\n"; 12337 return NULL; 12338 case CLI_GENERATE: 12339 return NULL; 12340 } 12341 12342 if (a->argc != 3) 12343 return CLI_SHOWUSAGE; 12344 12345 for (span = 0; span < NUM_SPANS; span++) { 12346 if (pris[span].pri) { 12347 for (x = 0; x < NUM_DCHANS; x++) { 12348 if (pris[span].dchannels[x]) { 12349 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 12350 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status); 12351 } 12352 } 12353 } 12354 } 12355 return CLI_SUCCESS; 12356 }
| static char* handle_pri_unset_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12139 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.
12140 { 12141 switch (cmd) { 12142 case CLI_INIT: 12143 e->command = "pri unset debug file"; 12144 e->usage = "Usage: pri unset debug file\n" 12145 " Stop sending debug output to the previously \n" 12146 " specified file\n"; 12147 return NULL; 12148 case CLI_GENERATE: 12149 return NULL; 12150 } 12151 /* Assume it is unset */ 12152 ast_mutex_lock(&pridebugfdlock); 12153 close(pridebugfd); 12154 pridebugfd = -1; 12155 ast_cli(a->fd, "PRI debug output to file disabled\n"); 12156 ast_mutex_unlock(&pridebugfdlock); 12157 return CLI_SUCCESS; 12158 }
| static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 12449 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.
12450 { 12451 switch (cmd) { 12452 case CLI_INIT: 12453 e->command = "pri show version"; 12454 e->usage = 12455 "Usage: pri show version\n" 12456 "Show libpri version information\n"; 12457 return NULL; 12458 case CLI_GENERATE: 12459 return NULL; 12460 } 12461 12462 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 12463 12464 return CLI_SUCCESS; 12465 }
| static char* handle_ss7_block_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13757 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.
13758 { 13759 int linkset, cic; 13760 int blocked = -1, i; 13761 switch (cmd) { 13762 case CLI_INIT: 13763 e->command = "ss7 block cic"; 13764 e->usage = 13765 "Usage: ss7 block cic <linkset> <CIC>\n" 13766 " Sends a remote blocking request for the given CIC on the specified linkset\n"; 13767 return NULL; 13768 case CLI_GENERATE: 13769 return NULL; 13770 } 13771 if (a->argc == 5) 13772 linkset = atoi(a->argv[3]); 13773 else 13774 return CLI_SHOWUSAGE; 13775 13776 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13777 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13778 return CLI_SUCCESS; 13779 } 13780 13781 if (!linksets[linkset-1].ss7) { 13782 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13783 return CLI_SUCCESS; 13784 } 13785 13786 cic = atoi(a->argv[4]); 13787 13788 if (cic < 1) { 13789 ast_cli(a->fd, "Invalid CIC specified!\n"); 13790 return CLI_SUCCESS; 13791 } 13792 13793 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13794 if (linksets[linkset-1].pvts[i]->cic == cic) { 13795 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 13796 if (!blocked) { 13797 ast_mutex_lock(&linksets[linkset-1].lock); 13798 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 13799 ast_mutex_unlock(&linksets[linkset-1].lock); 13800 } 13801 } 13802 } 13803 13804 if (blocked < 0) { 13805 ast_cli(a->fd, "Invalid CIC specified!\n"); 13806 return CLI_SUCCESS; 13807 } 13808 13809 if (!blocked) 13810 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic); 13811 else 13812 ast_cli(a->fd, "CIC %d already locally blocked\n", cic); 13813 13814 /* Break poll on the linkset so it sends our messages */ 13815 pthread_kill(linksets[linkset-1].master, SIGURG); 13816 13817 return CLI_SUCCESS; 13818 }
| static char* handle_ss7_block_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13820 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.
13821 { 13822 int linkset; 13823 int i; 13824 switch (cmd) { 13825 case CLI_INIT: 13826 e->command = "ss7 block linkset"; 13827 e->usage = 13828 "Usage: ss7 block linkset <linkset number>\n" 13829 " Sends a remote blocking request for all CICs on the given linkset\n"; 13830 return NULL; 13831 case CLI_GENERATE: 13832 return NULL; 13833 } 13834 if (a->argc == 4) 13835 linkset = atoi(a->argv[3]); 13836 else 13837 return CLI_SHOWUSAGE; 13838 13839 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13840 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13841 return CLI_SUCCESS; 13842 } 13843 13844 if (!linksets[linkset-1].ss7) { 13845 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13846 return CLI_SUCCESS; 13847 } 13848 13849 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13850 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 13851 ast_mutex_lock(&linksets[linkset-1].lock); 13852 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 13853 ast_mutex_unlock(&linksets[linkset-1].lock); 13854 } 13855 13856 /* Break poll on the linkset so it sends our messages */ 13857 pthread_kill(linksets[linkset-1].master, SIGURG); 13858 13859 return CLI_SUCCESS; 13860 }
| static char* handle_ss7_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13726 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.
13727 { 13728 int span; 13729 switch (cmd) { 13730 case CLI_INIT: 13731 e->command = "ss7 debug linkset"; 13732 e->usage = 13733 "Usage: ss7 debug linkset <linkset>\n" 13734 " Enables debugging on a given SS7 linkset\n"; 13735 return NULL; 13736 case CLI_GENERATE: 13737 return NULL; 13738 } 13739 if (a->argc < 4) 13740 return CLI_SHOWUSAGE; 13741 span = atoi(a->argv[3]); 13742 if ((span < 1) || (span > NUM_SPANS)) { 13743 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 13744 return CLI_SUCCESS; 13745 } 13746 if (!linksets[span-1].ss7) { 13747 ast_cli(a->fd, "No SS7 running on linkset %d\n", span); 13748 return CLI_SUCCESS; 13749 } 13750 if (linksets[span-1].ss7) 13751 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP); 13752 13753 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span); 13754 return CLI_SUCCESS; 13755 }
| static char* handle_ss7_no_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13695 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.
13696 { 13697 int span; 13698 switch (cmd) { 13699 case CLI_INIT: 13700 e->command = "ss7 no debug linkset"; 13701 e->usage = 13702 "Usage: ss7 no debug linkset <span>\n" 13703 " Disables debugging on a given SS7 linkset\n"; 13704 return NULL; 13705 case CLI_GENERATE: 13706 return NULL; 13707 } 13708 if (a->argc < 5) 13709 return CLI_SHOWUSAGE; 13710 span = atoi(a->argv[4]); 13711 if ((span < 1) || (span > NUM_SPANS)) { 13712 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS); 13713 return CLI_SUCCESS; 13714 } 13715 if (!linksets[span-1].ss7) { 13716 ast_cli(a->fd, "No SS7 running on linkset %d\n", span); 13717 return CLI_SUCCESS; 13718 } 13719 if (linksets[span-1].ss7) 13720 ss7_set_debug(linksets[span-1].ss7, 0); 13721 13722 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span); 13723 return CLI_SUCCESS; 13724 }
| static char* handle_ss7_show_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13962 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.
13963 { 13964 int linkset; 13965 struct dahdi_ss7 *ss7; 13966 switch (cmd) { 13967 case CLI_INIT: 13968 e->command = "ss7 show linkset"; 13969 e->usage = 13970 "Usage: ss7 show linkset <span>\n" 13971 " Shows the status of an SS7 linkset.\n"; 13972 return NULL; 13973 case CLI_GENERATE: 13974 return NULL; 13975 } 13976 13977 if (a->argc < 4) 13978 return CLI_SHOWUSAGE; 13979 linkset = atoi(a->argv[3]); 13980 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13981 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13982 return CLI_SUCCESS; 13983 } 13984 if (!linksets[linkset-1].ss7) { 13985 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13986 return CLI_SUCCESS; 13987 } 13988 if (linksets[linkset-1].ss7) 13989 ss7 = &linksets[linkset-1]; 13990 13991 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down"); 13992 13993 return CLI_SUCCESS; 13994 }
| static char* handle_ss7_unblock_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13862 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.
13863 { 13864 int linkset, cic; 13865 int i, blocked = -1; 13866 switch (cmd) { 13867 case CLI_INIT: 13868 e->command = "ss7 unblock cic"; 13869 e->usage = 13870 "Usage: ss7 unblock cic <linkset> <CIC>\n" 13871 " Sends a remote unblocking request for the given CIC on the specified linkset\n"; 13872 return NULL; 13873 case CLI_GENERATE: 13874 return NULL; 13875 } 13876 13877 if (a->argc == 5) 13878 linkset = atoi(a->argv[3]); 13879 else 13880 return CLI_SHOWUSAGE; 13881 13882 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13883 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13884 return CLI_SUCCESS; 13885 } 13886 13887 if (!linksets[linkset-1].ss7) { 13888 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13889 return CLI_SUCCESS; 13890 } 13891 13892 cic = atoi(a->argv[4]); 13893 13894 if (cic < 1) { 13895 ast_cli(a->fd, "Invalid CIC specified!\n"); 13896 return CLI_SUCCESS; 13897 } 13898 13899 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13900 if (linksets[linkset-1].pvts[i]->cic == cic) { 13901 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 13902 if (blocked) { 13903 ast_mutex_lock(&linksets[linkset-1].lock); 13904 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 13905 ast_mutex_unlock(&linksets[linkset-1].lock); 13906 } 13907 } 13908 } 13909 13910 if (blocked > 0) 13911 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic); 13912 13913 /* Break poll on the linkset so it sends our messages */ 13914 pthread_kill(linksets[linkset-1].master, SIGURG); 13915 13916 return CLI_SUCCESS; 13917 }
| static char* handle_ss7_unblock_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13919 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.
13920 { 13921 int linkset; 13922 int i; 13923 switch (cmd) { 13924 case CLI_INIT: 13925 e->command = "ss7 unblock linkset"; 13926 e->usage = 13927 "Usage: ss7 unblock linkset <linkset number>\n" 13928 " Sends a remote unblocking request for all CICs on the specified linkset\n"; 13929 return NULL; 13930 case CLI_GENERATE: 13931 return NULL; 13932 } 13933 13934 if (a->argc == 4) 13935 linkset = atoi(a->argv[3]); 13936 else 13937 return CLI_SHOWUSAGE; 13938 13939 if ((linkset < 1) || (linkset > NUM_SPANS)) { 13940 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 13941 return CLI_SUCCESS; 13942 } 13943 13944 if (!linksets[linkset-1].ss7) { 13945 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 13946 return CLI_SUCCESS; 13947 } 13948 13949 for (i = 0; i < linksets[linkset-1].numchans; i++) { 13950 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 13951 ast_mutex_lock(&linksets[linkset-1].lock); 13952 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 13953 ast_mutex_unlock(&linksets[linkset-1].lock); 13954 } 13955 13956 /* Break poll on the linkset so it sends our messages */ 13957 pthread_kill(linksets[linkset-1].master, SIGURG); 13958 13959 return CLI_SUCCESS; 13960 }
| static char* handle_ss7_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13996 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.
13997 { 13998 switch (cmd) { 13999 case CLI_INIT: 14000 e->command = "ss7 show version"; 14001 e->usage = 14002 "Usage: ss7 show version\n" 14003 " Show the libss7 version\n"; 14004 return NULL; 14005 case CLI_GENERATE: 14006 return NULL; 14007 } 14008 14009 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version()); 14010 14011 return CLI_SUCCESS; 14012 }
| static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2345 of file chan_dahdi.c.
References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), context, dahdi_pvt::mailbox, mailbox, and strsep().
Referenced by dahdi_handle_event(), do_monitor(), handle_init_event(), and mwi_send_thread().
02346 { 02347 int new_msgs; 02348 struct ast_event *event; 02349 char *mailbox, *context; 02350 02351 mailbox = context = ast_strdupa(p->mailbox); 02352 strsep(&context, "@"); 02353 if (ast_strlen_zero(context)) 02354 context = "default"; 02355 02356 event = ast_event_get_cached(AST_EVENT_MWI, 02357 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02358 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02359 AST_EVENT_IE_END); 02360 02361 if (event) { 02362 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 02363 ast_event_destroy(event); 02364 } else 02365 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 02366 02367 return new_msgs; 02368 }
| static int isourconf | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c | |||
| ) | [static] |
Definition at line 1860 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01861 { 01862 /* If they're listening to our channel, they're ours */ 01863 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01864 return 1; 01865 /* If they're a talker on our (allocated) conference, they're ours */ 01866 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01867 return 1; 01868 return 0; 01869 }
Definition at line 1890 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_pvt::law, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by update_conf().
01891 { 01892 int x; 01893 int useslavenative; 01894 struct dahdi_pvt *slave = NULL; 01895 /* Start out optimistic */ 01896 useslavenative = 1; 01897 /* Update conference state in a stateless fashion */ 01898 for (x = 0; x < 3; x++) { 01899 /* Any three-way calling makes slave native mode *definitely* out 01900 of the question */ 01901 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01902 useslavenative = 0; 01903 } 01904 /* If we don't have any 3-way calls, check to see if we have 01905 precisely one slave */ 01906 if (useslavenative) { 01907 for (x = 0; x < MAX_SLAVES; x++) { 01908 if (p->slaves[x]) { 01909 if (slave) { 01910 /* Whoops already have a slave! No 01911 slave native and stop right away */ 01912 slave = NULL; 01913 useslavenative = 0; 01914 break; 01915 } else { 01916 /* We have one slave so far */ 01917 slave = p->slaves[x]; 01918 } 01919 } 01920 } 01921 } 01922 /* If no slave, slave native definitely out */ 01923 if (!slave) 01924 useslavenative = 0; 01925 else if (slave->law != p->law) { 01926 useslavenative = 0; 01927 slave = NULL; 01928 } 01929 if (out) 01930 *out = slave; 01931 return useslavenative; 01932 }
| static int linkset_addsigchan | ( | int | sigchan | ) | [static] |
Definition at line 13574 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().
13575 { 13576 struct dahdi_ss7 *link; 13577 int res; 13578 int curfd; 13579 struct dahdi_params p; 13580 struct dahdi_bufferinfo bi; 13581 struct dahdi_spaninfo si; 13582 13583 13584 link = ss7_resolve_linkset(cur_linkset); 13585 if (!link) { 13586 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 13587 return -1; 13588 } 13589 13590 if (cur_ss7type < 0) { 13591 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n"); 13592 return -1; 13593 } 13594 13595 if (!link->ss7) 13596 link->ss7 = ss7_new(cur_ss7type); 13597 13598 if (!link->ss7) { 13599 ast_log(LOG_ERROR, "Can't create new SS7!\n"); 13600 return -1; 13601 } 13602 13603 link->type = cur_ss7type; 13604 13605 if (cur_pointcode < 0) { 13606 ast_log(LOG_ERROR, "Unspecified pointcode!\n"); 13607 return -1; 13608 } else 13609 ss7_set_pc(link->ss7, cur_pointcode); 13610 13611 if (sigchan < 0) { 13612 ast_log(LOG_ERROR, "Invalid sigchan!\n"); 13613 return -1; 13614 } else { 13615 if (link->numsigchans >= NUM_DCHANS) { 13616 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset); 13617 return -1; 13618 } 13619 curfd = link->numsigchans; 13620 13621 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600); 13622 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) { 13623 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno)); 13624 return -1; 13625 } 13626 memset(&p, 0, sizeof(p)); 13627 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p); 13628 if (res) { 13629 dahdi_close_ss7_fd(link, curfd); 13630 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno)); 13631 return -1; 13632 } 13633 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) { 13634 dahdi_close_ss7_fd(link, curfd); 13635 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan); 13636 return -1; 13637 } 13638 13639 memset(&bi, 0, sizeof(bi)); 13640 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 13641 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 13642 bi.numbufs = 32; 13643 bi.bufsize = 512; 13644 13645 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) { 13646 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno)); 13647 dahdi_close_ss7_fd(link, curfd); 13648 return -1; 13649 } 13650 13651 if (p.sigtype == DAHDI_SIG_MTP2) 13652 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]); 13653 else 13654 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]); 13655 13656 link->numsigchans++; 13657 13658 memset(&si, 0, sizeof(si)); 13659 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si); 13660 if (res) { 13661 dahdi_close_ss7_fd(link, curfd); 13662 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno)); 13663 } 13664 13665 if (!si.alarms) { 13666 link->linkstate[curfd] = LINKSTATE_DOWN; 13667 ss7_link_noalarm(link->ss7, link->fds[curfd]); 13668 } else { 13669 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM; 13670 ss7_link_alarm(link->ss7, link->fds[curfd]); 13671 } 13672 } 13673 13674 if (cur_adjpointcode < 0) { 13675 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n"); 13676 return -1; 13677 } else { 13678 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode); 13679 } 13680 13681 if (cur_defaultdpc < 0) { 13682 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n"); 13683 return -1; 13684 } 13685 13686 if (cur_networkindicator < 0) { 13687 ast_log(LOG_ERROR, "Invalid networkindicator!\n"); 13688 return -1; 13689 } else 13690 ss7_set_network_ind(link->ss7, cur_networkindicator); 13691 13692 return 0; 13693 }
| static int load_module | ( | void | ) | [static] |
Definition at line 15314 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().
15315 { 15316 int res; 15317 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15318 int y, i; 15319 #endif 15320 15321 #ifdef HAVE_PRI 15322 memset(pris, 0, sizeof(pris)); 15323 for (y = 0; y < NUM_SPANS; y++) { 15324 ast_mutex_init(&pris[y].lock); 15325 pris[y].offset = -1; 15326 pris[y].master = AST_PTHREADT_NULL; 15327 for (i = 0; i < NUM_DCHANS; i++) 15328 pris[y].fds[i] = -1; 15329 } 15330 pri_set_error(dahdi_pri_error); 15331 pri_set_message(dahdi_pri_message); 15332 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 15333 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 15334 #endif 15335 #ifdef HAVE_SS7 15336 memset(linksets, 0, sizeof(linksets)); 15337 for (y = 0; y < NUM_SPANS; y++) { 15338 ast_mutex_init(&linksets[y].lock); 15339 linksets[y].master = AST_PTHREADT_NULL; 15340 for (i = 0; i < NUM_DCHANS; i++) 15341 linksets[y].fds[i] = -1; 15342 } 15343 ss7_set_error(dahdi_ss7_error); 15344 ss7_set_message(dahdi_ss7_message); 15345 #endif /* HAVE_SS7 */ 15346 res = setup_dahdi(0); 15347 /* Make sure we can register our DAHDI channel type */ 15348 if (res) 15349 return AST_MODULE_LOAD_DECLINE; 15350 if (ast_channel_register(&dahdi_tech)) { 15351 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 15352 __unload_module(); 15353 return AST_MODULE_LOAD_FAILURE; 15354 } 15355 #ifdef HAVE_PRI 15356 ast_string_field_init(&inuse, 16); 15357 ast_string_field_set(&inuse, name, "GR-303InUse"); 15358 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 15359 #endif 15360 #ifdef HAVE_SS7 15361 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15362 #endif 15363 15364 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 15365 15366 memset(round_robin, 0, sizeof(round_robin)); 15367 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" ); 15368 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" ); 15369 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" ); 15370 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" ); 15371 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" ); 15372 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels"); 15373 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)"); 15374 15375 ast_cond_init(&mwi_thread_complete, NULL); 15376 ast_cond_init(&ss_thread_complete, NULL); 15377 15378 return res; 15379 }
| static struct dahdi_pvt* mkintf | ( | int | channel, | |
| const struct dahdi_chan_conf * | conf, | |||
| struct dahdi_pri * | pri, | |||
| int | reloading | |||
| ) | [static, read] |
Definition at line 8718 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, 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, 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().
08719 { 08720 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 08721 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 08722 char fn[80]; 08723 struct dahdi_bufferinfo bi; 08724 08725 int res; 08726 int span = 0; 08727 int here = 0; 08728 int x; 08729 struct dahdi_pvt **wlist; 08730 struct dahdi_pvt **wend; 08731 struct dahdi_params p; 08732 08733 wlist = &iflist; 08734 wend = &ifend; 08735 08736 #ifdef HAVE_PRI 08737 if (pri) { 08738 wlist = &pri->crvs; 08739 wend = &pri->crvend; 08740 } 08741 #endif 08742 08743 tmp2 = *wlist; 08744 prev = NULL; 08745 08746 while (tmp2) { 08747 if (!tmp2->destroy) { 08748 if (tmp2->channel == channel) { 08749 tmp = tmp2; 08750 here = 1; 08751 break; 08752 } 08753 if (tmp2->channel > channel) { 08754 break; 08755 } 08756 } 08757 prev = tmp2; 08758 tmp2 = tmp2->next; 08759 } 08760 08761 if (!here && reloading != 1) { 08762 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 08763 if (tmp) 08764 free(tmp); 08765 return NULL; 08766 } 08767 ast_mutex_init(&tmp->lock); 08768 ifcount++; 08769 for (x = 0; x < 3; x++) 08770 tmp->subs[x].dfd = -1; 08771 tmp->channel = channel; 08772 tmp->priindication_oob = conf->chan.priindication_oob; 08773 } 08774 08775 if (tmp) { 08776 int chan_sig = conf->chan.sig; 08777 if (!here) { 08778 if ((channel != CHAN_PSEUDO) && !pri) { 08779 int count = 0; 08780 snprintf(fn, sizeof(fn), "%d", channel); 08781 /* Open non-blocking */ 08782 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08783 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 */ 08784 usleep(1); 08785 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 08786 count++; 08787 } 08788 /* Allocate a DAHDI structure */ 08789 if (tmp->subs[SUB_REAL].dfd < 0) { 08790 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); 08791 destroy_dahdi_pvt(&tmp); 08792 return NULL; 08793 } 08794 memset(&p, 0, sizeof(p)); 08795 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08796 if (res < 0) { 08797 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 08798 destroy_dahdi_pvt(&tmp); 08799 return NULL; 08800 } 08801 if (conf->is_sig_auto) 08802 chan_sig = sigtype_to_signalling(p.sigtype); 08803 if (p.sigtype != (chan_sig & 0x3ffff)) { 08804 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)); 08805 destroy_dahdi_pvt(&tmp); 08806 return NULL; 08807 } 08808 tmp->law = p.curlaw; 08809 tmp->span = p.spanno; 08810 span = p.spanno - 1; 08811 } else { 08812 if (channel == CHAN_PSEUDO) 08813 chan_sig = 0; 08814 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 08815 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 08816 return NULL; 08817 } 08818 } 08819 #ifdef HAVE_SS7 08820 if (chan_sig == SIG_SS7) { 08821 struct dahdi_ss7 *ss7; 08822 int clear = 0; 08823 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 08824 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08825 destroy_dahdi_pvt(&tmp); 08826 return NULL; 08827 } 08828 08829 ss7 = ss7_resolve_linkset(cur_linkset); 08830 if (!ss7) { 08831 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 08832 destroy_dahdi_pvt(&tmp); 08833 return NULL; 08834 } 08835 if (cur_cicbeginswith < 0) { 08836 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 08837 destroy_dahdi_pvt(&tmp); 08838 return NULL; 08839 } 08840 08841 tmp->cic = cur_cicbeginswith++; 08842 08843 /* DB: Add CIC's DPC information */ 08844 tmp->dpc = cur_defaultdpc; 08845 08846 tmp->ss7 = ss7; 08847 tmp->ss7call = NULL; 08848 ss7->pvts[ss7->numchans++] = tmp; 08849 08850 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix)); 08851 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix)); 08852 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix)); 08853 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix)); 08854 08855 ss7->called_nai = conf->ss7.called_nai; 08856 ss7->calling_nai = conf->ss7.calling_nai; 08857 } 08858 #endif 08859 #ifdef HAVE_PRI 08860 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 08861 int offset; 08862 int myswitchtype; 08863 int matchesdchan; 08864 int x,y; 08865 offset = 0; 08866 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 08867 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 08868 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 08869 destroy_dahdi_pvt(&tmp); 08870 return NULL; 08871 } 08872 if (span >= NUM_SPANS) { 08873 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 08874 destroy_dahdi_pvt(&tmp); 08875 return NULL; 08876 } else { 08877 struct dahdi_spaninfo si; 08878 si.spanno = 0; 08879 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 08880 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 08881 destroy_dahdi_pvt(&tmp); 08882 return NULL; 08883 } 08884 /* Store the logical span first based upon the real span */ 08885 tmp->logicalspan = pris[span].prilogicalspan; 08886 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 08887 if (span < 0) { 08888 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 08889 destroy_dahdi_pvt(&tmp); 08890 return NULL; 08891 } 08892 if ((chan_sig == SIG_PRI) || 08893 (chan_sig == SIG_BRI) || 08894 (chan_sig == SIG_BRI_PTMP)) 08895 myswitchtype = conf->pri.switchtype; 08896 else 08897 myswitchtype = PRI_SWITCH_GR303_TMC; 08898 /* Make sure this isn't a d-channel */ 08899 matchesdchan=0; 08900 for (x = 0; x < NUM_SPANS; x++) { 08901 for (y = 0; y < NUM_DCHANS; y++) { 08902 if (pris[x].dchannels[y] == tmp->channel) { 08903 matchesdchan = 1; 08904 break; 08905 } 08906 } 08907 } 08908 offset = p.chanpos; 08909 if (!matchesdchan) { 08910 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 08911 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 08912 destroy_dahdi_pvt(&tmp); 08913 return NULL; 08914 } 08915 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 08916 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 08917 destroy_dahdi_pvt(&tmp); 08918 return NULL; 08919 } 08920 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 08921 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 08922 destroy_dahdi_pvt(&tmp); 08923 return NULL; 08924 } 08925 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 08926 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 08927 destroy_dahdi_pvt(&tmp); 08928 return NULL; 08929 } 08930 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 08931 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 08932 destroy_dahdi_pvt(&tmp); 08933 return NULL; 08934 } 08935 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 08936 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 08937 destroy_dahdi_pvt(&tmp); 08938 return NULL; 08939 } 08940 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 08941 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 08942 destroy_dahdi_pvt(&tmp); 08943 return NULL; 08944 } 08945 if (pris[span].numchans >= MAX_CHANNELS) { 08946 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 08947 pris[span].trunkgroup); 08948 destroy_dahdi_pvt(&tmp); 08949 return NULL; 08950 } 08951 08952 pris[span].sig = chan_sig; 08953 pris[span].nodetype = conf->pri.nodetype; 08954 pris[span].switchtype = myswitchtype; 08955 pris[span].nsf = conf->pri.nsf; 08956 pris[span].dialplan = conf->pri.dialplan; 08957 pris[span].localdialplan = conf->pri.localdialplan; 08958 pris[span].pvts[pris[span].numchans++] = tmp; 08959 pris[span].minunused = conf->pri.minunused; 08960 pris[span].minidle = conf->pri.minidle; 08961 pris[span].overlapdial = conf->pri.overlapdial; 08962 #ifdef HAVE_PRI_INBANDDISCONNECT 08963 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 08964 #endif 08965 pris[span].facilityenable = conf->pri.facilityenable; 08966 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 08967 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 08968 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 08969 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 08970 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 08971 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 08972 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 08973 pris[span].resetinterval = conf->pri.resetinterval; 08974 08975 tmp->pri = &pris[span]; 08976 tmp->prioffset = offset; 08977 tmp->call = NULL; 08978 } else { 08979 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 08980 destroy_dahdi_pvt(&tmp); 08981 return NULL; 08982 } 08983 } 08984 } else { 08985 tmp->prioffset = 0; 08986 } 08987 #endif 08988 } else { 08989 chan_sig = tmp->sig; 08990 if (tmp->subs[SUB_REAL].dfd > -1) { 08991 memset(&p, 0, sizeof(p)); 08992 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 08993 } 08994 } 08995 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 08996 switch (chan_sig) { 08997 case SIG_FXSKS: 08998 case SIG_FXSLS: 08999 case SIG_EM: 09000 case SIG_EM_E1: 09001 case SIG_EMWINK: 09002 case SIG_FEATD: 09003 case SIG_FEATDMF: 09004 case SIG_FEATDMF_TA: 09005 case SIG_FEATB: 09006 case SIG_E911: 09007 case SIG_SF: 09008 case SIG_SFWINK: 09009 case SIG_FGC_CAMA: 09010 case SIG_FGC_CAMAMF: 09011 case SIG_SF_FEATD: 09012 case SIG_SF_FEATDMF: 09013 case SIG_SF_FEATB: 09014 p.starttime = 250; 09015 break; 09016 } 09017 09018 if (tmp->radio) { 09019 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 09020 p.channo = channel; 09021 p.rxwinktime = 1; 09022 p.rxflashtime = 1; 09023 p.starttime = 1; 09024 p.debouncetime = 5; 09025 } 09026 if (!tmp->radio) { 09027 p.channo = channel; 09028 /* Override timing settings based on config file */ 09029 if (conf->timing.prewinktime >= 0) 09030 p.prewinktime = conf->timing.prewinktime; 09031 if (conf->timing.preflashtime >= 0) 09032 p.preflashtime = conf->timing.preflashtime; 09033 if (conf->timing.winktime >= 0) 09034 p.winktime = conf->timing.winktime; 09035 if (conf->timing.flashtime >= 0) 09036 p.flashtime = conf->timing.flashtime; 09037 if (conf->timing.starttime >= 0) 09038 p.starttime = conf->timing.starttime; 09039 if (conf->timing.rxwinktime >= 0) 09040 p.rxwinktime = conf->timing.rxwinktime; 09041 if (conf->timing.rxflashtime >= 0) 09042 p.rxflashtime = conf->timing.rxflashtime; 09043 if (conf->timing.debouncetime >= 0) 09044 p.debouncetime = conf->timing.debouncetime; 09045 } 09046 09047 /* dont set parms on a pseudo-channel (or CRV) */ 09048 if (tmp->subs[SUB_REAL].dfd >= 0) 09049 { 09050 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 09051 if (res < 0) { 09052 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 09053 destroy_dahdi_pvt(&tmp); 09054 return NULL; 09055 } 09056 } 09057 #if 1 09058 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 09059 memset(&bi, 0, sizeof(bi)); 09060 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 09061 if (!res) { 09062 bi.txbufpolicy = conf->chan.buf_policy; 09063 bi.rxbufpolicy = conf->chan.buf_policy; 09064 bi.numbufs = conf->chan.buf_no; 09065 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 09066 if (res < 0) { 09067 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 09068 } 09069 } else 09070 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 09071 } 09072 #endif 09073 tmp->immediate = conf->chan.immediate; 09074 tmp->transfertobusy = conf->chan.transfertobusy; 09075 if (chan_sig & __DAHDI_SIG_FXS) { 09076 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 09077 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 09078 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 09079 } 09080 tmp->sig = chan_sig; 09081 tmp->outsigmod = conf->chan.outsigmod; 09082 tmp->ringt_base = ringt_base; 09083 tmp->firstradio = 0; 09084 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 09085 tmp->permcallwaiting = conf->chan.callwaiting; 09086 else 09087 tmp->permcallwaiting = 0; 09088 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 09089 tmp->destroy = 0; 09090 tmp->drings = conf->chan.drings; 09091 09092 /* 10 is a nice default. */ 09093 if (tmp->drings.ringnum[0].range == 0) 09094 tmp->drings.ringnum[0].range = 10; 09095 if (tmp->drings.ringnum[1].range == 0) 09096 tmp->drings.ringnum[1].range = 10; 09097 if (tmp->drings.ringnum[2].range == 0) 09098 tmp->drings.ringnum[2].range = 10; 09099 09100 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 09101 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 09102 tmp->threewaycalling = conf->chan.threewaycalling; 09103 tmp->adsi = conf->chan.adsi; 09104 tmp->use_smdi = conf->chan.use_smdi; 09105 tmp->permhidecallerid = conf->chan.hidecallerid; 09106 tmp->callreturn = conf->chan.callreturn; 09107 tmp->echocancel = conf->chan.echocancel; 09108 tmp->echotraining = conf->chan.echotraining; 09109 tmp->pulse = conf->chan.pulse; 09110 if (tmp->echocancel.head.tap_length) { 09111 tmp->echocanbridged = conf->chan.echocanbridged; 09112 } else { 09113 if (conf->chan.echocanbridged) 09114 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 09115 tmp->echocanbridged = 0; 09116 } 09117 tmp->busydetect = conf->chan.busydetect; 09118 tmp->busycount = conf->chan.busycount; 09119 tmp->busy_tonelength = conf->chan.busy_tonelength; 09120 tmp->busy_quietlength = conf->chan.busy_quietlength; 09121 tmp->callprogress = conf->chan.callprogress; 09122 tmp->cancallforward = conf->chan.cancallforward; 09123 tmp->dtmfrelax = conf->chan.dtmfrelax; 09124 tmp->callwaiting = tmp->permcallwaiting; 09125 tmp->hidecallerid = tmp->permhidecallerid; 09126 tmp->channel = channel; 09127 tmp->stripmsd = conf->chan.stripmsd; 09128 tmp->use_callerid = conf->chan.use_callerid; 09129 tmp->cid_signalling = conf->chan.cid_signalling; 09130 tmp->cid_start = conf->chan.cid_start; 09131 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 09132 tmp->restrictcid = conf->chan.restrictcid; 09133 tmp->use_callingpres = conf->chan.use_callingpres; 09134 tmp->priexclusive = conf->chan.priexclusive; 09135 if (tmp->usedistinctiveringdetection) { 09136 if (!tmp->use_callerid) { 09137 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 09138 tmp->use_callerid = 1; 09139 } 09140 } 09141 09142 if (tmp->cid_signalling == CID_SIG_SMDI) { 09143 if (!tmp->use_smdi) { 09144 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 09145 tmp->use_smdi = 1; 09146 } 09147 } 09148 if (tmp->use_smdi) { 09149 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 09150 if (!(tmp->smdi_iface)) { 09151 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 09152 tmp->use_smdi = 0; 09153 } 09154 } 09155 09156 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 09157 tmp->amaflags = conf->chan.amaflags; 09158 if (!here) { 09159 tmp->confno = -1; 09160 tmp->propconfno = -1; 09161 } 09162 tmp->canpark = conf->chan.canpark; 09163 tmp->transfer = conf->chan.transfer; 09164 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 09165 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 09166 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 09167 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 09168 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 09169 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 09170 tmp->cid_ton = 0; 09171 if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP)) { 09172 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 09173 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 09174 } else { 09175 tmp->cid_num[0] = '\0'; 09176 tmp->cid_name[0] = '\0'; 09177 } 09178 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 09179 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 09180 char *mailbox, *context; 09181 mailbox = context = ast_strdupa(tmp->mailbox); 09182 strsep(&context, "@"); 09183 if (ast_strlen_zero(context)) 09184 context = "default"; 09185 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 09186 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 09187 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 09188 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 09189 AST_EVENT_IE_END); 09190 } 09191 tmp->msgstate = -1; 09192 tmp->group = conf->chan.group; 09193 tmp->callgroup = conf->chan.callgroup; 09194 tmp->pickupgroup= conf->chan.pickupgroup; 09195 if (conf->chan.vars) { 09196 tmp->vars = ast_variable_new(conf->chan.vars->name, conf->chan.vars->value, ""); 09197 } 09198 tmp->cid_rxgain = conf->chan.cid_rxgain; 09199 tmp->rxgain = conf->chan.rxgain; 09200 tmp->txgain = conf->chan.txgain; 09201 tmp->tonezone = conf->chan.tonezone; 09202 tmp->onhooktime = time(NULL); 09203 if (tmp->subs[SUB_REAL].dfd > -1) { 09204 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 09205 if (tmp->dsp) 09206 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 09207 update_conf(tmp); 09208 if (!here) { 09209 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7)) 09210 /* Hang it up to be sure it's good */ 09211 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09212 } 09213 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 09214 #ifdef HAVE_PRI 09215 /* the dchannel is down so put the channel in alarm */ 09216 if (tmp->pri && !pri_is_up(tmp->pri)) 09217 tmp->inalarm = 1; 09218 #endif 09219 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 09220 tmp->inalarm = 1; 09221 handle_alarms(tmp, res); 09222 } 09223 } 09224 09225 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 09226 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 09227 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 09228 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 09229 if (!here) { 09230 tmp->locallyblocked = tmp->remotelyblocked = 0; 09231 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) 09232 tmp->inservice = 0; 09233 else /* We default to in service on protocols that don't have a reset */ 09234 tmp->inservice = 1; 09235 } 09236 } 09237 if (tmp && !here) { 09238 /* nothing on the iflist */ 09239 if (!*wlist) { 09240 *wlist = tmp; 09241 tmp->prev = NULL; 09242 tmp->next = NULL; 09243 *wend = tmp; 09244 } else { 09245 /* at least one member on the iflist */ 09246 struct dahdi_pvt *working = *wlist; 09247 09248 /* check if we maybe have to put it on the begining */ 09249 if (working->channel > tmp->channel) { 09250 tmp->next = *wlist; 09251 tmp->prev = NULL; 09252 (*wlist)->prev = tmp; 09253 *wlist = tmp; 09254 } else { 09255 /* go through all the members and put the member in the right place */ 09256 while (working) { 09257 /* in the middle */ 09258 if (working->next) { 09259 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 09260 tmp->next = working->next; 09261 tmp->prev = working; 09262 working->next->prev = tmp; 09263 working->next = tmp; 09264 break; 09265 } 09266 } else { 09267 /* the last */ 09268 if (working->channel < tmp->channel) { 09269 working->next = tmp; 09270 tmp->next = NULL; 09271 tmp->prev = working; 09272 *wend = tmp; 09273 break; 09274 } 09275 } 09276 working = working->next; 09277 } 09278 } 09279 } 09280 } 09281 return tmp; 09282 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 294 of file chan_dahdi.c.
Referenced by mkintf().
00295 { 00296 /* This module does not handle MWI in an event-based manner. However, it 00297 * subscribes to MWI for each mailbox that is configured so that the core 00298 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00299 * event cache instead of checking the mailbox directly. */ 00300 }
| static void* mwi_send_thread | ( | void * | data | ) | [static] |
Definition at line 7924 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().
07925 { 07926 struct mwi_thread_data *mtd = data; 07927 struct timeval timeout_basis, suspend, now; 07928 int x, i, res; 07929 int num_read; 07930 enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */ 07931 07932 ast_mutex_lock(&mwi_thread_lock); 07933 mwi_thread_count++; 07934 ast_mutex_unlock(&mwi_thread_lock); 07935 07936 /* Determine how this spill is to be sent */ 07937 if(mwisend_rpas) { 07938 mwi_send_state = MWI_SEND_SA; 07939 } 07940 07941 gettimeofday(&timeout_basis, NULL); 07942 07943 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 07944 if (!mtd->pvt->cidspill) { 07945 mtd->pvt->mwisendactive = 0; 07946 ast_free(mtd); 07947 return NULL; 07948 } 07949 x = DAHDI_FLUSH_BOTH; 07950 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07951 x = 3000; 07952 ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07953 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL, 07954 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0); 07955 mtd->pvt->cidpos = 0; 07956 07957 while (MWI_SEND_DONE != mwi_send_state) { 07958 num_read = 0; 07959 gettimeofday(&now, NULL); 07960 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) { 07961 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state); 07962 goto quit; 07963 } 07964 07965 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07966 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07967 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07968 goto quit; 07969 } 07970 07971 if (i & DAHDI_IOMUX_SIGEVENT) { 07972 /* If we get an event, screen out events that we do not act on. 07973 * Otherwise, let handle_init_event determine what is needed 07974 */ 07975 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07976 switch (res) { 07977 case DAHDI_EVENT_RINGEROFF: 07978 if(mwi_send_state == MWI_SEND_SA_WAIT) { 07979 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 07980 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno)); 07981 goto quit; 07982 } 07983 mwi_send_state = MWI_SEND_PAUSE; 07984 gettimeofday(&suspend, NULL); 07985 } 07986 break; 07987 case DAHDI_EVENT_RINGERON: 07988 case DAHDI_EVENT_HOOKCOMPLETE: 07989 break; 07990 default: 07991 /* Got to the default init event handler */ 07992 if (0 < handle_init_event(mtd->pvt, res)) { 07993 /* I've spawned a thread, get out */ 07994 goto quit; 07995 } 07996 break; 07997 } 07998 } else if (i & DAHDI_IOMUX_READ) { 07999 if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 08000 if (errno != ELAST) { 08001 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08002 goto quit; 08003 } 08004 break; 08005 } 08006 } 08007 /* Perform mwi send action */ 08008 switch ( mwi_send_state) { 08009 case MWI_SEND_SA: 08010 /* Send the Ring Pulse Signal Alert */ 08011 res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 08012 if (res) { 08013 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 08014 goto quit; 08015 } 08016 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING); 08017 mwi_send_state = MWI_SEND_SA_WAIT; 08018 break; 08019 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 08020 break; 08021 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 08022 gettimeofday(&now, NULL); 08023 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) { 08024 mwi_send_state = MWI_SEND_SPILL; 08025 } 08026 break; 08027 case MWI_SEND_SPILL: 08028 /* We read some number of bytes. Write an equal amount of data */ 08029 if(0 < num_read) { 08030 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos) 08031 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos; 08032 res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read); 08033 if (res > 0) { 08034 mtd->pvt->cidpos += res; 08035 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) { 08036 ast_free(mtd->pvt->cidspill); 08037 mtd->pvt->cidspill = NULL; 08038 mtd->pvt->cidpos = 0; 08039 mtd->pvt->cidlen = 0; 08040 mwi_send_state = MWI_SEND_CLEANUP; 08041 } 08042 } else { 08043 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno)); 08044 goto quit; 08045 } 08046 } 08047 break; 08048 case MWI_SEND_CLEANUP: 08049 /* For now, do nothing */ 08050 mwi_send_state = MWI_SEND_DONE; 08051 break; 08052 default: 08053 /* Should not get here, punt*/ 08054 goto quit; 08055 break; 08056 } 08057 } 08058 08059 quit: 08060 if(mtd->pvt->cidspill) { 08061 ast_free(mtd->pvt->cidspill); 08062 mtd->pvt->cidspill = NULL; 08063 } 08064 mtd->pvt->mwisendactive = 0; 08065 ast_free(mtd); 08066 08067 ast_mutex_lock(&mwi_thread_lock); 08068 mwi_thread_count--; 08069 ast_cond_signal(&mwi_thread_complete); 08070 ast_mutex_unlock(&mwi_thread_lock); 08071 08072 return NULL; 08073 }
| static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 7781 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().
07782 { 07783 struct mwi_thread_data *mtd = data; 07784 struct callerid_state *cs; 07785 pthread_t threadid; 07786 int samples = 0; 07787 char *name, *number; 07788 int flags; 07789 int i, res; 07790 unsigned int spill_done = 0; 07791 int spill_result = -1; 07792 07793 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 07794 mtd->pvt->mwimonitoractive = 0; 07795 07796 return NULL; 07797 } 07798 07799 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 07800 07801 bump_gains(mtd->pvt); 07802 07803 for (;;) { 07804 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07805 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 07806 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07807 goto quit; 07808 } 07809 07810 if (i & DAHDI_IOMUX_SIGEVENT) { 07811 struct ast_channel *chan; 07812 07813 /* If we get an event, screen out events that we do not act on. 07814 * Otherwise, cancel and go to the simple switch to let it deal with it. 07815 */ 07816 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 07817 07818 switch (res) { 07819 case DAHDI_EVENT_NEONMWI_ACTIVE: 07820 case DAHDI_EVENT_NEONMWI_INACTIVE: 07821 case DAHDI_EVENT_NONE: 07822 case DAHDI_EVENT_BITSCHANGED: 07823 break; 07824 case DAHDI_EVENT_NOALARM: 07825 mtd->pvt->inalarm = 0; 07826 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); 07827 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 07828 "Channel: %d\r\n", mtd->pvt->channel); 07829 break; 07830 case DAHDI_EVENT_ALARM: 07831 mtd->pvt->inalarm = 1; 07832 res = get_alarms(mtd->pvt); 07833 handle_alarms(mtd->pvt, res); 07834 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 07835 default: 07836 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res)); 07837 callerid_free(cs); 07838 07839 restore_gains(mtd->pvt); 07840 mtd->pvt->ringt = mtd->pvt->ringt_base; 07841 07842 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) { 07843 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 07844 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 07845 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 07846 if (res < 0) 07847 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 07848 ast_hangup(chan); 07849 goto quit; 07850 } 07851 goto quit_no_clean; 07852 07853 } else { 07854 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 07855 } 07856 } 07857 } else if (i & DAHDI_IOMUX_READ) { 07858 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 07859 if (errno != ELAST) { 07860 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07861 goto quit; 07862 } 07863 break; 07864 } 07865 samples += res; 07866 if (!spill_done) { 07867 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 07868 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07869 break; 07870 } else if (spill_result) { 07871 spill_done = 1; 07872 } 07873 } else { 07874 /* keep reading data until the energy level drops below the threshold 07875 so we don't get another 'trigger' on the remaining carrier signal 07876 */ 07877 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 07878 break; 07879 } 07880 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 07881 break; 07882 } 07883 } 07884 07885 if (spill_result == 1) { 07886 callerid_get(cs, &name, &number, &flags); 07887 if (flags & CID_MSGWAITING) { 07888 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 07889 notify_message(mtd->pvt->mailbox, 1); 07890 } else if (flags & CID_NOMSGWAITING) { 07891 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 07892 notify_message(mtd->pvt->mailbox, 0); 07893 } else { 07894 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 07895 } 07896 } 07897 07898 07899 quit: 07900 callerid_free(cs); 07901 07902 restore_gains(mtd->pvt); 07903 07904 quit_no_clean: 07905 mtd->pvt->mwimonitoractive = 0; 07906 07907 ast_free(mtd); 07908 07909 return NULL; 07910 }
| static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
| unsigned char * | buf, | |||
| int | len, | |||
| int | idx, | |||
| int | linear | |||
| ) | [static] |
Definition at line 5973 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().
05974 { 05975 int sent=0; 05976 int size; 05977 int res; 05978 int fd; 05979 fd = p->subs[idx].dfd; 05980 while (len) { 05981 size = len; 05982 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05983 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05984 res = write(fd, buf, size); 05985 if (res != size) { 05986 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05987 return sent; 05988 } 05989 len -= size; 05990 buf += size; 05991 } 05992 return sent; 05993 }
| static int my_getsigstr | ( | struct ast_channel * | chan, | |
| char * | str, | |||
| const char * | term, | |||
| int | ms | |||
| ) | [static] |
Definition at line 6494 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
06495 { 06496 char c; 06497 06498 *str = 0; /* start with empty output buffer */ 06499 for (;;) 06500 { 06501 /* Wait for the first digit (up to specified ms). */ 06502 c = ast_waitfordigit(chan, ms); 06503 /* if timeout, hangup or error, return as such */ 06504 if (c < 1) 06505 return c; 06506 *str++ = c; 06507 *str = 0; 06508 if (strchr(term, c)) 06509 return 1; 06510 } 06511 }
| static void notify_message | ( | char * | mailbox_full, | |
| int | thereornot | |||
| ) | [static] |
Send MWI state change.
This function does two things:
1) It generates an internal Asterisk event notifying any other module that cares about MWI that the state of a mailbox has changed.
2) It runs the script specified by the mwimonitornotify option to allow some custom handling of the state change.
Definition at line 2284 of file chan_dahdi.c.
References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_safe_system(), ast_strdupa, ast_strlen_zero(), context, mailbox, s, and strsep().
Referenced by handle_init_event(), mwi_thread(), and ss_thread().
02285 { 02286 char s[sizeof(mwimonitornotify) + 80]; 02287 struct ast_event *event; 02288 char *mailbox, *context; 02289 02290 /* Strip off @default */ 02291 context = mailbox = ast_strdupa(mailbox_full); 02292 strsep(&context, "@"); 02293 if (ast_strlen_zero(context)) 02294 context = "default"; 02295 02296 if (!(event = ast_event_new(AST_EVENT_MWI, 02297 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02298 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02299 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02300 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02301 AST_EVENT_IE_END))) { 02302 return; 02303 } 02304 02305 ast_event_queue_and_cache(event); 02306 02307 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 02308 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 02309 ast_safe_system(s); 02310 } 02311 }
| static unsigned int parse_pointcode | ( | const char * | pcstring | ) | [static] |
Definition at line 8685 of file chan_dahdi.c.
Referenced by process_dahdi().
| static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3340 of file chan_dahdi.c.
References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, and dahdi_pri::pri.
Referenced by pri_find_principle().
03341 { 03342 int x = -1; 03343 03344 for (x = 0; x < NUM_DCHANS; x++) { 03345 if ((pri->dchans[x] == pri->pri)) 03346 break; 03347 } 03348 03349 return pri->fds[x]; 03350 }
| static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
| struct dahdi_pri * | pri, | |||
| struct dahdi_pvt * | bearer | |||
| ) | [static] |
Definition at line 3310 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().
03311 { 03312 bearer->owner = &inuse; 03313 bearer->realcall = crv; 03314 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 03315 if (crv->subs[SUB_REAL].owner) 03316 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd); 03317 crv->bearer = bearer; 03318 crv->call = bearer->call; 03319 crv->pri = pri; 03320 return 0; 03321 }
| static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 10794 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().
10795 { 10796 do { 10797 pri->resetpos++; 10798 } while ((pri->resetpos < pri->numchans) && 10799 (!pri->pvts[pri->resetpos] || 10800 pri->pvts[pri->resetpos]->call || 10801 pri->pvts[pri->resetpos]->resetting)); 10802 if (pri->resetpos < pri->numchans) { 10803 /* Mark the channel as resetting and restart it */ 10804 pri->pvts[pri->resetpos]->resetting = 1; 10805 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 10806 } else { 10807 pri->resetting = 0; 10808 time(&pri->lastreset); 10809 } 10810 return 0; 10811 }
| static int pri_create_spanmap | ( | int | span, | |
| int | trunkgroup, | |||
| int | logicalspan | |||
| ) | [static] |
Definition at line 8670 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
08671 { 08672 if (pris[span].mastertrunkgroup) { 08673 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); 08674 return -1; 08675 } 08676 pris[span].mastertrunkgroup = trunkgroup; 08677 pris[span].prilogicalspan = logicalspan; 08678 return 0; 08679 }
| static int pri_create_trunkgroup | ( | int | trunkgroup, | |
| int * | channels | |||
| ) | [static] |
Definition at line 8607 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().
08608 { 08609 struct dahdi_spaninfo si; 08610 struct dahdi_params p; 08611 int fd; 08612 int span; 08613 int ospan=0; 08614 int x,y; 08615 for (x = 0; x < NUM_SPANS; x++) { 08616 if (pris[x].trunkgroup == trunkgroup) { 08617 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 08618 return -1; 08619 } 08620 } 08621 for (y = 0; y < NUM_DCHANS; y++) { 08622 if (!channels[y]) 08623 break; 08624 memset(&si, 0, sizeof(si)); 08625 memset(&p, 0, sizeof(p)); 08626 fd = open("/dev/dahdi/channel", O_RDWR); 08627 if (fd < 0) { 08628 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 08629 return -1; 08630 } 08631 x = channels[y]; 08632 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 08633 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 08634 close(fd); 08635 return -1; 08636 } 08637 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 08638 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 08639 return -1; 08640 } 08641 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 08642 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 08643 close(fd); 08644 return -1; 08645 } 08646 span = p.spanno - 1; 08647 if (pris[span].trunkgroup) { 08648 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 08649 close(fd); 08650 return -1; 08651 } 08652 if (pris[span].pvts[0]) { 08653 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 08654 close(fd); 08655 return -1; 08656 } 08657 if (!y) { 08658 pris[span].trunkgroup = trunkgroup; 08659 pris[span].offset = channels[y] - p.chanpos; 08660 ospan = span; 08661 } 08662 pris[ospan].dchannels[y] = channels[y]; 08663 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 08664 pris[span].span = span + 1; 08665 close(fd); 08666 } 08667 return 0; 08668 }
| static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 10888 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().
10889 { 10890 struct dahdi_pri *pri = vpri; 10891 pri_event *e; 10892 struct pollfd fds[NUM_DCHANS]; 10893 int res; 10894 int chanpos = 0; 10895 int x; 10896 int haveidles; 10897 int activeidles; 10898 int nextidle = -1; 10899 struct ast_channel *c; 10900 struct timeval tv, lowest, *next; 10901 struct timeval lastidle = ast_tvnow(); 10902 int doidling=0; 10903 char *cc; 10904 char idlen[80]; 10905 struct ast_channel *idle; 10906 pthread_t p; 10907 time_t t; 10908 int i, which=-1; 10909 int numdchans; 10910 int cause=0; 10911 struct dahdi_pvt *crv; 10912 pthread_t threadid; 10913 char ani2str[6]; 10914 char plancallingnum[256]; 10915 char plancallingani[256]; 10916 char calledtonstr[10]; 10917 10918 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 10919 10920 gettimeofday(&lastidle, NULL); 10921 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 10922 /* Need to do idle dialing, check to be sure though */ 10923 cc = strchr(pri->idleext, '@'); 10924 if (cc) { 10925 *cc = '\0'; 10926 cc++; 10927 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 10928 #if 0 10929 /* Extensions may not be loaded yet */ 10930 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 10931 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 10932 else 10933 #endif 10934 doidling = 1; 10935 } else 10936 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 10937 } 10938 for (;;) { 10939 for (i = 0; i < NUM_DCHANS; i++) { 10940 if (!pri->dchannels[i]) 10941 break; 10942 fds[i].fd = pri->fds[i]; 10943 fds[i].events = POLLIN | POLLPRI; 10944 fds[i].revents = 0; 10945 } 10946 numdchans = i; 10947 time(&t); 10948 ast_mutex_lock(&pri->lock); 10949 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) { 10950 if (pri->resetting && pri_is_up(pri)) { 10951 if (pri->resetpos < 0) 10952 pri_check_restart(pri); 10953 } else { 10954 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 10955 pri->resetting = 1; 10956 pri->resetpos = -1; 10957 } 10958 } 10959 } 10960 /* Look for any idle channels if appropriate */ 10961 if (doidling && pri_is_up(pri)) { 10962 nextidle = -1; 10963 haveidles = 0; 10964 activeidles = 0; 10965 for (x = pri->numchans; x >= 0; x--) { 10966 if (pri->pvts[x] && !pri->pvts[x]->owner && 10967 !pri->pvts[x]->call) { 10968 if (haveidles < pri->minunused) { 10969 haveidles++; 10970 } else if (!pri->pvts[x]->resetting) { 10971 nextidle = x; 10972 break; 10973 } 10974 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 10975 activeidles++; 10976 } 10977 if (nextidle > -1) { 10978 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 10979 /* Don't create a new idle call more than once per second */ 10980 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 10981 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause); 10982 if (idle) { 10983 pri->pvts[nextidle]->isidlecall = 1; 10984 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 10985 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 10986 dahdi_hangup(idle); 10987 } 10988 } else 10989 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 10990 lastidle = ast_tvnow(); 10991 } 10992 } else if ((haveidles < pri->minunused) && 10993 (activeidles > pri->minidle)) { 10994 /* Mark something for hangup if there is something 10995 that can be hungup */ 10996 for (x = pri->numchans; x >= 0; x--) { 10997 /* find a candidate channel */ 10998 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 10999 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11000 haveidles++; 11001 /* Stop if we have enough idle channels or 11002 can't spare any more active idle ones */ 11003 if ((haveidles >= pri->minunused) || 11004 (activeidles <= pri->minidle)) 11005 break; 11006 } 11007 } 11008 } 11009 } 11010 /* Start with reasonable max */ 11011 lowest = ast_tv(60, 0); 11012 for (i = 0; i < NUM_DCHANS; i++) { 11013 /* Find lowest available d-channel */ 11014 if (!pri->dchannels[i]) 11015 break; 11016 if ((next = pri_schedule_next(pri->dchans[i]))) { 11017 /* We need relative time here */ 11018 tv = ast_tvsub(*next, ast_tvnow()); 11019 if (tv.tv_sec < 0) { 11020 tv = ast_tv(0,0); 11021 } 11022 if (doidling || pri->resetting) { 11023 if (tv.tv_sec > 1) { 11024 tv = ast_tv(1, 0); 11025 } 11026 } else { 11027 if (tv.tv_sec > 60) { 11028 tv = ast_tv(60, 0); 11029 } 11030 } 11031 } else if (doidling || pri->resetting) { 11032 /* Make sure we stop at least once per second if we're 11033 monitoring idle channels */ 11034 tv = ast_tv(1,0); 11035 } else { 11036 /* Don't poll for more than 60 seconds */ 11037 tv = ast_tv(60, 0); 11038 } 11039 if (!i || ast_tvcmp(tv, lowest) < 0) { 11040 lowest = tv; 11041 } 11042 } 11043 ast_mutex_unlock(&pri->lock); 11044 11045 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 11046 pthread_testcancel(); 11047 e = NULL; 11048 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 11049 pthread_testcancel(); 11050 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 11051 11052 ast_mutex_lock(&pri->lock); 11053 if (!res) { 11054 for (which = 0; which < NUM_DCHANS; which++) { 11055 if (!pri->dchans[which]) 11056 break; 11057 /* Just a timeout, run the scheduler */ 11058 e = pri_schedule_run(pri->dchans[which]); 11059 if (e) 11060 break; 11061 } 11062 } else if (res > -1) { 11063 for (which = 0; which < NUM_DCHANS; which++) { 11064 if (!pri->dchans[which]) 11065 break; 11066 if (fds[which].revents & POLLPRI) { 11067 /* Check for an event */ 11068 x = 0; 11069 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 11070 if (x) { 11071 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); 11072 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent", 11073 "PRIEvent: %s\r\n" 11074 "PRIEventCode: %d\r\n" 11075 "D-channel: %s\r\n" 11076 "Span: %d\r\n", 11077 event2str(x), 11078 x, 11079 pri_order(which), 11080 pri->span 11081 ); 11082 } 11083 /* Keep track of alarm state */ 11084 if (x == DAHDI_EVENT_ALARM) { 11085 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 11086 pri_find_dchan(pri); 11087 } else if (x == DAHDI_EVENT_NOALARM) { 11088 pri->dchanavail[which] |= DCHAN_NOTINALARM; 11089 pri_restart(pri->dchans[which]); 11090 } 11091 11092 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 11093 } else if (fds[which].revents & POLLIN) { 11094 e = pri_check_event(pri->dchans[which]); 11095 } 11096 if (e) 11097 break; 11098 } 11099 } else if (errno != EINTR) 11100 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 11101 11102 if (e) { 11103 if (pri->debug) 11104 pri_dump_event(pri->dchans[which], e); 11105 11106 if (e->e != PRI_EVENT_DCHAN_DOWN) { 11107 if (!(pri->dchanavail[which] & DCHAN_UP)) { 11108 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span); 11109 } 11110 pri->dchanavail[which] |= DCHAN_UP; 11111 } else if (pri->sig != SIG_BRI_PTMP) { 11112 if (pri->dchanavail[which] & DCHAN_UP) { 11113 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span); 11114 } 11115 pri->dchanavail[which] &= ~DCHAN_UP; 11116 } 11117 11118 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 11119 /* Must be an NFAS group that has the secondary dchan active */ 11120 pri->pri = pri->dchans[which]; 11121 11122 switch (e->e) { 11123 case PRI_EVENT_DCHAN_UP: 11124 if (!pri->pri) pri_find_dchan(pri); 11125 11126 /* Note presense of D-channel */ 11127 time(&pri->lastreset); 11128 11129 /* Restart in 5 seconds */ 11130 if (pri->resetinterval > -1) { 11131 pri->lastreset -= pri->resetinterval; 11132 pri->lastreset += 5; 11133 } 11134 pri->resetting = 0; 11135 /* Take the channels from inalarm condition */ 11136 for (i = 0; i < pri->numchans; i++) 11137 if (pri->pvts[i]) { 11138 pri->pvts[i]->inalarm = 0; 11139 } 11140 break; 11141 case PRI_EVENT_DCHAN_DOWN: 11142 pri_find_dchan(pri); 11143 if (!pri_is_up(pri)) { 11144 pri->resetting = 0; 11145 /* Hangup active channels and put them in alarm mode */ 11146 for (i = 0; i < pri->numchans; i++) { 11147 struct dahdi_pvt *p = pri->pvts[i]; 11148 if (p) { 11149 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 11150 /* T309 is not enabled : hangup calls when alarm occurs */ 11151 if (p->call) { 11152 if (p->pri && p->pri->pri) { 11153 pri_hangup(p->pri->pri, p->call, -1); 11154 pri_destroycall(p->pri->pri, p->call); 11155 p->call = NULL; 11156 } else 11157 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 11158 } 11159 if (p->realcall) { 11160 pri_hangup_all(p->realcall, pri); 11161 } else if (p->owner) 11162 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11163 } 11164 p->inalarm = 1; 11165 } 11166 } 11167 } 11168 break; 11169 case PRI_EVENT_RESTART: 11170 if (e->restart.channel > -1) { 11171 chanpos = pri_find_principle(pri, e->restart.channel); 11172 if (chanpos < 0) 11173 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 11174 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11175 else { 11176 ast_verb(3, "B-channel %d/%d restarted on span %d\n", 11177 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 11178 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11179 if (pri->pvts[chanpos]->call) { 11180 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 11181 pri->pvts[chanpos]->call = NULL; 11182 } 11183 /* Force soft hangup if appropriate */ 11184 if (pri->pvts[chanpos]->realcall) 11185 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11186 else if (pri->pvts[chanpos]->owner) 11187 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11188 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11189 } 11190 } else { 11191 ast_verb(3, "Restart on requested on entire span %d\n", pri->span); 11192 for (x = 0; x < pri->numchans; x++) 11193 if (pri->pvts[x]) { 11194 ast_mutex_lock(&pri->pvts[x]->lock); 11195 if (pri->pvts[x]->call) { 11196 pri_destroycall(pri->pri, pri->pvts[x]->call); 11197 pri->pvts[x]->call = NULL; 11198 } 11199 if (pri->pvts[x]->realcall) 11200 pri_hangup_all(pri->pvts[x]->realcall, pri); 11201 else if (pri->pvts[x]->owner) 11202 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11203 ast_mutex_unlock(&pri->pvts[x]->lock); 11204 } 11205 } 11206 break; 11207 case PRI_EVENT_KEYPAD_DIGIT: 11208 chanpos = pri_find_principle(pri, e->digit.channel); 11209 if (chanpos < 0) { 11210 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 11211 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 11212 } else { 11213 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 11214 if (chanpos > -1) { 11215 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11216 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 11217 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 11218 /* how to do that */ 11219 int digitlen = strlen(e->digit.digits); 11220 char digit; 11221 int i; 11222 for (i = 0; i < digitlen; i++) { 11223 digit = e->digit.digits[i]; 11224 { 11225 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11226 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11227 } 11228 } 11229 } 11230 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11231 } 11232 } 11233 break; 11234 11235 case PRI_EVENT_INFO_RECEIVED: 11236 chanpos = pri_find_principle(pri, e->ring.channel); 11237 if (chanpos < 0) { 11238 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 11239 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11240 } else { 11241 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 11242 if (chanpos > -1) { 11243 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11244 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 11245 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 11246 /* how to do that */ 11247 int digitlen = strlen(e->ring.callednum); 11248 char digit; 11249 int i; 11250 for (i = 0; i < digitlen; i++) { 11251 digit = e->ring.callednum[i]; 11252 { 11253 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 11254 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11255 } 11256 } 11257 } 11258 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11259 } 11260 } 11261 break; 11262 case PRI_EVENT_RING: 11263 crv = NULL; 11264 if (e->ring.channel == -1) 11265 chanpos = pri_find_empty_chan(pri, 1); 11266 else 11267 chanpos = pri_find_principle(pri, e->ring.channel); 11268 /* if no channel specified find one empty */ 11269 if (chanpos < 0) { 11270 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 11271 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11272 } else { 11273 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11274 if (pri->pvts[chanpos]->owner) { 11275 if (pri->pvts[chanpos]->call == e->ring.call) { 11276 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 11277 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11278 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11279 break; 11280 } else { 11281 /* This is where we handle initial glare */ 11282 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n", 11283 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 11284 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11285 chanpos = -1; 11286 } 11287 } 11288 if (chanpos > -1) 11289 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11290 } 11291 if ((chanpos < 0) && (e->ring.flexible)) 11292 chanpos = pri_find_empty_chan(pri, 1); 11293 if (chanpos > -1) { 11294 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11295 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 11296 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 11297 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 11298 if (crv) 11299 ast_mutex_lock(&crv->lock); 11300 if (!crv || crv->owner) { 11301 pri->pvts[chanpos]->call = NULL; 11302 if (crv) { 11303 if (crv->owner) 11304 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11305 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); 11306 } else 11307 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); 11308 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 11309 if (crv) 11310 ast_mutex_unlock(&crv->lock); 11311 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11312 break; 11313 } 11314 } 11315 pri->pvts[chanpos]->call = e->ring.call; 11316 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 11317 if (pri->pvts[chanpos]->use_callerid) { 11318 ast_shrink_phone_number(plancallingnum); 11319 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 11320 #ifdef PRI_ANI 11321 if (!ast_strlen_zero(e->ring.callingani)) { 11322 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 11323 ast_shrink_phone_number(plancallingani); 11324 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 11325 } else { 11326 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11327 } 11328 #endif 11329 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 11330 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 11331 } else { 11332 pri->pvts[chanpos]->cid_num[0] = '\0'; 11333 pri->pvts[chanpos]->cid_ani[0] = '\0'; 11334 pri->pvts[chanpos]->cid_name[0] = '\0'; 11335 pri->pvts[chanpos]->cid_ton = 0; 11336 } 11337 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 11338 e->ring.redirectingnum, e->ring.callingplanrdnis); 11339 /* If immediate=yes go to s|1 */ 11340 if (pri->pvts[chanpos]->immediate) { 11341 ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); 11342 pri->pvts[chanpos]->exten[0] = 's'; 11343 pri->pvts[chanpos]->exten[1] = '\0'; 11344 } 11345 /* Get called number */ 11346 else if (!ast_strlen_zero(e->ring.callednum)) { 11347 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 11348 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11349 } else if (pri->overlapdial) 11350 pri->pvts[chanpos]->exten[0] = '\0'; 11351 else { 11352 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 11353 pri->pvts[chanpos]->exten[0] = 's'; 11354 pri->pvts[chanpos]->exten[1] = '\0'; 11355 } 11356 /* Set DNID on all incoming calls -- even immediate */ 11357 if (!ast_strlen_zero(e->ring.callednum)) 11358 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 11359 /* No number yet, but received "sending complete"? */ 11360 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 11361 ast_verb(3, "Going to extension s|1 because of Complete received\n"); 11362 pri->pvts[chanpos]->exten[0] = 's'; 11363 pri->pvts[chanpos]->exten[1] = '\0'; 11364 } 11365 11366 /* Make sure extension exists (or in overlap dial mode, can exist) */ 11367 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 11368 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11369 /* Setup law */ 11370 int law; 11371 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 11372 /* Set to audio mode at this point */ 11373 law = 1; 11374 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11375 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 11376 } 11377 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 11378 law = DAHDI_LAW_ALAW; 11379 else 11380 law = DAHDI_LAW_MULAW; 11381 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 11382 if (res < 0) 11383 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 11384 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 11385 if (res < 0) 11386 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 11387 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 11388 /* Just announce proceeding */ 11389 pri->pvts[chanpos]->proceeding = 1; 11390 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 11391 } else { 11392 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 11393 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11394 else 11395 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 11396 } 11397 /* Get the use_callingpres state */ 11398 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 11399 11400 /* Start PBX */ 11401 if (!e->ring.complete 11402 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 11403 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 11404 /* 11405 * Release the PRI lock while we create the channel 11406 * so other threads can send D channel messages. 11407 */ 11408 ast_mutex_unlock(&pri->lock); 11409 if (crv) { 11410 /* Set bearer and such */ 11411 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 11412 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11413 pri->pvts[chanpos]->owner = &inuse; 11414 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 11415 } else { 11416 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 11417 } 11418 ast_mutex_lock(&pri->lock); 11419 if (c) { 11420 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11421 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11422 } 11423 if (e->ring.ani2 >= 0) { 11424 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11425 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11426 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11427 } 11428 11429 #ifdef SUPPORT_USERUSER 11430 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11431 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11432 } 11433 #endif 11434 11435 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11436 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11437 if (e->ring.redirectingreason >= 0) 11438 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11439 } 11440 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) { 11441 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 11442 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 11443 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11444 } else { 11445 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11446 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11447 if (c) 11448 ast_hangup(c); 11449 else { 11450 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11451 pri->pvts[chanpos]->call = NULL; 11452 } 11453 } 11454 } else { 11455 /* 11456 * Release the PRI lock while we create the channel 11457 * so other threads can send D channel messages. 11458 */ 11459 ast_mutex_unlock(&pri->lock); 11460 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 11461 ast_mutex_lock(&pri->lock); 11462 if (c) { 11463 /* 11464 * It is reasonably safe to set the following 11465 * channel variables while the PRI and DAHDI private 11466 * structures are locked. The PBX has not been 11467 * started yet and it is unlikely that any other task 11468 * will do anything with the channel we have just 11469 * created. 11470 */ 11471 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 11472 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 11473 } 11474 if (e->ring.ani2 >= 0) { 11475 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 11476 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 11477 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 11478 } 11479 11480 #ifdef SUPPORT_USERUSER 11481 if (!ast_strlen_zero(e->ring.useruserinfo)) { 11482 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 11483 } 11484 #endif 11485 11486 if (e->ring.redirectingreason >= 0) 11487 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 11488 11489 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 11490 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 11491 } 11492 if (c && !ast_pbx_start(c)) { 11493 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 11494 plancallingnum, pri->pvts[chanpos]->exten, 11495 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11496 11497 dahdi_enable_ec(pri->pvts[chanpos]); 11498 } else { 11499 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 11500 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 11501 if (c) { 11502 ast_hangup(c); 11503 } else { 11504 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 11505 pri->pvts[chanpos]->call = NULL; 11506 } 11507 } 11508 } 11509 } else { 11510 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 11511 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 11512 pri->pvts[chanpos]->prioffset, pri->span); 11513 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 11514 pri->pvts[chanpos]->call = NULL; 11515 pri->pvts[chanpos]->exten[0] = '\0'; 11516 } 11517 if (crv) 11518 ast_mutex_unlock(&crv->lock); 11519 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11520 } else { 11521 if (e->ring.flexible) 11522 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 11523 else 11524 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 11525 } 11526 break; 11527 case PRI_EVENT_RINGING: 11528 chanpos = pri_find_principle(pri, e->ringing.channel); 11529 if (chanpos < 0) { 11530 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 11531 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11532 } else { 11533 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 11534 if (chanpos < 0) { 11535 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 11536 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 11537 } else { 11538 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11539 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11540 dahdi_enable_ec(pri->pvts[chanpos]); 11541 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 11542 pri->pvts[chanpos]->alerting = 1; 11543 } else 11544 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n"); 11545 11546 #ifdef PRI_PROGRESS_MASK 11547 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11548 #else 11549 if (e->ringing.progress == 8) { 11550 #endif 11551 /* Now we can do call progress detection */ 11552 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11553 /* RINGING detection isn't required because we got ALERTING signal */ 11554 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 11555 pri->pvts[chanpos]->dsp_features = 0; 11556 } 11557 } 11558 11559 #ifdef SUPPORT_USERUSER 11560 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 11561 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11562 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11563 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 11564 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11565 } 11566 #endif 11567 11568 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11569 } 11570 } 11571 break; 11572 case PRI_EVENT_PROGRESS: 11573 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 11574 chanpos = pri_find_principle(pri, e->proceeding.channel); 11575 if (chanpos > -1) { 11576 #ifdef PRI_PROGRESS_MASK 11577 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) { 11578 #else 11579 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) { 11580 #endif 11581 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11582 11583 if (e->proceeding.cause > -1) { 11584 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); 11585 11586 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 11587 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 11588 if (pri->pvts[chanpos]->owner) { 11589 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 11590 11591 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 11592 f.subclass = AST_CONTROL_BUSY; 11593 } 11594 } 11595 } 11596 11597 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11598 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 11599 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11600 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11601 #ifdef PRI_PROGRESS_MASK 11602 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11603 #else 11604 if (e->proceeding.progress == 8) { 11605 #endif 11606 /* Now we can do call progress detection */ 11607 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11608 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11609 pri->pvts[chanpos]->dsp_features = 0; 11610 } 11611 /* Bring voice path up */ 11612 f.subclass = AST_CONTROL_PROGRESS; 11613 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11614 } 11615 pri->pvts[chanpos]->progress = 1; 11616 pri->pvts[chanpos]->dialing = 0; 11617 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11618 } 11619 } 11620 break; 11621 case PRI_EVENT_PROCEEDING: 11622 chanpos = pri_find_principle(pri, e->proceeding.channel); 11623 if (chanpos > -1) { 11624 if (!pri->pvts[chanpos]->proceeding) { 11625 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11626 11627 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11628 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 11629 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 11630 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11631 #ifdef PRI_PROGRESS_MASK 11632 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) { 11633 #else 11634 if (e->proceeding.progress == 8) { 11635 #endif 11636 /* Now we can do call progress detection */ 11637 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11638 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11639 pri->pvts[chanpos]->dsp_features = 0; 11640 } 11641 /* Bring voice path up */ 11642 f.subclass = AST_CONTROL_PROGRESS; 11643 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11644 } 11645 pri->pvts[chanpos]->proceeding = 1; 11646 pri->pvts[chanpos]->dialing = 0; 11647 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11648 } 11649 } 11650 break; 11651 case PRI_EVENT_FACNAME: 11652 chanpos = pri_find_principle(pri, e->facname.channel); 11653 if (chanpos < 0) { 11654 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 11655 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11656 } else { 11657 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 11658 if (chanpos < 0) { 11659 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 11660 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 11661 } else { 11662 /* Re-use *69 field for PRI */ 11663 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11664 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 11665 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 11666 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 11667 dahdi_enable_ec(pri->pvts[chanpos]); 11668 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11669 } 11670 } 11671 break; 11672 case PRI_EVENT_ANSWER: 11673 chanpos = pri_find_principle(pri, e->answer.channel); 11674 if (chanpos < 0) { 11675 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 11676 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11677 } else { 11678 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 11679 if (chanpos < 0) { 11680 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 11681 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 11682 } else { 11683 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11684 /* Now we can do call progress detection */ 11685 11686 /* We changed this so it turns on the DSP no matter what... progress or no progress. 11687 * By this time, we need DTMF detection and other features that were previously disabled 11688 * -- Matt F */ 11689 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 11690 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 11691 pri->pvts[chanpos]->dsp_features = 0; 11692 } 11693 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 11694 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); 11695 x = DAHDI_START; 11696 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 11697 if (res < 0) { 11698 if (errno != EINPROGRESS) { 11699 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 11700 } 11701 } 11702 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 11703 pri->pvts[chanpos]->dialing = 1; 11704 /* Send any "w" waited stuff */ 11705 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 11706 if (res < 0) { 11707 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 11708 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11709 } else 11710 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 11711 11712 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 11713 } else if (pri->pvts[chanpos]->confirmanswer) { 11714 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 11715 } else { 11716 pri->pvts[chanpos]->dialing = 0; 11717 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 11718 /* Enable echo cancellation if it's not on already */ 11719 dahdi_enable_ec(pri->pvts[chanpos]); 11720 } 11721 11722 #ifdef SUPPORT_USERUSER 11723 if (!ast_strlen_zero(e->answer.useruserinfo)) { 11724 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11725 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11726 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 11727 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11728 } 11729 #endif 11730 11731 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11732 } 11733 } 11734 break; 11735 case PRI_EVENT_HANGUP: 11736 chanpos = pri_find_principle(pri, e->hangup.channel); 11737 if (chanpos < 0) { 11738 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 11739 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11740 } else { 11741 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11742 if (chanpos > -1) { 11743 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11744 if (!pri->pvts[chanpos]->alreadyhungup) { 11745 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 11746 pri->pvts[chanpos]->alreadyhungup = 1; 11747 if (pri->pvts[chanpos]->realcall) 11748 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11749 else if (pri->pvts[chanpos]->owner) { 11750 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 11751 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11752 switch (pri->pvts[chanpos]->owner->_state) { 11753 case AST_STATE_BUSY: 11754 case AST_STATE_UP: 11755 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11756 break; 11757 default: 11758 switch (e->hangup.cause) { 11759 case PRI_CAUSE_USER_BUSY: 11760 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11761 break; 11762 case PRI_CAUSE_CALL_REJECTED: 11763 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11764 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11765 case PRI_CAUSE_SWITCH_CONGESTION: 11766 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11767 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11768 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11769 break; 11770 default: 11771 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11772 } 11773 break; 11774 } 11775 } 11776 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", 11777 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 11778 } else { 11779 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11780 pri->pvts[chanpos]->call = NULL; 11781 } 11782 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11783 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 11784 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11785 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11786 pri->pvts[chanpos]->resetting = 1; 11787 } 11788 if (e->hangup.aoc_units > -1) 11789 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11790 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11791 11792 #ifdef SUPPORT_USERUSER 11793 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 11794 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11795 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11796 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11797 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11798 } 11799 #endif 11800 11801 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11802 } else { 11803 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 11804 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11805 } 11806 } 11807 break; 11808 #ifndef PRI_EVENT_HANGUP_REQ 11809 #error please update libpri 11810 #endif 11811 case PRI_EVENT_HANGUP_REQ: 11812 chanpos = pri_find_principle(pri, e->hangup.channel); 11813 if (chanpos < 0) { 11814 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 11815 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11816 } else { 11817 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11818 if (chanpos > -1) { 11819 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11820 if (pri->pvts[chanpos]->realcall) 11821 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11822 else if (pri->pvts[chanpos]->owner) { 11823 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 11824 switch (pri->pvts[chanpos]->owner->_state) { 11825 case AST_STATE_BUSY: 11826 case AST_STATE_UP: 11827 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11828 break; 11829 default: 11830 switch (e->hangup.cause) { 11831 case PRI_CAUSE_USER_BUSY: 11832 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 11833 break; 11834 case PRI_CAUSE_CALL_REJECTED: 11835 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 11836 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 11837 case PRI_CAUSE_SWITCH_CONGESTION: 11838 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 11839 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 11840 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 11841 break; 11842 default: 11843 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11844 } 11845 break; 11846 } 11847 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); 11848 if (e->hangup.aoc_units > -1) 11849 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 11850 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 11851 } else { 11852 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 11853 pri->pvts[chanpos]->call = NULL; 11854 } 11855 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 11856 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", 11857 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11858 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 11859 pri->pvts[chanpos]->resetting = 1; 11860 } 11861 11862 #ifdef SUPPORT_USERUSER 11863 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11864 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11865 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11866 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11867 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11868 } 11869 #endif 11870 11871 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11872 } else { 11873 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); 11874 } 11875 } 11876 break; 11877 case PRI_EVENT_HANGUP_ACK: 11878 chanpos = pri_find_principle(pri, e->hangup.channel); 11879 if (chanpos < 0) { 11880 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 11881 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11882 } else { 11883 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 11884 if (chanpos > -1) { 11885 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11886 pri->pvts[chanpos]->call = NULL; 11887 pri->pvts[chanpos]->resetting = 0; 11888 if (pri->pvts[chanpos]->owner) { 11889 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 11890 } 11891 11892 #ifdef SUPPORT_USERUSER 11893 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 11894 struct ast_channel *owner = pri->pvts[chanpos]->owner; 11895 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11896 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 11897 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11898 } 11899 #endif 11900 11901 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11902 } 11903 } 11904 break; 11905 case PRI_EVENT_CONFIG_ERR: 11906 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 11907 break; 11908 case PRI_EVENT_RESTART_ACK: 11909 chanpos = pri_find_principle(pri, e->restartack.channel); 11910 if (chanpos < 0) { 11911 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 11912 channel number, so we have to figure it out... This must be why 11913 everybody resets exactly a channel at a time. */ 11914 for (x = 0; x < pri->numchans; x++) { 11915 if (pri->pvts[x] && pri->pvts[x]->resetting) { 11916 chanpos = x; 11917 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11918 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 11919 pri->pvts[chanpos]->prioffset, pri->span); 11920 if (pri->pvts[chanpos]->realcall) 11921 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11922 else if (pri->pvts[chanpos]->owner) { 11923 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 11924 pri->pvts[chanpos]->prioffset, pri->span); 11925 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11926 } 11927 pri->pvts[chanpos]->resetting = 0; 11928 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11929 pri->pvts[chanpos]->prioffset, pri->span); 11930 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11931 if (pri->resetting) 11932 pri_check_restart(pri); 11933 break; 11934 } 11935 } 11936 if (chanpos < 0) { 11937 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 11938 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11939 } 11940 } else { 11941 if (pri->pvts[chanpos]) { 11942 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11943 if (pri->pvts[chanpos]->realcall) 11944 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 11945 else if (pri->pvts[chanpos]->owner) { 11946 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 11947 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 11948 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11949 } 11950 pri->pvts[chanpos]->resetting = 0; 11951 pri->pvts[chanpos]->inservice = 1; 11952 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 11953 pri->pvts[chanpos]->prioffset, pri->span); 11954 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11955 if (pri->resetting) 11956 pri_check_restart(pri); 11957 } 11958 } 11959 break; 11960 case PRI_EVENT_SETUP_ACK: 11961 chanpos = pri_find_principle(pri, e->setup_ack.channel); 11962 if (chanpos < 0) { 11963 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 11964 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 11965 } else { 11966 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 11967 if (chanpos > -1) { 11968 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11969 pri->pvts[chanpos]->setup_ack = 1; 11970 /* Send any queued digits */ 11971 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 11972 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 11973 pri_information(pri->pri, pri->pvts[chanpos]->call, 11974 pri->pvts[chanpos]->dialdest[x]); 11975 } 11976 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 11977 } else 11978 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 11979 } 11980 break; 11981 case PRI_EVENT_NOTIFY: 11982 chanpos = pri_find_principle(pri, e->notify.channel); 11983 if (chanpos < 0) { 11984 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 11985 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 11986 } else { 11987 struct ast_frame f = { AST_FRAME_CONTROL, }; 11988 ast_mutex_lock(&pri->pvts[chanpos]->lock); 11989 switch (e->notify.info) { 11990 case PRI_NOTIFY_REMOTE_HOLD: 11991 f.subclass = AST_CONTROL_HOLD; 11992 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11993 break; 11994 case PRI_NOTIFY_REMOTE_RETRIEVAL: 11995 f.subclass = AST_CONTROL_UNHOLD; 11996 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 11997 break; 11998 } 11999 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12000 } 12001 break; 12002 default: 12003 ast_debug(1, "Event: %d\n", e->e); 12004 } 12005 } 12006 ast_mutex_unlock(&pri->lock); 12007 } 12008 /* Never reached */ 12009 return NULL; 12010 }
Definition at line 10541 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 3352 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().
03353 { 03354 int oldslot = -1; 03355 struct pri *old; 03356 int newslot = -1; 03357 int x; 03358 old = pri->pri; 03359 for (x = 0; x < NUM_DCHANS; x++) { 03360 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 03361 newslot = x; 03362 if (pri->dchans[x] == old) { 03363 oldslot = x; 03364 } 03365 } 03366 if (newslot < 0) { 03367 newslot = 0; 03368 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 03369 pri->dchannels[newslot]); 03370 } 03371 if (old && (oldslot != newslot)) 03372 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 03373 pri->dchannels[oldslot], pri->dchannels[newslot]); 03374 pri->pri = pri->dchans[newslot]; 03375 return 0; 03376 }
| static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
| int | backwards | |||
| ) | [static] |
Definition at line 9440 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().
09441 { 09442 int x; 09443 if (backwards) 09444 x = pri->numchans; 09445 else 09446 x = 0; 09447 for (;;) { 09448 if (backwards && (x < 0)) 09449 break; 09450 if (!backwards && (x >= pri->numchans)) 09451 break; 09452 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 09453 ast_debug(1, "Found empty available channel %d/%d\n", 09454 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 09455 return x; 09456 } 09457 if (backwards) 09458 x--; 09459 else 09460 x++; 09461 } 09462 return -1; 09463 }
| static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
| int | channel | |||
| ) | [static] |
Definition at line 10554 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().
10555 { 10556 int x; 10557 int span = PRI_SPAN(channel); 10558 int spanfd; 10559 struct dahdi_params param; 10560 int principle = -1; 10561 int explicit = PRI_EXPLICIT(channel); 10562 channel = PRI_CHANNEL(channel); 10563 10564 if (!explicit) { 10565 spanfd = pri_active_dchan_fd(pri); 10566 memset(¶m, 0, sizeof(param)); 10567 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 10568 return -1; 10569 span = pris[param.spanno - 1].prilogicalspan; 10570 } 10571 10572 for (x = 0; x < pri->numchans; x++) { 10573 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 10574 principle = x; 10575 break; 10576 } 10577 } 10578 10579 return principle; 10580 }
| static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
| int | principle, | |||
| q931_call * | c | |||
| ) | [static] |
Definition at line 10582 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().
10583 { 10584 int x; 10585 struct dahdi_pvt *crv; 10586 if (!c) { 10587 if (principle < 0) 10588 return -1; 10589 return principle; 10590 } 10591 if ((principle > -1) && 10592 (principle < pri->numchans) && 10593 (pri->pvts[principle]) && 10594 (pri->pvts[principle]->call == c)) 10595 return principle; 10596 /* First, check for other bearers */ 10597 for (x = 0; x < pri->numchans; x++) { 10598 if (!pri->pvts[x]) 10599 continue; 10600 if (pri->pvts[x]->call == c) { 10601 /* Found our call */ 10602 if (principle != x) { 10603 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 10604 10605 ast_verb(3, "Moving call from channel %d to channel %d\n", 10606 old->channel, new->channel); 10607 if (new->owner) { 10608 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 10609 old->channel, new->channel, new->channel); 10610 return -1; 10611 } 10612 /* Fix it all up now */ 10613 new->owner = old->owner; 10614 old->owner = NULL; 10615 if (new->owner) { 10616 ast_string_field_build(new->owner, name, 10617 "DAHDI/%d:%d-%d", pri->trunkgroup, 10618 new->channel, 1); 10619 new->owner->tech_pvt = new; 10620 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd); 10621 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 10622 old->subs[SUB_REAL].owner = NULL; 10623 } else 10624 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); 10625 new->call = old->call; 10626 old->call = NULL; 10627 10628 /* Copy any DSP that may be present */ 10629 new->dsp = old->dsp; 10630 new->dsp_features = old->dsp_features; 10631 old->dsp = NULL; 10632 old->dsp_features = 0; 10633 } 10634 return principle; 10635 } 10636 } 10637 /* Now check for a CRV with no bearer */ 10638 crv = pri->crvs; 10639 while (crv) { 10640 if (crv->call == c) { 10641 /* This is our match... Perform some basic checks */ 10642 if (crv->bearer) 10643 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 10644 else if (pri->pvts[principle]->owner) 10645 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 10646 else { 10647 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 10648 wakeup the potential sleeper */ 10649 dahdi_close_sub(crv, SUB_REAL); 10650 pri->pvts[principle]->call = crv->call; 10651 pri_assign_bearer(crv, pri, pri->pvts[principle]); 10652 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n", 10653 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 10654 pri->trunkgroup, crv->channel); 10655 wakeup_sub(crv, SUB_REAL, pri); 10656 } 10657 return principle; 10658 } 10659 crv = crv->next; 10660 } 10661 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 10662 return -1; 10663 }
Definition at line 1227 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, and dahdi_pri::master.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_send_keypad_facility_exec(), and dahdi_write().
01228 { 01229 int res; 01230 /* Grab the lock first */ 01231 do { 01232 res = ast_mutex_trylock(&pri->lock); 01233 if (res) { 01234 DEADLOCK_AVOIDANCE(&pvt->lock); 01235 } 01236 } while (res); 01237 /* Then break the poll */ 01238 if (pri->master != AST_PTHREADT_NULL) 01239 pthread_kill(pri->master, SIGURG); 01240 return 0; 01241 }
Definition at line 10813 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().
10814 { 10815 int x; 10816 int redo; 10817 ast_mutex_unlock(&pri->lock); 10818 ast_mutex_lock(&p->lock); 10819 do { 10820 redo = 0; 10821 for (x = 0; x < 3; x++) { 10822 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) { 10823 redo++; 10824 DEADLOCK_AVOIDANCE(&p->lock); 10825 } 10826 if (p->subs[x].owner) { 10827 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED); 10828 ast_channel_unlock(p->subs[x].owner); 10829 } 10830 } 10831 } while (redo); 10832 ast_mutex_unlock(&p->lock); 10833 ast_mutex_lock(&pri->lock); 10834 return 0; 10835 }
| static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 3300 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.
Referenced by mkintf(), and pri_dchannel().
03301 { 03302 int x; 03303 for (x = 0; x < NUM_DCHANS; x++) { 03304 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 03305 return 1; 03306 } 03307 return 0; 03308 }
| static char* pri_order | ( | int | level | ) | [static] |
Definition at line 3323 of file chan_dahdi.c.
Referenced by handle_pri_show_span(), and pri_dchannel().
| static void pri_rel | ( | struct dahdi_pri * | pri | ) | [inline, static] |
Definition at line 455 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_pri::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_send_keypad_facility_exec(), and dahdi_write().
00456 { 00457 ast_mutex_unlock(&pri->lock); 00458 }
| static int pri_resolve_span | ( | int * | span, | |
| int | channel, | |||
| int | offset, | |||
| struct dahdi_spaninfo * | si | |||
| ) | [static] |
Definition at line 8561 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().
08562 { 08563 int x; 08564 int trunkgroup; 08565 /* Get appropriate trunk group if there is one */ 08566 trunkgroup = pris[*span].mastertrunkgroup; 08567 if (trunkgroup) { 08568 /* Select a specific trunk group */ 08569 for (x = 0; x < NUM_SPANS; x++) { 08570 if (pris[x].trunkgroup == trunkgroup) { 08571 *span = x; 08572 return 0; 08573 } 08574 } 08575 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 08576 *span = -1; 08577 } else { 08578 if (pris[*span].trunkgroup) { 08579 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 08580 *span = -1; 08581 } else if (pris[*span].mastertrunkgroup) { 08582 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 08583 *span = -1; 08584 } else { 08585 if (si->totalchans == 31) { 08586 /* E1 */ 08587 pris[*span].dchannels[0] = 16 + offset; 08588 } else if (si->totalchans == 24) { 08589 /* T1 or J1 */ 08590 pris[*span].dchannels[0] = 24 + offset; 08591 } else if (si->totalchans == 3) { 08592 /* BRI */ 08593 pris[*span].dchannels[0] = 3 + offset; 08594 } else { 08595 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); 08596 *span = -1; 08597 return 0; 08598 } 08599 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 08600 pris[*span].offset = offset; 08601 pris[*span].span = *span + 1; 08602 } 08603 } 08604 return 0; 08605 }
| static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
| const char * | cat, | |||
| struct ast_variable * | v, | |||
| int | reload, | |||
| int | options | |||
| ) | [static] |
Definition at line 14267 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().
14268 { 14269 struct dahdi_pvt *tmp; 14270 int y; 14271 int found_pseudo = 0; 14272 char dahdichan[MAX_CHANLIST_LEN] = {}; 14273 14274 for (; v; v = v->next) { 14275 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 14276 continue; 14277 14278 /* must have parkinglot in confp before build_channels is called */ 14279 if (!strcasecmp(v->name, "parkinglot")) { 14280 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 14281 } 14282 14283 /* Create the interface list */ 14284 if (!strcasecmp(v->name, "channel") 14285 #ifdef HAVE_PRI 14286 || !strcasecmp(v->name, "crv") 14287 #endif 14288 ) { 14289 int iscrv; 14290 if (options & PROC_DAHDI_OPT_NOCHAN) { 14291 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 14292 continue; 14293 } 14294 iscrv = !strcasecmp(v->name, "crv"); 14295 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 14296 return -1; 14297 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 14298 } else if (!strcasecmp(v->name, "buffers")) { 14299 int res; 14300 char policy[21] = ""; 14301 14302 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 14303 if (res != 2) { 14304 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 14305 confp->chan.buf_no = numbufs; 14306 continue; 14307 } 14308 if (confp->chan.buf_no < 0) 14309 confp->chan.buf_no = numbufs; 14310 if (!strcasecmp(policy, "full")) { 14311 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 14312 } else if (!strcasecmp(policy, "immediate")) { 14313 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 14314 } else { 14315 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 14316 } 14317 } else if (!strcasecmp(v->name, "dahdichan")) { 14318 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 14319 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 14320 usedistinctiveringdetection = ast_true(v->value); 14321 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 14322 distinctiveringaftercid = ast_true(v->value); 14323 } else if (!strcasecmp(v->name, "dring1context")) { 14324 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 14325 } else if (!strcasecmp(v->name, "dring2context")) { 14326 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 14327 } else if (!strcasecmp(v->name, "dring3context")) { 14328 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 14329 } else if (!strcasecmp(v->name, "dring1range")) { 14330 confp->chan.drings.ringnum[0].range = atoi(v->value); 14331 } else if (!strcasecmp(v->name, "dring2range")) { 14332 confp->chan.drings.ringnum[1].range = atoi(v->value); 14333 } else if (!strcasecmp(v->name, "dring3range")) { 14334 confp->chan.drings.ringnum[2].range = atoi(v->value); 14335 } else if (!strcasecmp(v->name, "dring1")) { 14336 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]); 14337 } else if (!strcasecmp(v->name, "dring2")) { 14338 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]); 14339 } else if (!strcasecmp(v->name, "dring3")) { 14340 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]); 14341 } else if (!strcasecmp(v->name, "usecallerid")) { 14342 confp->chan.use_callerid = ast_true(v->value); 14343 } else if (!strcasecmp(v->name, "cidsignalling")) { 14344 if (!strcasecmp(v->value, "bell")) 14345 confp->chan.cid_signalling = CID_SIG_BELL; 14346 else if (!strcasecmp(v->value, "v23")) 14347 confp->chan.cid_signalling = CID_SIG_V23; 14348 else if (!strcasecmp(v->value, "dtmf")) 14349 confp->chan.cid_signalling = CID_SIG_DTMF; 14350 else if (!strcasecmp(v->value, "smdi")) 14351 confp->chan.cid_signalling = CID_SIG_SMDI; 14352 else if (!strcasecmp(v->value, "v23_jp")) 14353 confp->chan.cid_signalling = CID_SIG_V23_JP; 14354 else if (ast_true(v->value)) 14355 confp->chan.cid_signalling = CID_SIG_BELL; 14356 } else if (!strcasecmp(v->name, "cidstart")) { 14357 if (!strcasecmp(v->value, "ring")) 14358 confp->chan.cid_start = CID_START_RING; 14359 else if (!strcasecmp(v->value, "polarity_in")) 14360 confp->chan.cid_start = CID_START_POLARITY_IN; 14361 else if (!strcasecmp(v->value, "polarity")) 14362 confp->chan.cid_start = CID_START_POLARITY; 14363 else if (ast_true(v->value)) 14364 confp->chan.cid_start = CID_START_RING; 14365 } else if (!strcasecmp(v->name, "threewaycalling")) { 14366 confp->chan.threewaycalling = ast_true(v->value); 14367 } else if (!strcasecmp(v->name, "cancallforward")) { 14368 confp->chan.cancallforward = ast_true(v->value); 14369 } else if (!strcasecmp(v->name, "relaxdtmf")) { 14370 if (ast_true(v->value)) 14371 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 14372 else 14373 confp->chan.dtmfrelax = 0; 14374 } else if (!strcasecmp(v->name, "mailbox")) { 14375 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 14376 } else if (!strcasecmp(v->name, "hasvoicemail")) { 14377 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 14378 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 14379 } 14380 } else if (!strcasecmp(v->name, "adsi")) { 14381 confp->chan.adsi = ast_true(v->value); 14382 } else if (!strcasecmp(v->name, "usesmdi")) { 14383 confp->chan.use_smdi = ast_true(v->value); 14384 } else if (!strcasecmp(v->name, "smdiport")) { 14385 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 14386 } else if (!strcasecmp(v->name, "transfer")) { 14387 confp->chan.transfer = ast_true(v->value); 14388 } else if (!strcasecmp(v->name, "canpark")) { 14389 confp->chan.canpark = ast_true(v->value); 14390 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 14391 confp->chan.echocanbridged = ast_true(v->value); 14392 } else if (!strcasecmp(v->name, "busydetect")) { 14393 confp->chan.busydetect = ast_true(v->value); 14394 } else if (!strcasecmp(v->name, "busycount")) { 14395 confp->chan.busycount = atoi(v->value); 14396 } else if (!strcasecmp(v->name, "busypattern")) { 14397 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) { 14398 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 14399 } 14400 } else if (!strcasecmp(v->name, "callprogress")) { 14401 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 14402 if (ast_true(v->value)) 14403 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 14404 } else if (!strcasecmp(v->name, "faxdetect")) { 14405 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 14406 if (!strcasecmp(v->value, "incoming")) { 14407 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 14408 } else if (!strcasecmp(v->value, "outgoing")) { 14409 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 14410 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 14411 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 14412 } else if (!strcasecmp(v->name, "echocancel")) { 14413 process_echocancel(confp, v->value, v->lineno); 14414 } else if (!strcasecmp(v->name, "echotraining")) { 14415 if (sscanf(v->value, "%30d", &y) == 1) { 14416 if ((y < 10) || (y > 4000)) { 14417 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 14418 } else { 14419 confp->chan.echotraining = y; 14420 } 14421 } else if (ast_true(v->value)) { 14422 confp->chan.echotraining = 400; 14423 } else 14424 confp->chan.echotraining = 0; 14425 } else if (!strcasecmp(v->name, "hidecallerid")) { 14426 confp->chan.hidecallerid = ast_true(v->value); 14427 } else if (!strcasecmp(v->name, "hidecalleridname")) { 14428 confp->chan.hidecalleridname = ast_true(v->value); 14429 } else if (!strcasecmp(v->name, "pulsedial")) { 14430 confp->chan.pulse = ast_true(v->value); 14431 } else if (!strcasecmp(v->name, "callreturn")) { 14432 confp->chan.callreturn = ast_true(v->value); 14433 } else if (!strcasecmp(v->name, "callwaiting")) { 14434 confp->chan.callwaiting = ast_true(v->value); 14435 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 14436 confp->chan.callwaitingcallerid = ast_true(v->value); 14437 } else if (!strcasecmp(v->name, "context")) { 14438 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 14439 } else if (!strcasecmp(v->name, "language")) { 14440 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 14441 } else if (!strcasecmp(v->name, "progzone")) { 14442 ast_copy_string(progzone, v->value, sizeof(progzone)); 14443 } else if (!strcasecmp(v->name, "mohinterpret") 14444 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 14445 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 14446 } else if (!strcasecmp(v->name, "mohsuggest")) { 14447 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 14448 } else if (!strcasecmp(v->name, "parkinglot")) { 14449 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 14450 } else if (!strcasecmp(v->name, "stripmsd")) { 14451 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 14452 confp->chan.stripmsd = atoi(v->value); 14453 } else if (!strcasecmp(v->name, "jitterbuffers")) { 14454 numbufs = atoi(v->value); 14455 } else if (!strcasecmp(v->name, "group")) { 14456 confp->chan.group = ast_get_group(v->value); 14457 } else if (!strcasecmp(v->name, "callgroup")) { 14458 if (!strcasecmp(v->value, "none")) 14459 confp->chan.callgroup = 0; 14460 else 14461 confp->chan.callgroup = ast_get_group(v->value); 14462 } else if (!strcasecmp(v->name, "pickupgroup")) { 14463 if (!strcasecmp(v->value, "none")) 14464 confp->chan.pickupgroup = 0; 14465 else 14466 confp->chan.pickupgroup = ast_get_group(v->value); 14467 } else if (!strcasecmp(v->name, "setvar")) { 14468 char *varname = ast_strdupa(v->value), *varval = NULL; 14469 struct ast_variable *tmpvar; 14470 if (varname && (varval = strchr(varname, '='))) { 14471 *varval++ = '\0'; 14472 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 14473 tmpvar->next = confp->chan.vars; 14474 confp->chan.vars = tmpvar; 14475 } 14476 } 14477 } else if (!strcasecmp(v->name, "immediate")) { 14478 confp->chan.immediate = ast_true(v->value); 14479 } else if (!strcasecmp(v->name, "transfertobusy")) { 14480 confp->chan.transfertobusy = ast_true(v->value); 14481 } else if (!strcasecmp(v->name, "mwimonitor")) { 14482 confp->chan.mwimonitor_neon = 0; 14483 confp->chan.mwimonitor_fsk = 0; 14484 confp->chan.mwimonitor_rpas = 0; 14485 if (strcasestr(v->value, "fsk")) { 14486 confp->chan.mwimonitor_fsk = 1; 14487 } 14488 if (strcasestr(v->value, "rpas")) { 14489 confp->chan.mwimonitor_rpas = 1; 14490 } 14491 if (strcasestr(v->value, "neon")) { 14492 confp->chan.mwimonitor_neon = 1; 14493 } 14494 /* If set to true or yes, assume that simple fsk is desired */ 14495 if (ast_true(v->value)) { 14496 confp->chan.mwimonitor_fsk = 1; 14497 } 14498 } else if (!strcasecmp(v->name, "cid_rxgain")) { 14499 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 14500 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 14501 } 14502 } else if (!strcasecmp(v->name, "rxgain")) { 14503 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 14504 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 14505 } 14506 } else if (!strcasecmp(v->name, "txgain")) { 14507 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 14508 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 14509 } 14510 } else if (!strcasecmp(v->name, "tonezone")) { 14511 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 14512 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 14513 } 14514 } else if (!strcasecmp(v->name, "callerid")) { 14515 if (!strcasecmp(v->value, "asreceived")) { 14516 confp->chan.cid_num[0] = '\0'; 14517 confp->chan.cid_name[0] = '\0'; 14518 } else { 14519 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 14520 } 14521 } else if (!strcasecmp(v->name, "fullname")) { 14522 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 14523 } else if (!strcasecmp(v->name, "cid_number")) { 14524 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 14525 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 14526 confp->chan.dahditrcallerid = ast_true(v->value); 14527 } else if (!strcasecmp(v->name, "restrictcid")) { 14528 confp->chan.restrictcid = ast_true(v->value); 14529 } else if (!strcasecmp(v->name, "usecallingpres")) { 14530 confp->chan.use_callingpres = ast_true(v->value); 14531 } else if (!strcasecmp(v->name, "accountcode")) { 14532 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 14533 } else if (!strcasecmp(v->name, "amaflags")) { 14534 y = ast_cdr_amaflags2int(v->value); 14535 if (y < 0) 14536 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 14537 else 14538 confp->chan.amaflags = y; 14539 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 14540 confp->chan.polarityonanswerdelay = atoi(v->value); 14541 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 14542 confp->chan.answeronpolarityswitch = ast_true(v->value); 14543 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 14544 confp->chan.hanguponpolarityswitch = ast_true(v->value); 14545 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 14546 confp->chan.sendcalleridafter = atoi(v->value); 14547 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 14548 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 14549 } else if (!strcasecmp(v->name, "mwisendtype")) { 14550 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 14551 mwisend_rpas = 1; 14552 } else { 14553 mwisend_rpas = 0; 14554 } 14555 } else if (reload != 1) { 14556 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 14557 int orig_radio = confp->chan.radio; 14558 int orig_outsigmod = confp->chan.outsigmod; 14559 int orig_auto = confp->is_sig_auto; 14560 14561 confp->chan.radio = 0; 14562 confp->chan.outsigmod = -1; 14563 confp->is_sig_auto = 0; 14564 if (!strcasecmp(v->value, "em")) { 14565 confp->chan.sig = SIG_EM; 14566 } else if (!strcasecmp(v->value, "em_e1")) { 14567 confp->chan.sig = SIG_EM_E1; 14568 } else if (!strcasecmp(v->value, "em_w")) { 14569 confp->chan.sig = SIG_EMWINK; 14570 } else if (!strcasecmp(v->value, "fxs_ls")) { 14571 confp->chan.sig = SIG_FXSLS; 14572 } else if (!strcasecmp(v->value, "fxs_gs")) { 14573 confp->chan.sig = SIG_FXSGS; 14574 } else if (!strcasecmp(v->value, "fxs_ks")) { 14575 confp->chan.sig = SIG_FXSKS; 14576 } else if (!strcasecmp(v->value, "fxo_ls")) { 14577 confp->chan.sig = SIG_FXOLS; 14578 } else if (!strcasecmp(v->value, "fxo_gs")) { 14579 confp->chan.sig = SIG_FXOGS; 14580 } else if (!strcasecmp(v->value, "fxo_ks")) { 14581 confp->chan.sig = SIG_FXOKS; 14582 } else if (!strcasecmp(v->value, "fxs_rx")) { 14583 confp->chan.sig = SIG_FXSKS; 14584 confp->chan.radio = 1; 14585 } else if (!strcasecmp(v->value, "fxo_rx")) { 14586 confp->chan.sig = SIG_FXOLS; 14587 confp->chan.radio = 1; 14588 } else if (!strcasecmp(v->value, "fxs_tx")) { 14589 confp->chan.sig = SIG_FXSLS; 14590 confp->chan.radio = 1; 14591 } else if (!strcasecmp(v->value, "fxo_tx")) { 14592 confp->chan.sig = SIG_FXOGS; 14593 confp->chan.radio = 1; 14594 } else if (!strcasecmp(v->value, "em_rx")) { 14595 confp->chan.sig = SIG_EM; 14596 confp->chan.radio = 1; 14597 } else if (!strcasecmp(v->value, "em_tx")) { 14598 confp->chan.sig = SIG_EM; 14599 confp->chan.radio = 1; 14600 } else if (!strcasecmp(v->value, "em_rxtx")) { 14601 confp->chan.sig = SIG_EM; 14602 confp->chan.radio = 2; 14603 } else if (!strcasecmp(v->value, "em_txrx")) { 14604 confp->chan.sig = SIG_EM; 14605 confp->chan.radio = 2; 14606 } else if (!strcasecmp(v->value, "sf")) { 14607 confp->chan.sig = SIG_SF; 14608 } else if (!strcasecmp(v->value, "sf_w")) { 14609 confp->chan.sig = SIG_SFWINK; 14610 } else if (!strcasecmp(v->value, "sf_featd")) { 14611 confp->chan.sig = SIG_FEATD; 14612 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14613 confp->chan.sig = SIG_FEATDMF; 14614 } else if (!strcasecmp(v->value, "sf_featb")) { 14615 confp->chan.sig = SIG_SF_FEATB; 14616 } else if (!strcasecmp(v->value, "sf")) { 14617 confp->chan.sig = SIG_SF; 14618 } else if (!strcasecmp(v->value, "sf_rx")) { 14619 confp->chan.sig = SIG_SF; 14620 confp->chan.radio = 1; 14621 } else if (!strcasecmp(v->value, "sf_tx")) { 14622 confp->chan.sig = SIG_SF; 14623 confp->chan.radio = 1; 14624 } else if (!strcasecmp(v->value, "sf_rxtx")) { 14625 confp->chan.sig = SIG_SF; 14626 confp->chan.radio = 2; 14627 } else if (!strcasecmp(v->value, "sf_txrx")) { 14628 confp->chan.sig = SIG_SF; 14629 confp->chan.radio = 2; 14630 } else if (!strcasecmp(v->value, "featd")) { 14631 confp->chan.sig = SIG_FEATD; 14632 } else if (!strcasecmp(v->value, "featdmf")) { 14633 confp->chan.sig = SIG_FEATDMF; 14634 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14635 confp->chan.sig = SIG_FEATDMF_TA; 14636 } else if (!strcasecmp(v->value, "e911")) { 14637 confp->chan.sig = SIG_E911; 14638 } else if (!strcasecmp(v->value, "fgccama")) { 14639 confp->chan.sig = SIG_FGC_CAMA; 14640 } else if (!strcasecmp(v->value, "fgccamamf")) { 14641 confp->chan.sig = SIG_FGC_CAMAMF; 14642 } else if (!strcasecmp(v->value, "featb")) { 14643 confp->chan.sig = SIG_FEATB; 14644 #ifdef HAVE_PRI 14645 } else if (!strcasecmp(v->value, "pri_net")) { 14646 confp->chan.sig = SIG_PRI; 14647 confp->pri.nodetype = PRI_NETWORK; 14648 } else if (!strcasecmp(v->value, "pri_cpe")) { 14649 confp->chan.sig = SIG_PRI; 14650 confp->pri.nodetype = PRI_CPE; 14651 } else if (!strcasecmp(v->value, "bri_cpe")) { 14652 confp->chan.sig = SIG_BRI; 14653 confp->pri.nodetype = PRI_CPE; 14654 } else if (!strcasecmp(v->value, "bri_net")) { 14655 confp->chan.sig = SIG_BRI; 14656 confp->pri.nodetype = PRI_NETWORK; 14657 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 14658 confp->chan.sig = SIG_BRI_PTMP; 14659 confp->pri.nodetype = PRI_CPE; 14660 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 14661 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 14662 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 14663 confp->chan.sig = SIG_GR303FXOKS; 14664 confp->pri.nodetype = PRI_NETWORK; 14665 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 14666 confp->chan.sig = SIG_GR303FXSKS; 14667 confp->pri.nodetype = PRI_CPE; 14668 #endif 14669 #ifdef HAVE_SS7 14670 } else if (!strcasecmp(v->value, "ss7")) { 14671 confp->chan.sig = SIG_SS7; 14672 #endif 14673 } else if (!strcasecmp(v->value, "auto")) { 14674 confp->is_sig_auto = 1; 14675 } else { 14676 confp->chan.outsigmod = orig_outsigmod; 14677 confp->chan.radio = orig_radio; 14678 confp->is_sig_auto = orig_auto; 14679 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14680 } 14681 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 14682 if (!strcasecmp(v->value, "em")) { 14683 confp->chan.outsigmod = SIG_EM; 14684 } else if (!strcasecmp(v->value, "em_e1")) { 14685 confp->chan.outsigmod = SIG_EM_E1; 14686 } else if (!strcasecmp(v->value, "em_w")) { 14687 confp->chan.outsigmod = SIG_EMWINK; 14688 } else if (!strcasecmp(v->value, "sf")) { 14689 confp->chan.outsigmod = SIG_SF; 14690 } else if (!strcasecmp(v->value, "sf_w")) { 14691 confp->chan.outsigmod = SIG_SFWINK; 14692 } else if (!strcasecmp(v->value, "sf_featd")) { 14693 confp->chan.outsigmod = SIG_FEATD; 14694 } else if (!strcasecmp(v->value, "sf_featdmf")) { 14695 confp->chan.outsigmod = SIG_FEATDMF; 14696 } else if (!strcasecmp(v->value, "sf_featb")) { 14697 confp->chan.outsigmod = SIG_SF_FEATB; 14698 } else if (!strcasecmp(v->value, "sf")) { 14699 confp->chan.outsigmod = SIG_SF; 14700 } else if (!strcasecmp(v->value, "featd")) { 14701 confp->chan.outsigmod = SIG_FEATD; 14702 } else if (!strcasecmp(v->value, "featdmf")) { 14703 confp->chan.outsigmod = SIG_FEATDMF; 14704 } else if (!strcasecmp(v->value, "featdmf_ta")) { 14705 confp->chan.outsigmod = SIG_FEATDMF_TA; 14706 } else if (!strcasecmp(v->value, "e911")) { 14707 confp->chan.outsigmod = SIG_E911; 14708 } else if (!strcasecmp(v->value, "fgccama")) { 14709 confp->chan.outsigmod = SIG_FGC_CAMA; 14710 } else if (!strcasecmp(v->value, "fgccamamf")) { 14711 confp->chan.outsigmod = SIG_FGC_CAMAMF; 14712 } else if (!strcasecmp(v->value, "featb")) { 14713 confp->chan.outsigmod = SIG_FEATB; 14714 } else { 14715 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 14716 } 14717 #ifdef HAVE_PRI 14718 } else if (!strcasecmp(v->name, "pridialplan")) { 14719 if (!strcasecmp(v->value, "national")) { 14720 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 14721 } else if (!strcasecmp(v->value, "unknown")) { 14722 confp->pri.dialplan = PRI_UNKNOWN + 1; 14723 } else if (!strcasecmp(v->value, "private")) { 14724 confp->pri.dialplan = PRI_PRIVATE + 1; 14725 } else if (!strcasecmp(v->value, "international")) { 14726 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 14727 } else if (!strcasecmp(v->value, "local")) { 14728 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 14729 } else if (!strcasecmp(v->value, "dynamic")) { 14730 confp->pri.dialplan = -1; 14731 } else if (!strcasecmp(v->value, "redundant")) { 14732 confp->pri.dialplan = -2; 14733 } else { 14734 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 14735 } 14736 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 14737 if (!strcasecmp(v->value, "national")) { 14738 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 14739 } else if (!strcasecmp(v->value, "unknown")) { 14740 confp->pri.localdialplan = PRI_UNKNOWN + 1; 14741 } else if (!strcasecmp(v->value, "private")) { 14742 confp->pri.localdialplan = PRI_PRIVATE + 1; 14743 } else if (!strcasecmp(v->value, "international")) { 14744 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 14745 } else if (!strcasecmp(v->value, "local")) { 14746 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 14747 } else if (!strcasecmp(v->value, "dynamic")) { 14748 confp->pri.localdialplan = -1; 14749 } else if (!strcasecmp(v->value, "redundant")) { 14750 confp->pri.localdialplan = -2; 14751 } else { 14752 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 14753 } 14754 } else if (!strcasecmp(v->name, "switchtype")) { 14755 if (!strcasecmp(v->value, "national")) 14756 confp->pri.switchtype = PRI_SWITCH_NI2; 14757 else if (!strcasecmp(v->value, "ni1")) 14758 confp->pri.switchtype = PRI_SWITCH_NI1; 14759 else if (!strcasecmp(v->value, "dms100")) 14760 confp->pri.switchtype = PRI_SWITCH_DMS100; 14761 else if (!strcasecmp(v->value, "4ess")) 14762 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 14763 else if (!strcasecmp(v->value, "5ess")) 14764 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 14765 else if (!strcasecmp(v->value, "euroisdn")) 14766 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 14767 else if (!strcasecmp(v->value, "qsig")) 14768 confp->pri.switchtype = PRI_SWITCH_QSIG; 14769 else { 14770 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 14771 return -1; 14772 } 14773 } else if (!strcasecmp(v->name, "nsf")) { 14774 if (!strcasecmp(v->value, "sdn")) 14775 confp->pri.nsf = PRI_NSF_SDN; 14776 else if (!strcasecmp(v->value, "megacom")) 14777 confp->pri.nsf = PRI_NSF_MEGACOM; 14778 else if (!strcasecmp(v->value, "tollfreemegacom")) 14779 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 14780 else if (!strcasecmp(v->value, "accunet")) 14781 confp->pri.nsf = PRI_NSF_ACCUNET; 14782 else if (!strcasecmp(v->value, "none")) 14783 confp->pri.nsf = PRI_NSF_NONE; 14784 else { 14785 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 14786 confp->pri.nsf = PRI_NSF_NONE; 14787 } 14788 } else if (!strcasecmp(v->name, "priindication")) { 14789 if (!strcasecmp(v->value, "outofband")) 14790 confp->chan.priindication_oob = 1; 14791 else if (!strcasecmp(v->value, "inband")) 14792 confp->chan.priindication_oob = 0; 14793 else 14794 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 14795 v->value, v->lineno); 14796 } else if (!strcasecmp(v->name, "priexclusive")) { 14797 confp->chan.priexclusive = ast_true(v->value); 14798 } else if (!strcasecmp(v->name, "internationalprefix")) { 14799 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 14800 } else if (!strcasecmp(v->name, "nationalprefix")) { 14801 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 14802 } else if (!strcasecmp(v->name, "localprefix")) { 14803 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 14804 } else if (!strcasecmp(v->name, "privateprefix")) { 14805 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 14806 } else if (!strcasecmp(v->name, "unknownprefix")) { 14807 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 14808 } else if (!strcasecmp(v->name, "resetinterval")) { 14809 if (!strcasecmp(v->value, "never")) 14810 confp->pri.resetinterval = -1; 14811 else if (atoi(v->value) >= 60) 14812 confp->pri.resetinterval = atoi(v->value); 14813 else 14814 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 14815 v->value, v->lineno); 14816 } else if (!strcasecmp(v->name, "minunused")) { 14817 confp->pri.minunused = atoi(v->value); 14818 } else if (!strcasecmp(v->name, "minidle")) { 14819 confp->pri.minidle = atoi(v->value); 14820 } else if (!strcasecmp(v->name, "idleext")) { 14821 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 14822 } else if (!strcasecmp(v->name, "idledial")) { 14823 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 14824 } else if (!strcasecmp(v->name, "overlapdial")) { 14825 if (ast_true(v->value)) { 14826 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14827 } else if (!strcasecmp(v->value, "incoming")) { 14828 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 14829 } else if (!strcasecmp(v->value, "outgoing")) { 14830 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 14831 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 14832 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 14833 } else { 14834 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 14835 } 14836 #ifdef HAVE_PRI_INBANDDISCONNECT 14837 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 14838 confp->pri.inbanddisconnect = ast_true(v->value); 14839 #endif 14840 } else if (!strcasecmp(v->name, "pritimer")) { 14841 #ifdef PRI_GETSET_TIMERS 14842 char tmp[20]; 14843 char *timerc; 14844 char *c; 14845 int timer; 14846 int timeridx; 14847 14848 ast_copy_string(tmp, v->value, sizeof(tmp)); 14849 c = tmp; 14850 timerc = strsep(&c, ","); 14851 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 14852 timeridx = pri_timer2idx(timerc); 14853 timer = atoi(c); 14854 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 14855 ast_log(LOG_WARNING, 14856 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 14857 v->lineno); 14858 } else if (!timer) { 14859 ast_log(LOG_WARNING, 14860 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 14861 c, timerc, v->lineno); 14862 } else { 14863 pritimers[timeridx] = timer; 14864 } 14865 } else { 14866 ast_log(LOG_WARNING, 14867 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 14868 v->value, v->lineno); 14869 } 14870 14871 } else if (!strcasecmp(v->name, "facilityenable")) { 14872 confp->pri.facilityenable = ast_true(v->value); 14873 #endif /* PRI_GETSET_TIMERS */ 14874 #endif /* HAVE_PRI */ 14875 #ifdef HAVE_SS7 14876 } else if (!strcasecmp(v->name, "ss7type")) { 14877 if (!strcasecmp(v->value, "itu")) { 14878 cur_ss7type = SS7_ITU; 14879 } else if (!strcasecmp(v->value, "ansi")) { 14880 cur_ss7type = SS7_ANSI; 14881 } else 14882 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 14883 } else if (!strcasecmp(v->name, "linkset")) { 14884 cur_linkset = atoi(v->value); 14885 } else if (!strcasecmp(v->name, "pointcode")) { 14886 cur_pointcode = parse_pointcode(v->value); 14887 } else if (!strcasecmp(v->name, "adjpointcode")) { 14888 cur_adjpointcode = parse_pointcode(v->value); 14889 } else if (!strcasecmp(v->name, "defaultdpc")) { 14890 cur_defaultdpc = parse_pointcode(v->value); 14891 } else if (!strcasecmp(v->name, "cicbeginswith")) { 14892 cur_cicbeginswith = atoi(v->value); 14893 } else if (!strcasecmp(v->name, "networkindicator")) { 14894 if (!strcasecmp(v->value, "national")) 14895 cur_networkindicator = SS7_NI_NAT; 14896 else if (!strcasecmp(v->value, "national_spare")) 14897 cur_networkindicator = SS7_NI_NAT_SPARE; 14898 else if (!strcasecmp(v->value, "international")) 14899 cur_networkindicator = SS7_NI_INT; 14900 else if (!strcasecmp(v->value, "international_spare")) 14901 cur_networkindicator = SS7_NI_INT_SPARE; 14902 else 14903 cur_networkindicator = -1; 14904 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 14905 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix)); 14906 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 14907 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix)); 14908 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 14909 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix)); 14910 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 14911 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix)); 14912 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 14913 if (!strcasecmp(v->value, "national")) { 14914 confp->ss7.called_nai = SS7_NAI_NATIONAL; 14915 } else if (!strcasecmp(v->value, "international")) { 14916 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL; 14917 } else if (!strcasecmp(v->value, "subscriber")) { 14918 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER; 14919 } else if (!strcasecmp(v->value, "dynamic")) { 14920 confp->ss7.called_nai = SS7_NAI_DYNAMIC; 14921 } else { 14922 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 14923 } 14924 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 14925 if (!strcasecmp(v->value, "national")) { 14926 confp->ss7.calling_nai = SS7_NAI_NATIONAL; 14927 } else if (!strcasecmp(v->value, "international")) { 14928 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL; 14929 } else if (!strcasecmp(v->value, "subscriber")) { 14930 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER; 14931 } else if (!strcasecmp(v->value, "dynamic")) { 14932 confp->ss7.calling_nai = SS7_NAI_DYNAMIC; 14933 } else { 14934 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 14935 } 14936 } else if (!strcasecmp(v->name, "sigchan")) { 14937 int sigchan, res; 14938 sigchan = atoi(v->value); 14939 res = linkset_addsigchan(sigchan); 14940 if (res < 0) 14941 return -1; 14942 14943 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 14944 struct dahdi_ss7 *link; 14945 link = ss7_resolve_linkset(cur_linkset); 14946 if (!link) { 14947 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 14948 return -1; 14949 } 14950 if (ast_true(v->value)) 14951 link->flags |= LINKSET_FLAG_EXPLICITACM; 14952 14953 #endif /* HAVE_SS7 */ 14954 } else if (!strcasecmp(v->name, "cadence")) { 14955 /* setup to scan our argument */ 14956 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 14957 int i; 14958 struct dahdi_ring_cadence new_cadence; 14959 int cid_location = -1; 14960 int firstcadencepos = 0; 14961 char original_args[80]; 14962 int cadence_is_ok = 1; 14963 14964 ast_copy_string(original_args, v->value, sizeof(original_args)); 14965 /* 16 cadences allowed (8 pairs) */ 14966 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]); 14967 14968 /* Cadence must be even (on/off) */ 14969 if (element_count % 2 == 1) { 14970 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 14971 cadence_is_ok = 0; 14972 } 14973 14974 /* Ring cadences cannot be negative */ 14975 for (i = 0; i < element_count; i++) { 14976 if (c[i] == 0) { 14977 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 14978 cadence_is_ok = 0; 14979 break; 14980 } else if (c[i] < 0) { 14981 if (i % 2 == 1) { 14982 /* Silence duration, negative possibly okay */ 14983 if (cid_location == -1) { 14984 cid_location = i; 14985 c[i] *= -1; 14986 } else { 14987 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 14988 cadence_is_ok = 0; 14989 break; 14990 } 14991 } else { 14992 if (firstcadencepos == 0) { 14993 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 14994 /* duration will be passed negative to the DAHDI driver */ 14995 } else { 14996 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 14997 cadence_is_ok = 0; 14998 break; 14999 } 15000 } 15001 } 15002 } 15003 15004 /* Substitute our scanned cadence */ 15005 for (i = 0; i < 16; i++) { 15006 new_cadence.ringcadence[i] = c[i]; 15007 } 15008 15009 if (cadence_is_ok) { 15010 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 15011 if (element_count < 2) { 15012 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 15013 } else { 15014 if (cid_location == -1) { 15015 /* user didn't say; default to first pause */ 15016 cid_location = 1; 15017 } else { 15018 /* convert element_index to cidrings value */ 15019 cid_location = (cid_location + 1) / 2; 15020 } 15021 /* ---we like their cadence; try to install it--- */ 15022 if (!user_has_defined_cadences++) 15023 /* this is the first user-defined cadence; clear the default user cadences */ 15024 num_cadence = 0; 15025 if ((num_cadence+1) >= NUM_CADENCE_MAX) 15026 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 15027 else { 15028 cadences[num_cadence] = new_cadence; 15029 cidrings[num_cadence++] = cid_location; 15030 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 15031 } 15032 } 15033 } 15034 } else if (!strcasecmp(v->name, "ringtimeout")) { 15035 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 15036 } else if (!strcasecmp(v->name, "prewink")) { 15037 confp->timing.prewinktime = atoi(v->value); 15038 } else if (!strcasecmp(v->name, "preflash")) { 15039 confp->timing.preflashtime = atoi(v->value); 15040 } else if (!strcasecmp(v->name, "wink")) { 15041 confp->timing.winktime = atoi(v->value); 15042 } else if (!strcasecmp(v->name, "flash")) { 15043 confp->timing.flashtime = atoi(v->value); 15044 } else if (!strcasecmp(v->name, "start")) { 15045 confp->timing.starttime = atoi(v->value); 15046 } else if (!strcasecmp(v->name, "rxwink")) { 15047 confp->timing.rxwinktime = atoi(v->value); 15048 } else if (!strcasecmp(v->name, "rxflash")) { 15049 confp->timing.rxflashtime = atoi(v->value); 15050 } else if (!strcasecmp(v->name, "debounce")) { 15051 confp->timing.debouncetime = atoi(v->value); 15052 } else if (!strcasecmp(v->name, "toneduration")) { 15053 int toneduration; 15054 int ctlfd; 15055 int res; 15056 struct dahdi_dialparams dps; 15057 15058 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 15059 if (ctlfd == -1) { 15060 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 15061 return -1; 15062 } 15063 15064 toneduration = atoi(v->value); 15065 if (toneduration > -1) { 15066 memset(&dps, 0, sizeof(dps)); 15067 15068 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 15069 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 15070 if (res < 0) { 15071 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 15072 return -1; 15073 } 15074 } 15075 close(ctlfd); 15076 } else if (!strcasecmp(v->name, "defaultcic")) { 15077 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 15078 } else if (!strcasecmp(v->name, "defaultozz")) { 15079 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 15080 } else if (!strcasecmp(v->name, "mwilevel")) { 15081 mwilevel = atoi(v->value); 15082 } 15083 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 15084 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 15085 } 15086 if (dahdichan[0]) { 15087 /* The user has set 'dahdichan' */ 15088 /*< \todo pass proper line number instead of 0 */ 15089 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 15090 return -1; 15091 } 15092 } 15093 /*< \todo why check for the pseudo in the per-channel section. 15094 * Any actual use for manual setup of the pseudo channel? */ 15095 if (!found_pseudo && reload != 1) { 15096 /* use the default configuration for a channel, so 15097 that any settings from real configured channels 15098 don't "leak" into the pseudo channel config 15099 */ 15100 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 15101 15102 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 15103 15104 if (tmp) { 15105 ast_verb(3, "Automatically generated pseudo channel\n"); 15106 } else { 15107 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 15108 } 15109 } 15110 return 0; 15111 }
| static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
| const char * | data, | |||
| unsigned int | line | |||
| ) | [static] |
Definition at line 14211 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().
14212 { 14213 char *parse = ast_strdupa(data); 14214 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 14215 unsigned int param_count; 14216 unsigned int x; 14217 14218 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 14219 return; 14220 14221 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 14222 14223 /* first parameter is tap length, process it here */ 14224 14225 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 14226 14227 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 14228 confp->chan.echocancel.head.tap_length = x; 14229 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 14230 confp->chan.echocancel.head.tap_length = 128; 14231 14232 /* now process any remaining parameters */ 14233 14234 for (x = 1; x < param_count; x++) { 14235 struct { 14236 char *name; 14237 char *value; 14238 } param; 14239 14240 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 14241 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 14242 continue; 14243 } 14244 14245 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 14246 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 14247 continue; 14248 } 14249 14250 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 14251 14252 if (param.value) { 14253 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 14254 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 14255 continue; 14256 } 14257 } 14258 confp->chan.echocancel.head.param_count++; 14259 } 14260 }
| static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 10837 of file chan_dahdi.c.
Referenced by pri_dchannel().
| static int reload | ( | void | ) | [static] |
Definition at line 15481 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
15482 { 15483 int res = 0; 15484 15485 res = setup_dahdi(1); 15486 if (res) { 15487 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 15488 return -1; 15489 } 15490 return 0; 15491 }
| static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1934 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup().
01935 { 01936 p->confno = -1; 01937 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01938 if (p->subs[SUB_REAL].dfd > -1) { 01939 struct dahdi_confinfo zi; 01940 01941 memset(&zi, 0, sizeof(zi)); 01942 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01943 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01944 } 01945 return 0; 01946 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 8534 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().
08535 { 08536 /* If we're supposed to be stopped -- stay stopped */ 08537 if (monitor_thread == AST_PTHREADT_STOP) 08538 return 0; 08539 ast_mutex_lock(&monlock); 08540 if (monitor_thread == pthread_self()) { 08541 ast_mutex_unlock(&monlock); 08542 ast_log(LOG_WARNING, "Cannot kill myself\n"); 08543 return -1; 08544 } 08545 if (monitor_thread != AST_PTHREADT_NULL) { 08546 /* Wake up the thread */ 08547 pthread_kill(monitor_thread, SIGURG); 08548 } else { 08549 /* Start a new monitor */ 08550 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 08551 ast_mutex_unlock(&monlock); 08552 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 08553 return -1; 08554 } 08555 } 08556 ast_mutex_unlock(&monlock); 08557 return 0; 08558 }
| static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2313 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_read(), and send_callerid().
02314 { 02315 int res; 02316 if (p->saveconf.confmode) { 02317 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02318 p->saveconf.confmode = 0; 02319 if (res) { 02320 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02321 return -1; 02322 } 02323 } 02324 ast_debug(1, "Restored conferencing\n"); 02325 return 0; 02326 }
| static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2194 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::dfd, errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by dahdi_hangup(), mwi_thread(), and ss_thread().
02195 { 02196 int res; 02197 02198 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02199 if (res) { 02200 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02201 return -1; 02202 } 02203 02204 return 0; 02205 }
| static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2240 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::dfd, errno, LOG_WARNING, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), and dahdi_handle_event().
02241 { 02242 struct dahdi_confinfo c; 02243 int res; 02244 if (p->saveconf.confmode) { 02245 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02246 return -1; 02247 } 02248 p->saveconf.chan = 0; 02249 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02250 if (res) { 02251 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02252 p->saveconf.confmode = 0; 02253 return -1; 02254 } 02255 memset(&c, 0, sizeof(c)); 02256 c.confmode = DAHDI_CONF_NORMAL; 02257 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02258 if (res) { 02259 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02260 return -1; 02261 } 02262 ast_debug(1, "Disabled conferencing\n"); 02263 return 0; 02264 }
| static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2370 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), dahdi_subchannel::dfd, errno, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_read(), and send_cwcidspill().
02371 { 02372 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 02373 int res; 02374 /* Take out of linear mode if necessary */ 02375 if (p->subs[SUB_REAL].linear) { 02376 p->subs[SUB_REAL].linear = 0; 02377 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 02378 } 02379 while (p->cidpos < p->cidlen) { 02380 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 02381 if (res < 0) { 02382 if (errno == EAGAIN) 02383 return 0; 02384 else { 02385 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 02386 return -1; 02387 } 02388 } 02389 if (!res) 02390 return 0; 02391 p->cidpos += res; 02392 } 02393 ast_free(p->cidspill); 02394 p->cidspill = NULL; 02395 if (p->callwaitcas) { 02396 /* Wait for CID/CW to expire */ 02397 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 02398 } else 02399 restore_conference(p); 02400 return 0; 02401 }
| static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2330 of file chan_dahdi.c.
References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verb, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, READ_SIZE, and send_callerid().
Referenced by dahdi_handle_dtmfup().
02331 { 02332 p->callwaitcas = 0; 02333 p->cidcwexpire = 0; 02334 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02335 return -1; 02336 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02337 /* Make sure we account for the end */ 02338 p->cidlen += READ_SIZE * 4; 02339 p->cidpos = 0; 02340 send_callerid(p); 02341 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02342 return 0; 02343 }
| static int set_actual_gain | ( | int | fd, | |
| int | chan, | |||
| float | rxgain, | |||
| float | txgain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2175 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), mkintf(), pri_dchannel(), and restore_gains().
02176 { 02177 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02178 }
| static int set_actual_rxgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2157 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02158 { 02159 struct dahdi_gains g; 02160 int res; 02161 02162 memset(&g, 0, sizeof(g)); 02163 g.chan = chan; 02164 res = ioctl(fd, DAHDI_GETGAINS, &g); 02165 if (res) { 02166 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02167 return res; 02168 } 02169 02170 fill_rxgain(&g, gain, law); 02171 02172 return ioctl(fd, DAHDI_SETGAINS, &g); 02173 }
| static int set_actual_txgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2139 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02140 { 02141 struct dahdi_gains g; 02142 int res; 02143 02144 memset(&g, 0, sizeof(g)); 02145 g.chan = chan; 02146 res = ioctl(fd, DAHDI_GETGAINS, &g); 02147 if (res) { 02148 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02149 return res; 02150 } 02151 02152 fill_txgain(&g, gain, law); 02153 02154 return ioctl(fd, DAHDI_SETGAINS, &g); 02155 }
| static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 15113 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().
15114 { 15115 struct ast_config *cfg, *ucfg; 15116 struct ast_variable *v; 15117 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 15118 struct dahdi_chan_conf conf; 15119 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 15120 const char *cat; 15121 int res; 15122 15123 #ifdef HAVE_PRI 15124 char *c; 15125 int spanno; 15126 int i; 15127 int logicalspan; 15128 int trunkgroup; 15129 int dchannels[NUM_DCHANS]; 15130 #endif 15131 15132 cfg = ast_config_load(config, config_flags); 15133 15134 /* Error if we have no config file */ 15135 if (!cfg) { 15136 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 15137 return 0; 15138 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 15139 ucfg = ast_config_load("users.conf", config_flags); 15140 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 15141 return 0; 15142 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15143 cfg = ast_config_load(config, config_flags); 15144 } else { 15145 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 15146 ucfg = ast_config_load("users.conf", config_flags); 15147 } 15148 15149 /* It's a little silly to lock it, but we mind as well just to be sure */ 15150 ast_mutex_lock(&iflock); 15151 #ifdef HAVE_PRI 15152 if (reload != 1) { 15153 /* Process trunkgroups first */ 15154 v = ast_variable_browse(cfg, "trunkgroups"); 15155 while (v) { 15156 if (!strcasecmp(v->name, "trunkgroup")) { 15157 trunkgroup = atoi(v->value); 15158 if (trunkgroup > 0) { 15159 if ((c = strchr(v->value, ','))) { 15160 i = 0; 15161 memset(dchannels, 0, sizeof(dchannels)); 15162 while (c && (i < NUM_DCHANS)) { 15163 dchannels[i] = atoi(c + 1); 15164 if (dchannels[i] < 0) { 15165 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); 15166 } else 15167 i++; 15168 c = strchr(c + 1, ','); 15169 } 15170 if (i) { 15171 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 15172 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); 15173 } else 15174 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"); 15175 } else 15176 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15177 } else 15178 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 15179 } else 15180 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 15181 } else if (!strcasecmp(v->name, "spanmap")) { 15182 spanno = atoi(v->value); 15183 if (spanno > 0) { 15184 if ((c = strchr(v->value, ','))) { 15185 trunkgroup = atoi(c + 1); 15186 if (trunkgroup > 0) { 15187 if ((c = strchr(c + 1, ','))) 15188 logicalspan = atoi(c + 1); 15189 else 15190 logicalspan = 0; 15191 if (logicalspan >= 0) { 15192 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 15193 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15194 } else 15195 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 15196 } else 15197 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); 15198 } else 15199 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 15200 } else 15201 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 15202 } else 15203 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 15204 } else { 15205 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 15206 } 15207 v = v->next; 15208 } 15209 } 15210 #endif 15211 15212 /* Copy the default jb config over global_jbconf */ 15213 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 15214 15215 mwimonitornotify[0] = '\0'; 15216 15217 v = ast_variable_browse(cfg, "channels"); 15218 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) { 15219 ast_mutex_unlock(&iflock); 15220 ast_config_destroy(cfg); 15221 if (ucfg) { 15222 ast_config_destroy(ucfg); 15223 } 15224 return res; 15225 } 15226 15227 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 15228 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 15229 /* [channels] and [trunkgroups] are used. Let's also reserve 15230 * [globals] and [general] for future use 15231 */ 15232 if (!strcasecmp(cat, "general") || 15233 !strcasecmp(cat, "trunkgroups") || 15234 !strcasecmp(cat, "globals") || 15235 !strcasecmp(cat, "channels")) { 15236 continue; 15237 } 15238 15239 memcpy(&conf, &base_conf, sizeof(conf)); 15240 15241 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 15242 ast_mutex_unlock(&iflock); 15243 ast_config_destroy(cfg); 15244 if (ucfg) { 15245 ast_config_destroy(cfg); 15246 } 15247 return res; 15248 } 15249 } 15250 15251 ast_config_destroy(cfg); 15252 15253 if (ucfg) { 15254 const char *chans; 15255 15256 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0); 15257 15258 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 15259 if (!strcasecmp(cat, "general")) { 15260 continue; 15261 } 15262 15263 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 15264 15265 if (ast_strlen_zero(chans)) { 15266 continue; 15267 } 15268 15269 memcpy(&conf, &base_conf, sizeof(conf)); 15270 15271 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 15272 ast_config_destroy(ucfg); 15273 ast_mutex_unlock(&iflock); 15274 return res; 15275 } 15276 } 15277 ast_config_destroy(ucfg); 15278 } 15279 ast_mutex_unlock(&iflock); 15280 15281 #ifdef HAVE_PRI 15282 if (reload != 1) { 15283 int x; 15284 for (x = 0; x < NUM_SPANS; x++) { 15285 if (pris[x].pvts[0]) { 15286 if (start_pri(pris + x)) { 15287 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 15288 return -1; 15289 } else 15290 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 15291 } 15292 } 15293 } 15294 #endif 15295 #ifdef HAVE_SS7 15296 if (reload != 1) { 15297 int x; 15298 for (x = 0; x < NUM_SPANS; x++) { 15299 if (linksets[x].ss7) { 15300 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) { 15301 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 15302 return -1; 15303 } else 15304 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 15305 } 15306 } 15307 } 15308 #endif 15309 /* And start the monitor for the first time */ 15310 restart_monitor(); 15311 return 0; 15312 }
| static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
Definition at line 8713 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 9944 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().
09945 { 09946 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 09947 if (size) { 09948 *buf = '\0'; 09949 } 09950 return; 09951 } 09952 switch (nai) { 09953 case SS7_NAI_INTERNATIONAL: 09954 snprintf(buf, size, "%s%s", ss7->internationalprefix, number); 09955 break; 09956 case SS7_NAI_NATIONAL: 09957 snprintf(buf, size, "%s%s", ss7->nationalprefix, number); 09958 break; 09959 case SS7_NAI_SUBSCRIBER: 09960 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number); 09961 break; 09962 case SS7_NAI_UNKNOWN: 09963 snprintf(buf, size, "%s%s", ss7->unknownprefix, number); 09964 break; 09965 default: 09966 snprintf(buf, size, "%s", number); 09967 break; 09968 } 09969 }
| 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 9763 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().
09764 { 09765 int i; 09766 09767 for (i = 0; i < linkset->numchans; i++) { 09768 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 09769 if (state) { 09770 if (state[i]) 09771 linkset->pvts[i]->remotelyblocked = block; 09772 } else 09773 linkset->pvts[i]->remotelyblocked = block; 09774 } 09775 } 09776 }
| static int ss7_find_cic | ( | struct dahdi_ss7 * | linkset, | |
| int | cic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9718 of file chan_dahdi.c.
References dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_ss7::numchans, and dahdi_ss7::pvts.
Referenced by ss7_linkset().
Definition at line 1250 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_ss7::lock, and dahdi_ss7::master.
Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().
01251 { 01252 int res; 01253 /* Grab the lock first */ 01254 do { 01255 res = ast_mutex_trylock(&pri->lock); 01256 if (res) { 01257 DEADLOCK_AVOIDANCE(&pvt->lock); 01258 } 01259 } while (res); 01260 /* Then break the poll */ 01261 if (pri->master != AST_PTHREADT_NULL) 01262 pthread_kill(pri->master, SIGURG); 01263 return 0; 01264 }
| static void ss7_handle_cqm | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9731 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().
09732 { 09733 unsigned char status[32]; 09734 struct dahdi_pvt *p = NULL; 09735 int i, offset; 09736 09737 for (i = 0; i < linkset->numchans; i++) { 09738 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 09739 p = linkset->pvts[i]; 09740 offset = p->cic - startcic; 09741 status[offset] = 0; 09742 if (p->locallyblocked) 09743 status[offset] |= (1 << 0) | (1 << 4); 09744 if (p->remotelyblocked) 09745 status[offset] |= (1 << 1) | (1 << 5); 09746 if (p->ss7call) { 09747 if (p->outgoing) 09748 status[offset] |= (1 << 3); 09749 else 09750 status[offset] |= (1 << 2); 09751 } else 09752 status[offset] |= 0x3 << 2; 09753 } 09754 } 09755 09756 if (p) 09757 isup_cqr(linkset->ss7, startcic, endcic, dpc, status); 09758 else 09759 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n"); 09760 09761 }
| static void ss7_inservice | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 9778 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 9975 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().
09976 { 09977 int res, i; 09978 struct timeval *next = NULL, tv; 09979 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data; 09980 struct ss7 *ss7 = linkset->ss7; 09981 ss7_event *e = NULL; 09982 struct dahdi_pvt *p; 09983 int chanpos; 09984 struct pollfd pollers[NUM_DCHANS]; 09985 int cic; 09986 unsigned int dpc; 09987 int nextms = 0; 09988 09989 ss7_start(ss7); 09990 09991 while(1) { 09992 ast_mutex_lock(&linkset->lock); 09993 if ((next = ss7_schedule_next(ss7))) { 09994 tv = ast_tvnow(); 09995 tv.tv_sec = next->tv_sec - tv.tv_sec; 09996 tv.tv_usec = next->tv_usec - tv.tv_usec; 09997 if (tv.tv_usec < 0) { 09998 tv.tv_usec += 1000000; 09999 tv.tv_sec -= 1; 10000 } 10001 if (tv.tv_sec < 0) { 10002 tv.tv_sec = 0; 10003 tv.tv_usec = 0; 10004 } 10005 nextms = tv.tv_sec * 1000; 10006 nextms += tv.tv_usec / 1000; 10007 } 10008 ast_mutex_unlock(&linkset->lock); 10009 10010 for (i = 0; i < linkset->numsigchans; i++) { 10011 pollers[i].fd = linkset->fds[i]; 10012 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]); 10013 pollers[i].revents = 0; 10014 } 10015 10016 res = poll(pollers, linkset->numsigchans, nextms); 10017 if ((res < 0) && (errno != EINTR)) { 10018 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno)); 10019 } else if (!res) { 10020 ast_mutex_lock(&linkset->lock); 10021 ss7_schedule_run(ss7); 10022 ast_mutex_unlock(&linkset->lock); 10023 continue; 10024 } 10025 10026 ast_mutex_lock(&linkset->lock); 10027 for (i = 0; i < linkset->numsigchans; i++) { 10028 if (pollers[i].revents & POLLPRI) { 10029 int x; 10030 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) { 10031 ast_log(LOG_ERROR, "Error in exception retrieval!\n"); 10032 } 10033 switch (x) { 10034 case DAHDI_EVENT_OVERRUN: 10035 ast_debug(1, "Overrun detected!\n"); 10036 break; 10037 case DAHDI_EVENT_BADFCS: 10038 ast_debug(1, "Bad FCS\n"); 10039 break; 10040 case DAHDI_EVENT_ABORT: 10041 ast_debug(1, "HDLC Abort\n"); 10042 break; 10043 case DAHDI_EVENT_ALARM: 10044 ast_log(LOG_ERROR, "Alarm on link!\n"); 10045 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM); 10046 linkset->linkstate[i] &= ~LINKSTATE_UP; 10047 ss7_link_alarm(ss7, pollers[i].fd); 10048 break; 10049 case DAHDI_EVENT_NOALARM: 10050 ast_log(LOG_ERROR, "Alarm cleared on link\n"); 10051 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN); 10052 linkset->linkstate[i] |= LINKSTATE_STARTING; 10053 ss7_link_noalarm(ss7, pollers[i].fd); 10054 break; 10055 default: 10056 ast_log(LOG_ERROR, "Got exception %d!\n", x); 10057 break; 10058 } 10059 } 10060 10061 if (pollers[i].revents & POLLIN) { 10062 ast_mutex_lock(&linkset->lock); 10063 res = ss7_read(ss7, pollers[i].fd); 10064 ast_mutex_unlock(&linkset->lock); 10065 } 10066 10067 if (pollers[i].revents & POLLOUT) { 10068 ast_mutex_lock(&linkset->lock); 10069 res = ss7_write(ss7, pollers[i].fd); 10070 ast_mutex_unlock(&linkset->lock); 10071 if (res < 0) { 10072 ast_debug(1, "Error in write %s\n", strerror(errno)); 10073 } 10074 } 10075 } 10076 10077 while ((e = ss7_check_event(ss7))) { 10078 switch (e->e) { 10079 case SS7_EVENT_UP: 10080 if (linkset->state != LINKSET_STATE_UP) { 10081 ast_verbose("--- SS7 Up ---\n"); 10082 ss7_reset_linkset(linkset); 10083 } 10084 linkset->state = LINKSET_STATE_UP; 10085 break; 10086 case SS7_EVENT_DOWN: 10087 ast_verbose("--- SS7 Down ---\n"); 10088 linkset->state = LINKSET_STATE_DOWN; 10089 for (i = 0; i < linkset->numchans; i++) { 10090 struct dahdi_pvt *p = linkset->pvts[i]; 10091 if (p) 10092 p->inalarm = 1; 10093 } 10094 break; 10095 case MTP2_LINK_UP: 10096 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data); 10097 break; 10098 case MTP2_LINK_DOWN: 10099 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data); 10100 break; 10101 case ISUP_EVENT_CPG: 10102 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc); 10103 if (chanpos < 0) { 10104 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic); 10105 break; 10106 } 10107 p = linkset->pvts[chanpos]; 10108 ast_mutex_lock(&p->lock); 10109 switch (e->cpg.event) { 10110 case CPG_EVENT_ALERTING: 10111 p->alerting = 1; 10112 p->subs[SUB_REAL].needringing = 1; 10113 break; 10114 case CPG_EVENT_PROGRESS: 10115 case CPG_EVENT_INBANDINFO: 10116 { 10117 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 10118 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic); 10119 dahdi_queue_frame(p, &f, linkset); 10120 p->progress = 1; 10121 p->dialing = 0; 10122 if (p->dsp && p->dsp_features) { 10123 ast_dsp_set_features(p->dsp, p->dsp_features); 10124 p->dsp_features = 0; 10125 } 10126 } 10127 break; 10128 default: 10129 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event); 10130 } 10131 10132 ast_mutex_unlock(&p->lock); 10133 break; 10134 case ISUP_EVENT_RSC: 10135 ast_verbose("Resetting CIC %d\n", e->rsc.cic); 10136 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc); 10137 if (chanpos < 0) { 10138 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic); 10139 break; 10140 } 10141 p = linkset->pvts[chanpos]; 10142 ast_mutex_lock(&p->lock); 10143 p->inservice = 1; 10144 p->remotelyblocked = 0; 10145 dpc = p->dpc; 10146 isup_set_call_dpc(e->rsc.call, dpc); 10147 if (p->ss7call) 10148 p->ss7call = NULL; 10149 if (p->owner) 10150 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10151 ast_mutex_unlock(&p->lock); 10152 isup_rlc(ss7, e->rsc.call); 10153 break; 10154 case ISUP_EVENT_GRS: 10155 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic); 10156 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc); 10157 if (chanpos < 0) { 10158 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic); 10159 break; 10160 } 10161 p = linkset->pvts[chanpos]; 10162 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc); 10163 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0); 10164 break; 10165 case ISUP_EVENT_CQM: 10166 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic); 10167 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc); 10168 break; 10169 case ISUP_EVENT_GRA: 10170 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic); 10171 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc); 10172 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1); 10173 break; 10174 case ISUP_EVENT_IAM: 10175 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); 10176 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc); 10177 if (chanpos < 0) { 10178 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic); 10179 isup_rel(ss7, e->iam.call, -1); 10180 break; 10181 } 10182 p = linkset->pvts[chanpos]; 10183 ast_mutex_lock(&p->lock); 10184 if (p->owner) { 10185 if (p->ss7call == e->iam.call) { 10186 ast_mutex_unlock(&p->lock); 10187 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic); 10188 break; 10189 } else { 10190 ast_mutex_unlock(&p->lock); 10191 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic); 10192 break; 10193 } 10194 } 10195 10196 dpc = p->dpc; 10197 p->ss7call = e->iam.call; 10198 isup_set_call_dpc(p->ss7call, dpc); 10199 10200 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) { 10201 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai); 10202 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind); 10203 } else 10204 p->cid_num[0] = 0; 10205 10206 if (p->immediate) { 10207 p->exten[0] = 's'; 10208 p->exten[1] = '\0'; 10209 } else if (!ast_strlen_zero(e->iam.called_party_num)) { 10210 char *st; 10211 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai); 10212 st = strchr(p->exten, '#'); 10213 if (st) 10214 *st = '\0'; 10215 } else 10216 p->exten[0] = '\0'; 10217 10218 p->cid_ani[0] = '\0'; 10219 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name))) 10220 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name)); 10221 else 10222 p->cid_name[0] = '\0'; 10223 10224 p->cid_ani2 = e->iam.oli_ani2; 10225 p->cid_ton = 0; 10226 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number)); 10227 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number)); 10228 p->gen_add_type = e->iam.gen_add_type; 10229 p->gen_add_nai = e->iam.gen_add_nai; 10230 p->gen_add_pres_ind = e->iam.gen_add_pres_ind; 10231 p->gen_add_num_plan = e->iam.gen_add_num_plan; 10232 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number)); 10233 p->gen_dig_type = e->iam.gen_dig_type; 10234 p->gen_dig_scheme = e->iam.gen_dig_scheme; 10235 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number)); 10236 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num)); 10237 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num)); 10238 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name)); 10239 p->calling_party_cat = e->iam.calling_party_cat; 10240 10241 /* Set DNID */ 10242 if (!ast_strlen_zero(e->iam.called_party_num)) 10243 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai); 10244 10245 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 10246 10247 if (e->iam.cot_check_required) { 10248 dahdi_loopback(p, 1); 10249 } else 10250 ss7_start_call(p, linkset); 10251 } else { 10252 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten); 10253 p->alreadyhungup = 1; 10254 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED); 10255 } 10256 ast_mutex_unlock(&p->lock); 10257 break; 10258 case ISUP_EVENT_COT: 10259 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc); 10260 if (chanpos < 0) { 10261 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic); 10262 isup_rel(ss7, e->cot.call, -1); 10263 break; 10264 } 10265 p = linkset->pvts[chanpos]; 10266 10267 ast_mutex_lock(&p->lock); 10268 10269 if (p->loopedback) { 10270 dahdi_loopback(p, 0); 10271 ss7_start_call(p, linkset); 10272 } 10273 10274 ast_mutex_unlock(&p->lock); 10275 10276 break; 10277 case ISUP_EVENT_CCR: 10278 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic); 10279 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc); 10280 if (chanpos < 0) { 10281 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic); 10282 break; 10283 } 10284 10285 p = linkset->pvts[chanpos]; 10286 10287 ast_mutex_lock(&p->lock); 10288 dahdi_loopback(p, 1); 10289 ast_mutex_unlock(&p->lock); 10290 10291 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc); 10292 break; 10293 case ISUP_EVENT_CVT: 10294 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic); 10295 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc); 10296 if (chanpos < 0) { 10297 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic); 10298 break; 10299 } 10300 10301 p = linkset->pvts[chanpos]; 10302 10303 ast_mutex_lock(&p->lock); 10304 dahdi_loopback(p, 1); 10305 ast_mutex_unlock(&p->lock); 10306 10307 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc); 10308 break; 10309 case ISUP_EVENT_REL: 10310 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc); 10311 if (chanpos < 0) { 10312 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic); 10313 break; 10314 } 10315 p = linkset->pvts[chanpos]; 10316 ast_mutex_lock(&p->lock); 10317 if (p->owner) { 10318 p->owner->hangupcause = e->rel.cause; 10319 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 10320 } else if (!p->restartpending) 10321 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic); 10322 10323 /* End the loopback if we have one */ 10324 dahdi_loopback(p, 0); 10325 10326 isup_rlc(ss7, e->rel.call); 10327 p->ss7call = NULL; 10328 10329 ast_mutex_unlock(&p->lock); 10330 break; 10331 case ISUP_EVENT_ACM: 10332 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc); 10333 if (chanpos < 0) { 10334 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic); 10335 isup_rel(ss7, e->acm.call, -1); 10336 break; 10337 } else { 10338 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 10339 10340 p = linkset->pvts[chanpos]; 10341 10342 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic); 10343 10344 if (e->acm.call_ref_ident > 0) { 10345 p->rlt = 1; /* Setting it but not using it here*/ 10346 } 10347 10348 ast_mutex_lock(&p->lock); 10349 dahdi_queue_frame(p, &f, linkset); 10350 p->proceeding = 1; 10351 p->dialing = 0; 10352 /* Send alerting if subscriber is free */ 10353 if (e->acm.called_party_status_ind == 1) { 10354 p->alerting = 1; 10355 p->subs[SUB_REAL].needringing = 1; 10356 } 10357 ast_mutex_unlock(&p->lock); 10358 } 10359 break; 10360 case ISUP_EVENT_CGB: 10361 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc); 10362 if (chanpos < 0) { 10363 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic); 10364 break; 10365 } 10366 p = linkset->pvts[chanpos]; 10367 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1); 10368 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type); 10369 break; 10370 case ISUP_EVENT_CGU: 10371 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc); 10372 if (chanpos < 0) { 10373 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic); 10374 break; 10375 } 10376 p = linkset->pvts[chanpos]; 10377 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0); 10378 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type); 10379 break; 10380 case ISUP_EVENT_UCIC: 10381 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc); 10382 if (chanpos < 0) { 10383 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic); 10384 break; 10385 } 10386 p = linkset->pvts[chanpos]; 10387 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic); 10388 ast_mutex_lock(&p->lock); 10389 p->remotelyblocked = 1; 10390 p->inservice = 0; 10391 ast_mutex_unlock(&p->lock); //doesn't require a SS7 acknowledgement 10392 break; 10393 case ISUP_EVENT_BLO: 10394 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc); 10395 if (chanpos < 0) { 10396 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic); 10397 break; 10398 } 10399 p = linkset->pvts[chanpos]; 10400 ast_debug(1, "Blocking CIC %d\n", e->blo.cic); 10401 ast_mutex_lock(&p->lock); 10402 p->remotelyblocked = 1; 10403 ast_mutex_unlock(&p->lock); 10404 isup_bla(linkset->ss7, e->blo.cic, p->dpc); 10405 break; 10406 case ISUP_EVENT_BLA: 10407 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc); 10408 if (chanpos < 0) { 10409 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic); 10410 break; 10411 } 10412 ast_debug(1, "Blocking CIC %d\n", e->bla.cic); 10413 p = linkset->pvts[chanpos]; 10414 ast_mutex_lock(&p->lock); 10415 p->locallyblocked = 1; 10416 ast_mutex_unlock(&p->lock); 10417 break; 10418 case ISUP_EVENT_UBL: 10419 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc); 10420 if (chanpos < 0) { 10421 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic); 10422 break; 10423 } 10424 p = linkset->pvts[chanpos]; 10425 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic); 10426 ast_mutex_lock(&p->lock); 10427 p->remotelyblocked = 0; 10428 ast_mutex_unlock(&p->lock); 10429 isup_uba(linkset->ss7, e->ubl.cic, p->dpc); 10430 break; 10431 case ISUP_EVENT_UBA: 10432 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc); 10433 if (chanpos < 0) { 10434 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic); 10435 break; 10436 } 10437 p = linkset->pvts[chanpos]; 10438 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic); 10439 ast_mutex_lock(&p->lock); 10440 p->locallyblocked = 0; 10441 ast_mutex_unlock(&p->lock); 10442 break; 10443 case ISUP_EVENT_CON: 10444 case ISUP_EVENT_ANM: 10445 if (e->e == ISUP_EVENT_CON) 10446 cic = e->con.cic; 10447 else 10448 cic = e->anm.cic; 10449 10450 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc); 10451 if (chanpos < 0) { 10452 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic); 10453 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1); 10454 break; 10455 } else { 10456 p = linkset->pvts[chanpos]; 10457 ast_mutex_lock(&p->lock); 10458 p->subs[SUB_REAL].needanswer = 1; 10459 if (p->dsp && p->dsp_features) { 10460 ast_dsp_set_features(p->dsp, p->dsp_features); 10461 p->dsp_features = 0; 10462 } 10463 dahdi_enable_ec(p); 10464 ast_mutex_unlock(&p->lock); 10465 } 10466 break; 10467 case ISUP_EVENT_RLC: 10468 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc); 10469 if (chanpos < 0) { 10470 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic); 10471 break; 10472 } else { 10473 p = linkset->pvts[chanpos]; 10474 ast_mutex_lock(&p->lock); 10475 if (p->alreadyhungup) 10476 p->ss7call = NULL; 10477 else 10478 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n"); 10479 ast_mutex_unlock(&p->lock); 10480 } 10481 break; 10482 case ISUP_EVENT_FAA: 10483 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc); 10484 if (chanpos < 0) { 10485 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic); 10486 break; 10487 } else { 10488 p = linkset->pvts[chanpos]; 10489 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic); 10490 ast_mutex_lock(&p->lock); 10491 if (p->alreadyhungup){ 10492 p->ss7call = NULL; 10493 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n"); 10494 } 10495 ast_mutex_unlock(&p->lock); 10496 } 10497 break; 10498 default: 10499 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e)); 10500 break; 10501 } 10502 } 10503 ast_mutex_unlock(&linkset->lock); 10504 } 10505 10506 return 0; 10507 }
| static int ss7_pres_scr2cid_pres | ( | char | presentation_ind, | |
| char | screening_ind | |||
| ) | [static] |
Definition at line 9970 of file chan_dahdi.c.
Referenced by ss7_linkset().
| static void ss7_rel | ( | struct dahdi_ss7 * | ss7 | ) | [inline, static] |
Definition at line 1245 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_ss7::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().
01246 { 01247 ast_mutex_unlock(&ss7->lock); 01248 }
| static void ss7_reset_linkset | ( | struct dahdi_ss7 * | linkset | ) | [static] |
Definition at line 9788 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().
09789 { 09790 int i, startcic = -1, endcic, dpc; 09791 09792 if (linkset->numchans <= 0) 09793 return; 09794 09795 startcic = linkset->pvts[0]->cic; 09796 /* DB: CIC's DPC fix */ 09797 dpc = linkset->pvts[0]->dpc; 09798 09799 for (i = 0; i < linkset->numchans; i++) { 09800 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)) { 09801 continue; 09802 } else { 09803 endcic = linkset->pvts[i]->cic; 09804 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic); 09805 isup_grs(linkset->ss7, startcic, endcic, dpc); 09806 09807 /* DB: CIC's DPC fix */ 09808 if (linkset->pvts[i+1]) { 09809 startcic = linkset->pvts[i+1]->cic; 09810 dpc = linkset->pvts[i+1]->dpc; 09811 } 09812 } 09813 } 09814 }
| static struct dahdi_ss7* ss7_resolve_linkset | ( | int | linkset | ) | [static, read] |
Definition at line 8699 of file chan_dahdi.c.
References linksets, and NUM_SPANS.
Referenced by linkset_addsigchan(), mkintf(), and process_dahdi().
Definition at line 9828 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().
09829 { 09830 struct ss7 *ss7 = linkset->ss7; 09831 int res; 09832 int law = 1; 09833 struct ast_channel *c; 09834 char tmp[256]; 09835 09836 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 09837 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno)); 09838 09839 if (linkset->type == SS7_ITU) 09840 law = DAHDI_LAW_ALAW; 09841 else 09842 law = DAHDI_LAW_MULAW; 09843 09844 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law); 09845 if (res < 0) 09846 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel); 09847 09848 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) { 09849 p->proceeding = 1; 09850 isup_acm(ss7, p->ss7call); 09851 } 09852 09853 ast_mutex_unlock(&linkset->lock); 09854 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0); 09855 09856 if (!c) { 09857 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic); 09858 /* Holding this lock is assumed entering the function */ 09859 ast_mutex_lock(&linkset->lock); 09860 return; 09861 } else 09862 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic); 09863 09864 dahdi_enable_ec(p); 09865 09866 /* We only reference these variables in the context of the ss7_linkset function 09867 * when receiving either and IAM or a COT message. Since they are only accessed 09868 * from this context, we should be safe to unlock around them */ 09869 09870 ast_mutex_unlock(&p->lock); 09871 09872 if (!ast_strlen_zero(p->charge_number)) { 09873 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number); 09874 /* Clear this after we set it */ 09875 p->charge_number[0] = 0; 09876 } 09877 if (!ast_strlen_zero(p->gen_add_number)) { 09878 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number); 09879 /* Clear this after we set it */ 09880 p->gen_add_number[0] = 0; 09881 } 09882 if (!ast_strlen_zero(p->jip_number)) { 09883 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number); 09884 /* Clear this after we set it */ 09885 p->jip_number[0] = 0; 09886 } 09887 if (!ast_strlen_zero(p->gen_dig_number)) { 09888 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number); 09889 /* Clear this after we set it */ 09890 p->gen_dig_number[0] = 0; 09891 } 09892 if (!ast_strlen_zero(p->orig_called_num)) { 09893 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num); 09894 /* Clear this after we set it */ 09895 p->orig_called_num[0] = 0; 09896 } 09897 09898 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type); 09899 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp); 09900 /* Clear this after we set it */ 09901 p->gen_dig_type = 0; 09902 09903 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme); 09904 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp); 09905 /* Clear this after we set it */ 09906 p->gen_dig_scheme = 0; 09907 09908 if (!ast_strlen_zero(p->lspi_ident)) { 09909 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident); 09910 /* Clear this after we set it */ 09911 p->lspi_ident[0] = 0; 09912 } 09913 09914 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident); 09915 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp); 09916 /* Clear this after we set it */ 09917 p->call_ref_ident = 0; 09918 09919 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc); 09920 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp); 09921 /* Clear this after we set it */ 09922 p->call_ref_pc = 0; 09923 09924 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat); 09925 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp); 09926 /* Clear this after we set it */ 09927 p->calling_party_cat = 0; 09928 09929 if (!ast_strlen_zero(p->redirecting_num)) { 09930 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num); 09931 /* Clear this after we set it */ 09932 p->redirecting_num[0] = 0; 09933 } 09934 if (!ast_strlen_zero(p->generic_name)) { 09935 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name); 09936 /* Clear this after we set it */ 09937 p->generic_name[0] = 0; 09938 } 09939 09940 ast_mutex_lock(&p->lock); 09941 ast_mutex_lock(&linkset->lock); 09942 }
| static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 6553 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, ast_cond_signal(), AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_free, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_destroy(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), ASTOBJ_UNREF, buf, bump_gains(), dahdi_pvt::call, dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, chan, dahdi_pvt::channel, ast_channel::cid, CID_MSGWAITING, ast_callerid::cid_name, dahdi_pvt::cid_name, CID_NOMSGWAITING, ast_callerid::cid_num, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, dahdi_pvt::exten, exten, f, ast_frame::frametype, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_rpas, my_getsigstr(), name, NEED_MFDETECT, notify_message(), dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::pri, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_lock, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, and dahdi_pvt::usedistinctiveringdetection.
Referenced by dahdi_handle_event(), handle_init_event(), mwi_thread(), and pri_dchannel().
06554 { 06555 struct ast_channel *chan = data; 06556 struct dahdi_pvt *p = chan->tech_pvt; 06557 char exten[AST_MAX_EXTENSION] = ""; 06558 char exten2[AST_MAX_EXTENSION] = ""; 06559 unsigned char buf[256]; 06560 char dtmfcid[300]; 06561 char dtmfbuf[300]; 06562 struct callerid_state *cs = NULL; 06563 char *name = NULL, *number = NULL; 06564 int distMatches; 06565 int curRingData[3]; 06566 int receivedRingT; 06567 int counter1; 06568 int counter; 06569 int samples = 0; 06570 struct ast_smdi_md_message *smdi_msg = NULL; 06571 int flags = 0; 06572 int i; 06573 int timeout; 06574 int getforward = 0; 06575 char *s1, *s2; 06576 int len = 0; 06577 int res; 06578 int idx; 06579 06580 ast_mutex_lock(&ss_thread_lock); 06581 ss_thread_count++; 06582 ast_mutex_unlock(&ss_thread_lock); 06583 /* in the bizarre case where the channel has become a zombie before we 06584 even get started here, abort safely 06585 */ 06586 if (!p) { 06587 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 06588 ast_hangup(chan); 06589 goto quit; 06590 } 06591 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 06592 idx = dahdi_get_index(chan, p, 1); 06593 if (idx < 0) { 06594 ast_log(LOG_WARNING, "Huh?\n"); 06595 ast_hangup(chan); 06596 goto quit; 06597 } 06598 if (p->dsp) 06599 ast_dsp_digitreset(p->dsp); 06600 switch (p->sig) { 06601 #ifdef HAVE_PRI 06602 case SIG_PRI: 06603 case SIG_BRI: 06604 case SIG_BRI_PTMP: 06605 /* Now loop looking for an extension */ 06606 ast_copy_string(exten, p->exten, sizeof(exten)); 06607 len = strlen(exten); 06608 res = 0; 06609 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06610 if (len && !ast_ignore_pattern(chan->context, exten)) 06611 tone_zone_play_tone(p->subs[idx].dfd, -1); 06612 else 06613 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06614 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 06615 timeout = matchdigittimeout; 06616 else 06617 timeout = gendigittimeout; 06618 res = ast_waitfordigit(chan, timeout); 06619 if (res < 0) { 06620 ast_debug(1, "waitfordigit returned < 0...\n"); 06621 ast_hangup(chan); 06622 goto quit; 06623 } else if (res) { 06624 exten[len++] = res; 06625 exten[len] = '\0'; 06626 } else 06627 break; 06628 } 06629 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 06630 if (ast_strlen_zero(exten)) { 06631 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n"); 06632 exten[0] = 's'; 06633 exten[1] = '\0'; 06634 } 06635 tone_zone_play_tone(p->subs[idx].dfd, -1); 06636 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 06637 /* Start the real PBX */ 06638 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06639 if (p->dsp) ast_dsp_digitreset(p->dsp); 06640 dahdi_enable_ec(p); 06641 ast_setstate(chan, AST_STATE_RING); 06642 res = ast_pbx_run(chan); 06643 if (res) { 06644 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 06645 } 06646 } else { 06647 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 06648 chan->hangupcause = AST_CAUSE_UNALLOCATED; 06649 ast_hangup(chan); 06650 p->exten[0] = '\0'; 06651 /* Since we send release complete here, we won't get one */ 06652 p->call = NULL; 06653 } 06654 goto quit; 06655 break; 06656 #endif 06657 case SIG_FEATD: 06658 case SIG_FEATDMF: 06659 case SIG_FEATDMF_TA: 06660 case SIG_E911: 06661 case SIG_FGC_CAMAMF: 06662 case SIG_FEATB: 06663 case SIG_EMWINK: 06664 case SIG_SF_FEATD: 06665 case SIG_SF_FEATDMF: 06666 case SIG_SF_FEATB: 06667 case SIG_SFWINK: 06668 if (dahdi_wink(p, idx)) 06669 goto quit; 06670 /* Fall through */ 06671 case SIG_EM: 06672 case SIG_EM_E1: 06673 case SIG_SF: 06674 case SIG_FGC_CAMA: 06675 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06676 if (p->dsp) 06677 ast_dsp_digitreset(p->dsp); 06678 /* set digit mode appropriately */ 06679 if (p->dsp) { 06680 if (NEED_MFDETECT(p)) 06681 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06682 else 06683 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06684 } 06685 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 06686 /* Wait for the first digit only if immediate=no */ 06687 if (!p->immediate) 06688 /* Wait for the first digit (up to 5 seconds). */ 06689 res = ast_waitfordigit(chan, 5000); 06690 else 06691 res = 0; 06692 if (res > 0) { 06693 /* save first char */ 06694 dtmfbuf[0] = res; 06695 switch (p->sig) { 06696 case SIG_FEATD: 06697 case SIG_SF_FEATD: 06698 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06699 if (res > 0) 06700 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06701 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06702 break; 06703 case SIG_FEATDMF_TA: 06704 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06705 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06706 if (dahdi_wink(p, idx)) goto quit; 06707 dtmfbuf[0] = 0; 06708 /* Wait for the first digit (up to 5 seconds). */ 06709 res = ast_waitfordigit(chan, 5000); 06710 if (res <= 0) break; 06711 dtmfbuf[0] = res; 06712 /* fall through intentionally */ 06713 case SIG_FEATDMF: 06714 case SIG_E911: 06715 case SIG_FGC_CAMAMF: 06716 case SIG_SF_FEATDMF: 06717 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06718 /* if international caca, do it again to get real ANO */ 06719 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 06720 { 06721 if (dahdi_wink(p, idx)) goto quit; 06722 dtmfbuf[0] = 0; 06723 /* Wait for the first digit (up to 5 seconds). */ 06724 res = ast_waitfordigit(chan, 5000); 06725 if (res <= 0) break; 06726 dtmfbuf[0] = res; 06727 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06728 } 06729 if (res > 0) { 06730 /* if E911, take off hook */ 06731 if (p->sig == SIG_E911) 06732 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06733 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 06734 } 06735 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06736 break; 06737 case SIG_FEATB: 06738 case SIG_SF_FEATB: 06739 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 06740 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06741 break; 06742 case SIG_EMWINK: 06743 /* if we received a '*', we are actually receiving Feature Group D 06744 dial syntax, so use that mode; otherwise, fall through to normal 06745 mode 06746 */ 06747 if (res == '*') { 06748 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 06749 if (res > 0) 06750 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 06751 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 06752 break; 06753 } 06754 default: 06755 /* If we got the first digit, get the rest */ 06756 len = 1; 06757 dtmfbuf[len] = '\0'; 06758 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06759 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 06760 timeout = matchdigittimeout; 06761 } else { 06762 timeout = gendigittimeout; 06763 } 06764 res = ast_waitfordigit(chan, timeout); 06765 if (res < 0) { 06766 ast_debug(1, "waitfordigit returned < 0...\n"); 06767 ast_hangup(chan); 06768 goto quit; 06769 } else if (res) { 06770 dtmfbuf[len++] = res; 06771 dtmfbuf[len] = '\0'; 06772 } else { 06773 break; 06774 } 06775 } 06776 break; 06777 } 06778 } 06779 if (res == -1) { 06780 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 06781 ast_hangup(chan); 06782 goto quit; 06783 } else if (res < 0) { 06784 ast_debug(1, "Got hung up before digits finished\n"); 06785 ast_hangup(chan); 06786 goto quit; 06787 } 06788 06789 if (p->sig == SIG_FGC_CAMA) { 06790 char anibuf[100]; 06791 06792 if (ast_safe_sleep(chan,1000) == -1) { 06793 ast_hangup(chan); 06794 goto quit; 06795 } 06796 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06797 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 06798 res = my_getsigstr(chan, anibuf, "#", 10000); 06799 if ((res > 0) && (strlen(anibuf) > 2)) { 06800 if (anibuf[strlen(anibuf) - 1] == '#') 06801 anibuf[strlen(anibuf) - 1] = 0; 06802 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 06803 } 06804 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06805 } 06806 06807 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 06808 if (ast_strlen_zero(exten)) 06809 ast_copy_string(exten, "s", sizeof(exten)); 06810 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 06811 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 06812 if (exten[0] == '*') { 06813 char *stringp=NULL; 06814 ast_copy_string(exten2, exten, sizeof(exten2)); 06815 /* Parse out extension and callerid */ 06816 stringp=exten2 +1; 06817 s1 = strsep(&stringp, "*"); 06818 s2 = strsep(&stringp, "*"); 06819 if (s2) { 06820 if (!ast_strlen_zero(p->cid_num)) 06821 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06822 else 06823 ast_set_callerid(chan, s1, NULL, s1); 06824 ast_copy_string(exten, s2, sizeof(exten)); 06825 } else 06826 ast_copy_string(exten, s1, sizeof(exten)); 06827 } else if (p->sig == SIG_FEATD) 06828 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06829 } 06830 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06831 if (exten[0] == '*') { 06832 char *stringp=NULL; 06833 ast_copy_string(exten2, exten, sizeof(exten2)); 06834 /* Parse out extension and callerid */ 06835 stringp=exten2 +1; 06836 s1 = strsep(&stringp, "#"); 06837 s2 = strsep(&stringp, "#"); 06838 if (s2) { 06839 if (!ast_strlen_zero(p->cid_num)) 06840 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06841 else 06842 if (*(s1 + 2)) 06843 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 06844 ast_copy_string(exten, s2 + 1, sizeof(exten)); 06845 } else 06846 ast_copy_string(exten, s1 + 2, sizeof(exten)); 06847 } else 06848 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 06849 } 06850 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 06851 if (exten[0] == '*') { 06852 char *stringp=NULL; 06853 ast_copy_string(exten2, exten, sizeof(exten2)); 06854 /* Parse out extension and callerid */ 06855 stringp=exten2 +1; 06856 s1 = strsep(&stringp, "#"); 06857 s2 = strsep(&stringp, "#"); 06858 if (s2 && (*(s2 + 1) == '0')) { 06859 if (*(s2 + 2)) 06860 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 06861 } 06862 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 06863 else ast_copy_string(exten, "911", sizeof(exten)); 06864 } else 06865 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 06866 } 06867 if (p->sig == SIG_FEATB) { 06868 if (exten[0] == '*') { 06869 char *stringp=NULL; 06870 ast_copy_string(exten2, exten, sizeof(exten2)); 06871 /* Parse out extension and callerid */ 06872 stringp=exten2 +1; 06873 s1 = strsep(&stringp, "#"); 06874 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 06875 } else 06876 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 06877 } 06878 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 06879 dahdi_wink(p, idx); 06880 /* some switches require a minimum guard time between 06881 the last FGD wink and something that answers 06882 immediately. This ensures it */ 06883 if (ast_safe_sleep(chan,100)) goto quit; 06884 } 06885 dahdi_enable_ec(p); 06886 if (NEED_MFDETECT(p)) { 06887 if (p->dsp) { 06888 if (!p->hardwaredtmf) 06889 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 06890 else { 06891 ast_dsp_free(p->dsp); 06892 p->dsp = NULL; 06893 } 06894 } 06895 } 06896 06897 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 06898 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06899 if (p->dsp) ast_dsp_digitreset(p->dsp); 06900 res = ast_pbx_run(chan); 06901 if (res) { 06902 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06903 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06904 } 06905 goto quit; 06906 } else { 06907 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 06908 sleep(2); 06909 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 06910 if (res < 0) 06911 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 06912 else 06913 sleep(1); 06914 res = ast_streamfile(chan, "ss-noservice", chan->language); 06915 if (res >= 0) 06916 ast_waitstream(chan, ""); 06917 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06918 ast_hangup(chan); 06919 goto quit; 06920 } 06921 break; 06922 case SIG_FXOLS: 06923 case SIG_FXOGS: 06924 case SIG_FXOKS: 06925 /* Read the first digit */ 06926 timeout = firstdigittimeout; 06927 /* If starting a threeway call, never timeout on the first digit so someone 06928 can use flash-hook as a "hold" feature */ 06929 if (p->subs[SUB_THREEWAY].owner) 06930 timeout = 999999; 06931 while (len < AST_MAX_EXTENSION-1) { 06932 /* Read digit unless it's supposed to be immediate, in which case the 06933 only answer is 's' */ 06934 if (p->immediate) 06935 res = 's'; 06936 else 06937 res = ast_waitfordigit(chan, timeout); 06938 timeout = 0; 06939 if (res < 0) { 06940 ast_debug(1, "waitfordigit returned < 0...\n"); 06941 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06942 ast_hangup(chan); 06943 goto quit; 06944 } else if (res) { 06945 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 06946 exten[len++]=res; 06947 exten[len] = '\0'; 06948 } 06949 if (!ast_ignore_pattern(chan->context, exten)) 06950 tone_zone_play_tone(p->subs[idx].dfd, -1); 06951 else 06952 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06953 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 06954 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 06955 if (getforward) { 06956 /* Record this as the forwarding extension */ 06957 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 06958 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 06959 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 06960 if (res) 06961 break; 06962 usleep(500000); 06963 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06964 sleep(1); 06965 memset(exten, 0, sizeof(exten)); 06966 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 06967 len = 0; 06968 getforward = 0; 06969 } else { 06970 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 06971 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 06972 if (!ast_strlen_zero(p->cid_num)) { 06973 if (!p->hidecallerid) 06974 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 06975 else 06976 ast_set_callerid(chan, NULL, NULL, p->cid_num); 06977 } 06978 if (!ast_strlen_zero(p->cid_name)) { 06979 if (!p->hidecallerid) 06980 ast_set_callerid(chan, NULL, p->cid_name, NULL); 06981 } 06982 ast_setstate(chan, AST_STATE_RING); 06983 dahdi_enable_ec(p); 06984 res = ast_pbx_run(chan); 06985 if (res) { 06986 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06987 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06988 } 06989 goto quit; 06990 } 06991 } else { 06992 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06993 so just set the timeout to matchdigittimeout and wait some more */ 06994 timeout = matchdigittimeout; 06995 } 06996 } else if (res == 0) { 06997 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 06998 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 06999 dahdi_wait_event(p->subs[idx].dfd); 07000 ast_hangup(chan); 07001 goto quit; 07002 } else if (p->callwaiting && !strcmp(exten, "*70")) { 07003 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 07004 /* Disable call waiting if enabled */ 07005 p->callwaiting = 0; 07006 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07007 if (res) { 07008 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07009 chan->name, strerror(errno)); 07010 } 07011 len = 0; 07012 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 07013 memset(exten, 0, sizeof(exten)); 07014 timeout = firstdigittimeout; 07015 07016 } else if (!strcmp(exten,ast_pickup_ext())) { 07017 /* Scan all channels and see if there are any 07018 * ringing channels that have call groups 07019 * that equal this channels pickup group 07020 */ 07021 if (idx == SUB_REAL) { 07022 /* Switch us from Third call to Call Wait */ 07023 if (p->subs[SUB_THREEWAY].owner) { 07024 /* If you make a threeway call and the *8# a call, it should actually 07025 look like a callwait */ 07026 alloc_sub(p, SUB_CALLWAIT); 07027 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 07028 unalloc_sub(p, SUB_THREEWAY); 07029 } 07030 dahdi_enable_ec(p); 07031 if (ast_pickup_call(chan)) { 07032 ast_debug(1, "No call pickup possible...\n"); 07033 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07034 dahdi_wait_event(p->subs[idx].dfd); 07035 } 07036 ast_hangup(chan); 07037 goto quit; 07038 } else { 07039 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 07040 ast_hangup(chan); 07041 goto quit; 07042 } 07043 07044 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 07045 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 07046 /* Disable Caller*ID if enabled */ 07047 p->hidecallerid = 1; 07048 if (chan->cid.cid_num) 07049 ast_free(chan->cid.cid_num); 07050 chan->cid.cid_num = NULL; 07051 if (chan->cid.cid_name) 07052 ast_free(chan->cid.cid_name); 07053 chan->cid.cid_name = NULL; 07054 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07055 if (res) { 07056 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07057 chan->name, strerror(errno)); 07058 } 07059 len = 0; 07060 memset(exten, 0, sizeof(exten)); 07061 timeout = firstdigittimeout; 07062 } else if (p->callreturn && !strcmp(exten, "*69")) { 07063 res = 0; 07064 if (!ast_strlen_zero(p->lastcid_num)) { 07065 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 07066 } 07067 if (!res) 07068 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07069 break; 07070 } else if (!strcmp(exten, "*78")) { 07071 dahdi_dnd(p, 1); 07072 /* Do not disturb */ 07073 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07074 getforward = 0; 07075 memset(exten, 0, sizeof(exten)); 07076 len = 0; 07077 } else if (!strcmp(exten, "*79")) { 07078 dahdi_dnd(p, 0); 07079 /* Do not disturb */ 07080 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07081 getforward = 0; 07082 memset(exten, 0, sizeof(exten)); 07083 len = 0; 07084 } else if (p->cancallforward && !strcmp(exten, "*72")) { 07085 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07086 getforward = 1; 07087 memset(exten, 0, sizeof(exten)); 07088 len = 0; 07089 } else if (p->cancallforward && !strcmp(exten, "*73")) { 07090 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 07091 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07092 memset(p->call_forward, 0, sizeof(p->call_forward)); 07093 getforward = 0; 07094 memset(exten, 0, sizeof(exten)); 07095 len = 0; 07096 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 07097 p->subs[SUB_THREEWAY].owner && 07098 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 07099 /* This is a three way call, the main call being a real channel, 07100 and we're parking the first call. */ 07101 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 07102 ast_verb(3, "Parking call to '%s'\n", chan->name); 07103 break; 07104 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 07105 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); 07106 res = ast_db_put("blacklist", p->lastcid_num, "1"); 07107 if (!res) { 07108 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07109 memset(exten, 0, sizeof(exten)); 07110 len = 0; 07111 } 07112 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 07113 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 07114 /* Enable Caller*ID if enabled */ 07115 p->hidecallerid = 0; 07116 if (chan->cid.cid_num) 07117 ast_free(chan->cid.cid_num); 07118 chan->cid.cid_num = NULL; 07119 if (chan->cid.cid_name) 07120 ast_free(chan->cid.cid_name); 07121 chan->cid.cid_name = NULL; 07122 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 07123 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 07124 if (res) { 07125 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 07126 chan->name, strerror(errno)); 07127 } 07128 len = 0; 07129 memset(exten, 0, sizeof(exten)); 07130 timeout = firstdigittimeout; 07131 } else if (!strcmp(exten, "*0")) { 07132 struct ast_channel *nbridge = 07133 p->subs[SUB_THREEWAY].owner; 07134 struct dahdi_pvt *pbridge = NULL; 07135 /* set up the private struct of the bridged one, if any */ 07136 if (nbridge && ast_bridged_channel(nbridge)) 07137 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 07138 if (nbridge && pbridge && 07139 (nbridge->tech == &dahdi_tech) && 07140 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 07141 ISTRUNK(pbridge)) { 07142 int func = DAHDI_FLASH; 07143 /* Clear out the dial buffer */ 07144 p->dop.dialstr[0] = '\0'; 07145 /* flash hookswitch */ 07146 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07147 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07148 nbridge->name, strerror(errno)); 07149 } 07150 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07151 unalloc_sub(p, SUB_THREEWAY); 07152 p->owner = p->subs[SUB_REAL].owner; 07153 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 07154 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 07155 ast_hangup(chan); 07156 goto quit; 07157 } else { 07158 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07159 dahdi_wait_event(p->subs[idx].dfd); 07160 tone_zone_play_tone(p->subs[idx].dfd, -1); 07161 swap_subs(p, SUB_REAL, SUB_THREEWAY); 07162 unalloc_sub(p, SUB_THREEWAY); 07163 p->owner = p->subs[SUB_REAL].owner; 07164 ast_hangup(chan); 07165 goto quit; 07166 } 07167 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 07168 ((exten[0] != '*') || (strlen(exten) > 2))) { 07169 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); 07170 break; 07171 } 07172 if (!timeout) 07173 timeout = gendigittimeout; 07174 if (len && !ast_ignore_pattern(chan->context, exten)) 07175 tone_zone_play_tone(p->subs[idx].dfd, -1); 07176 } 07177 break; 07178 case SIG_FXSLS: 07179 case SIG_FXSGS: 07180 case SIG_FXSKS: 07181 #ifdef HAVE_PRI 07182 if (p->pri) { 07183 /* This is a GR-303 trunk actually. Wait for the first ring... */ 07184 struct ast_frame *f; 07185 int res; 07186 time_t start; 07187 07188 time(&start); 07189 ast_setstate(chan, AST_STATE_RING); 07190 while (time(NULL) < start + 3) { 07191 res = ast_waitfor(chan, 1000); 07192 if (res) { 07193 f = ast_read(chan); 07194 if (!f) { 07195 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 07196 ast_hangup(chan); 07197 goto quit; 07198 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 07199 res = 1; 07200 } else 07201 res = 0; 07202 ast_frfree(f); 07203 if (res) { 07204 ast_debug(1, "Got ring!\n"); 07205 res = 0; 07206 break; 07207 } 07208 } 07209 } 07210 } 07211 #endif 07212 /* check for SMDI messages */ 07213 if (p->use_smdi && p->smdi_iface) { 07214 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 07215 07216 if (smdi_msg != NULL) { 07217 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 07218 07219 if (smdi_msg->type == 'B') 07220 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 07221 else if (smdi_msg->type == 'N') 07222 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 07223 07224 ast_debug(1, "Received SMDI message on %s\n", chan->name); 07225 } else { 07226 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 07227 } 07228 } 07229 07230 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 07231 number = smdi_msg->calling_st; 07232 07233 /* If we want caller id, we're in a prering state due to a polarity reversal 07234 * and we're set to use a polarity reversal to trigger the start of caller id, 07235 * grab the caller id and wait for ringing to start... */ 07236 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { 07237 /* If set to use DTMF CID signalling, listen for DTMF */ 07238 if (p->cid_signalling == CID_SIG_DTMF) { 07239 int k = 0; 07240 cs = NULL; 07241 ast_debug(1, "Receiving DTMF cid on " 07242 "channel %s\n", chan->name); 07243 dahdi_setlinear(p->subs[idx].dfd, 0); 07244 res = 2000; 07245 for (;;) { 07246 struct ast_frame *f; 07247 res = ast_waitfor(chan, res); 07248 if (res <= 0) { 07249 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07250 "Exiting simple switch\n"); 07251 ast_hangup(chan); 07252 goto quit; 07253 } 07254 f = ast_read(chan); 07255 if (!f) 07256 break; 07257 if (f->frametype == AST_FRAME_DTMF) { 07258 dtmfbuf[k++] = f->subclass; 07259 ast_debug(1, "CID got digit '%c'\n", f->subclass); 07260 res = 2000; 07261 } 07262 ast_frfree(f); 07263 if (chan->_state == AST_STATE_RING || 07264 chan->_state == AST_STATE_RINGING) 07265 break; /* Got ring */ 07266 } 07267 dtmfbuf[k] = '\0'; 07268 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07269 /* Got cid and ring. */ 07270 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 07271 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07272 ast_debug(1, "CID is '%s', flags %d\n", 07273 dtmfcid, flags); 07274 /* If first byte is NULL, we have no cid */ 07275 if (!ast_strlen_zero(dtmfcid)) 07276 number = dtmfcid; 07277 else 07278 number = NULL; 07279 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07280 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 07281 cs = callerid_new(p->cid_signalling); 07282 if (cs) { 07283 samples = 0; 07284 #if 1 07285 bump_gains(p); 07286 #endif 07287 /* Take out of linear mode for Caller*ID processing */ 07288 dahdi_setlinear(p->subs[idx].dfd, 0); 07289 07290 /* First we wait and listen for the Caller*ID */ 07291 for (;;) { 07292 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07293 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07294 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07295 callerid_free(cs); 07296 ast_hangup(chan); 07297 goto quit; 07298 } 07299 if (i & DAHDI_IOMUX_SIGEVENT) { 07300 res = dahdi_get_event(p->subs[idx].dfd); 07301 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07302 07303 if (p->cid_signalling == CID_SIG_V23_JP) { 07304 if (res == DAHDI_EVENT_RINGBEGIN) { 07305 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07306 usleep(1); 07307 } 07308 } else { 07309 res = 0; 07310 break; 07311 } 07312 } else if (i & DAHDI_IOMUX_READ) { 07313 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07314 if (res < 0) { 07315 if (errno != ELAST) { 07316 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07317 callerid_free(cs); 07318 ast_hangup(chan); 07319 goto quit; 07320 } 07321 break; 07322 } 07323 samples += res; 07324 07325 if (p->cid_signalling == CID_SIG_V23_JP) { 07326 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 07327 } else { 07328 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07329 } 07330 07331 if (res < 0) { 07332 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 07333 break; 07334 } else if (res) 07335 break; 07336 else if (samples > (8000 * 10)) 07337 break; 07338 } 07339 } 07340 if (res == 1) { 07341 callerid_get(cs, &name, &number, &flags); 07342 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07343 } 07344 07345 if (p->cid_signalling == CID_SIG_V23_JP) { 07346 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07347 usleep(1); 07348 res = 4000; 07349 } else { 07350 07351 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 07352 res = 2000; 07353 } 07354 07355 for (;;) { 07356 struct ast_frame *f; 07357 res = ast_waitfor(chan, res); 07358 if (res <= 0) { 07359 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 07360 "Exiting simple switch\n"); 07361 ast_hangup(chan); 07362 goto quit; 07363 } 07364 if (!(f = ast_read(chan))) { 07365 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 07366 ast_hangup(chan); 07367 goto quit; 07368 } 07369 ast_frfree(f); 07370 if (chan->_state == AST_STATE_RING || 07371 chan->_state == AST_STATE_RINGING) 07372 break; /* Got ring */ 07373 } 07374 07375 /* We must have a ring by now, so, if configured, lets try to listen for 07376 * distinctive ringing */ 07377 if (p->usedistinctiveringdetection) { 07378 len = 0; 07379 distMatches = 0; 07380 /* Clear the current ring data array so we dont have old data in it. */ 07381 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07382 curRingData[receivedRingT] = 0; 07383 receivedRingT = 0; 07384 counter = 0; 07385 counter1 = 0; 07386 /* Check to see if context is what it should be, if not set to be. */ 07387 if (strcmp(p->context,p->defcontext) != 0) { 07388 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07389 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07390 } 07391 07392 for (;;) { 07393 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07394 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07395 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07396 callerid_free(cs); 07397 ast_hangup(chan); 07398 goto quit; 07399 } 07400 if (i & DAHDI_IOMUX_SIGEVENT) { 07401 res = dahdi_get_event(p->subs[idx].dfd); 07402 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07403 res = 0; 07404 /* Let us detect distinctive ring */ 07405 07406 curRingData[receivedRingT] = p->ringt; 07407 07408 if (p->ringt < p->ringt_base/2) 07409 break; 07410 /* Increment the ringT counter so we can match it against 07411 values in chan_dahdi.conf for distinctive ring */ 07412 if (++receivedRingT == ARRAY_LEN(curRingData)) 07413 break; 07414 } else if (i & DAHDI_IOMUX_READ) { 07415 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07416 if (res < 0) { 07417 if (errno != ELAST) { 07418 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07419 callerid_free(cs); 07420 ast_hangup(chan); 07421 goto quit; 07422 } 07423 break; 07424 } 07425 if (p->ringt) 07426 p->ringt--; 07427 if (p->ringt == 1) { 07428 res = -1; 07429 break; 07430 } 07431 } 07432 } 07433 /* this only shows up if you have n of the dring patterns filled in */ 07434 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07435 for (counter = 0; counter < 3; counter++) { 07436 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07437 channel */ 07438 distMatches = 0; 07439 for (counter1 = 0; counter1 < 3; counter1++) { 07440 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07441 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07442 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07443 curRingData[counter1]); 07444 distMatches++; 07445 } 07446 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07447 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07448 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07449 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07450 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07451 distMatches++; 07452 } 07453 } 07454 07455 if (distMatches == 3) { 07456 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07457 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07458 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07459 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07460 break; 07461 } 07462 } 07463 } 07464 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07465 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07466 #if 1 07467 restore_gains(p); 07468 #endif 07469 } else 07470 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07471 } else { 07472 ast_log(LOG_WARNING, "Channel %s in prering " 07473 "state, but I have nothing to do. " 07474 "Terminating simple switch, should be " 07475 "restarted by the actual ring.\n", 07476 chan->name); 07477 ast_hangup(chan); 07478 goto quit; 07479 } 07480 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 07481 if (p->cid_signalling == CID_SIG_DTMF) { 07482 int k = 0; 07483 cs = NULL; 07484 dahdi_setlinear(p->subs[idx].dfd, 0); 07485 res = 2000; 07486 for (;;) { 07487 struct ast_frame *f; 07488 res = ast_waitfor(chan, res); 07489 if (res <= 0) { 07490 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 07491 "Exiting simple switch\n"); 07492 ast_hangup(chan); 07493 return NULL; 07494 } 07495 f = ast_read(chan); 07496 if (f->frametype == AST_FRAME_DTMF) { 07497 dtmfbuf[k++] = f->subclass; 07498 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 07499 res = 2000; 07500 } 07501 ast_frfree(f); 07502 07503 if (p->ringt_base == p->ringt) 07504 break; 07505 07506 } 07507 dtmfbuf[k] = '\0'; 07508 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07509 /* Got cid and ring. */ 07510 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 07511 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 07512 dtmfcid, flags); 07513 /* If first byte is NULL, we have no cid */ 07514 if (!ast_strlen_zero(dtmfcid)) 07515 number = dtmfcid; 07516 else 07517 number = NULL; 07518 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 07519 } else { 07520 /* FSK Bell202 callerID */ 07521 cs = callerid_new(p->cid_signalling); 07522 if (cs) { 07523 #if 1 07524 bump_gains(p); 07525 #endif 07526 samples = 0; 07527 len = 0; 07528 distMatches = 0; 07529 /* Clear the current ring data array so we dont have old data in it. */ 07530 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 07531 curRingData[receivedRingT] = 0; 07532 receivedRingT = 0; 07533 counter = 0; 07534 counter1 = 0; 07535 /* Check to see if context is what it should be, if not set to be. */ 07536 if (strcmp(p->context,p->defcontext) != 0) { 07537 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 07538 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 07539 } 07540 07541 /* Take out of linear mode for Caller*ID processing */ 07542 dahdi_setlinear(p->subs[idx].dfd, 0); 07543 for (;;) { 07544 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07545 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07546 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07547 callerid_free(cs); 07548 ast_hangup(chan); 07549 goto quit; 07550 } 07551 if (i & DAHDI_IOMUX_SIGEVENT) { 07552 res = dahdi_get_event(p->subs[idx].dfd); 07553 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07554 /* If we get a PR event, they hung up while processing calerid */ 07555 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 07556 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 07557 p->polarity = POLARITY_IDLE; 07558 callerid_free(cs); 07559 ast_hangup(chan); 07560 goto quit; 07561 } 07562 res = 0; 07563 /* Let us detect callerid when the telco uses distinctive ring */ 07564 07565 curRingData[receivedRingT] = p->ringt; 07566 07567 if (p->ringt < p->ringt_base/2) 07568 break; 07569 /* Increment the ringT counter so we can match it against 07570 values in chan_dahdi.conf for distinctive ring */ 07571 if (++receivedRingT == ARRAY_LEN(curRingData)) 07572 break; 07573 } else if (i & DAHDI_IOMUX_READ) { 07574 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07575 if (res < 0) { 07576 if (errno != ELAST) { 07577 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07578 callerid_free(cs); 07579 ast_hangup(chan); 07580 goto quit; 07581 } 07582 break; 07583 } 07584 if (p->ringt) 07585 p->ringt--; 07586 if (p->ringt == 1) { 07587 res = -1; 07588 break; 07589 } 07590 samples += res; 07591 res = callerid_feed(cs, buf, res, AST_LAW(p)); 07592 if (res < 0) { 07593 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 07594 break; 07595 } else if (res) 07596 break; 07597 else if (samples > (8000 * 10)) 07598 break; 07599 } 07600 } 07601 if (res == 1) { 07602 callerid_get(cs, &name, &number, &flags); 07603 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 07604 } 07605 if (distinctiveringaftercid == 1) { 07606 /* Clear the current ring data array so we dont have old data in it. */ 07607 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 07608 curRingData[receivedRingT] = 0; 07609 } 07610 receivedRingT = 0; 07611 ast_verb(3, "Detecting post-CID distinctive ring\n"); 07612 for (;;) { 07613 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 07614 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 07615 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 07616 callerid_free(cs); 07617 ast_hangup(chan); 07618 goto quit; 07619 } 07620 if (i & DAHDI_IOMUX_SIGEVENT) { 07621 res = dahdi_get_event(p->subs[idx].dfd); 07622 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 07623 res = 0; 07624 /* Let us detect callerid when the telco uses distinctive ring */ 07625 07626 curRingData[receivedRingT] = p->ringt; 07627 07628 if (p->ringt < p->ringt_base/2) 07629 break; 07630 /* Increment the ringT counter so we can match it against 07631 values in chan_dahdi.conf for distinctive ring */ 07632 if (++receivedRingT == ARRAY_LEN(curRingData)) 07633 break; 07634 } else if (i & DAHDI_IOMUX_READ) { 07635 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 07636 if (res < 0) { 07637 if (errno != ELAST) { 07638 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 07639 callerid_free(cs); 07640 ast_hangup(chan); 07641 goto quit; 07642 } 07643 break; 07644 } 07645 if (p->ringt) 07646 p->ringt--; 07647 if (p->ringt == 1) { 07648 res = -1; 07649 break; 07650 } 07651 } 07652 } 07653 } 07654 if (p->usedistinctiveringdetection) { 07655 /* this only shows up if you have n of the dring patterns filled in */ 07656 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 07657 07658 for (counter = 0; counter < 3; counter++) { 07659 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 07660 channel */ 07661 /* this only shows up if you have n of the dring patterns filled in */ 07662 ast_verb(3, "Checking %d,%d,%d\n", 07663 p->drings.ringnum[counter].ring[0], 07664 p->drings.ringnum[counter].ring[1], 07665 p->drings.ringnum[counter].ring[2]); 07666 distMatches = 0; 07667 for (counter1 = 0; counter1 < 3; counter1++) { 07668 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 07669 if (p->drings.ringnum[counter].ring[counter1] == -1) { 07670 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 07671 curRingData[counter1]); 07672 distMatches++; 07673 } 07674 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 07675 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 07676 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 07677 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 07678 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 07679 distMatches++; 07680 } 07681 } 07682 if (distMatches == 3) { 07683 /* The ring matches, set the context to whatever is for distinctive ring.. */ 07684 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 07685 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 07686 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 07687 break; 07688 } 07689 } 07690 } 07691 /* Restore linear mode (if appropriate) for Caller*ID processing */ 07692 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07693 #if 1 07694 restore_gains(p); 07695 #endif 07696 if (res < 0) { 07697 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 07698 } 07699 } else 07700 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 07701 } 07702 } 07703 else 07704 cs = NULL; 07705 07706 if (number) 07707 ast_shrink_phone_number(number); 07708 ast_set_callerid(chan, number, name, number); 07709 07710 if (smdi_msg) 07711 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 07712 07713 if (cs) 07714 callerid_free(cs); 07715 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 07716 if (flags & CID_MSGWAITING) { 07717 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel); 07718 notify_message(p->mailbox, 1); 07719 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07720 if (p->mwimonitor_rpas) { 07721 ast_hangup(chan); 07722 return NULL; 07723 } 07724 } else if (flags & CID_NOMSGWAITING) { 07725 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel); 07726 notify_message(p->mailbox, 0); 07727 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 07728 if (p->mwimonitor_rpas) { 07729 ast_hangup(chan); 07730 return NULL; 07731 } 07732 } 07733 07734 ast_setstate(chan, AST_STATE_RING); 07735 chan->rings = 1; 07736 p->ringt = p->ringt_base; 07737 res = ast_pbx_run(chan); 07738 if (res) { 07739 ast_hangup(chan); 07740 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 07741 } 07742 goto quit; 07743 default: 07744 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 07745 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07746 if (res < 0) 07747 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07748 } 07749 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07750 if (res < 0) 07751 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 07752 ast_hangup(chan); 07753 quit: 07754 ast_mutex_lock(&ss_thread_lock); 07755 ss_thread_count--; 07756 ast_cond_signal(&ss_thread_complete); 07757 ast_mutex_unlock(&ss_thread_lock); 07758 return NULL; 07759 }
| static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 12012 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().
12013 { 12014 int res, x; 12015 struct dahdi_params p; 12016 struct dahdi_bufferinfo bi; 12017 struct dahdi_spaninfo si; 12018 int i; 12019 12020 for (i = 0; i < NUM_DCHANS; i++) { 12021 if (!pri->dchannels[i]) 12022 break; 12023 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR); 12024 x = pri->dchannels[i]; 12025 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 12026 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 12027 return -1; 12028 } 12029 memset(&p, 0, sizeof(p)); 12030 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 12031 if (res) { 12032 dahdi_close_pri_fd(pri, i); 12033 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 12034 return -1; 12035 } 12036 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 12037 dahdi_close_pri_fd(pri, i); 12038 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 12039 return -1; 12040 } 12041 memset(&si, 0, sizeof(si)); 12042 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 12043 if (res) { 12044 dahdi_close_pri_fd(pri, i); 12045 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 12046 } 12047 if (!si.alarms) 12048 pri->dchanavail[i] |= DCHAN_NOTINALARM; 12049 else 12050 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 12051 memset(&bi, 0, sizeof(bi)); 12052 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 12053 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 12054 bi.numbufs = 32; 12055 bi.bufsize = 1024; 12056 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 12057 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 12058 dahdi_close_pri_fd(pri, i); 12059 return -1; 12060 } 12061 switch (pri->sig) { 12062 case SIG_BRI: 12063 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype); 12064 break; 12065 case SIG_BRI_PTMP: 12066 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype); 12067 break; 12068 default: 12069 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 12070 } 12071 /* Force overlap dial if we're doing GR-303! */ 12072 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 12073 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 12074 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 12075 #ifdef HAVE_PRI_INBANDDISCONNECT 12076 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 12077 #endif 12078 /* Enslave to master if appropriate */ 12079 if (i) 12080 pri_enslave(pri->dchans[0], pri->dchans[i]); 12081 if (!pri->dchans[i]) { 12082 dahdi_close_pri_fd(pri, i); 12083 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 12084 return -1; 12085 } 12086 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 12087 pri_set_nsf(pri->dchans[i], pri->nsf); 12088 #ifdef PRI_GETSET_TIMERS 12089 for (x = 0; x < PRI_MAX_TIMERS; x++) { 12090 if (pritimers[x] != 0) 12091 pri_set_timer(pri->dchans[i], x, pritimers[x]); 12092 } 12093 #endif 12094 } 12095 /* Assume primary is the one we use */ 12096 pri->pri = pri->dchans[0]; 12097 pri->resetpos = -1; 12098 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 12099 for (i = 0; i < NUM_DCHANS; i++) { 12100 if (!pri->dchannels[i]) 12101 break; 12102 dahdi_close_pri_fd(pri, i); 12103 } 12104 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 12105 return -1; 12106 } 12107 return 0; 12108 }
| static void swap_subs | ( | struct dahdi_pvt * | p, | |
| int | a, | |||
| int | b | |||
| ) | [static] |
Definition at line 1408 of file chan_dahdi.c.
References ast_channel_set_fd(), ast_debug, dahdi_subchannel::chan, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01409 { 01410 int tchan; 01411 int tinthreeway; 01412 struct ast_channel *towner; 01413 01414 ast_debug(1, "Swapping %d and %d\n", a, b); 01415 01416 tchan = p->subs[a].chan; 01417 towner = p->subs[a].owner; 01418 tinthreeway = p->subs[a].inthreeway; 01419 01420 p->subs[a].chan = p->subs[b].chan; 01421 p->subs[a].owner = p->subs[b].owner; 01422 p->subs[a].inthreeway = p->subs[b].inthreeway; 01423 01424 p->subs[b].chan = tchan; 01425 p->subs[b].owner = towner; 01426 p->subs[b].inthreeway = tinthreeway; 01427 01428 if (p->subs[a].owner) 01429 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 01430 if (p->subs[b].owner) 01431 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 01432 wakeup_sub(p, a, NULL); 01433 wakeup_sub(p, b, NULL); 01434 }
| static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 1558 of file chan_dahdi.c.
References ast_debug, ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.
Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
01559 { 01560 if (!x) { 01561 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01562 return -1; 01563 } 01564 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 01565 dahdi_close_sub(p, x); 01566 p->subs[x].linear = 0; 01567 p->subs[x].chan = 0; 01568 p->subs[x].owner = NULL; 01569 p->subs[x].inthreeway = 0; 01570 p->polarity = POLARITY_IDLE; 01571 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01572 return 0; 01573 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 14103 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), linksets, lock, NUM_SPANS, and pris.
14104 { 14105 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14106 int y; 14107 #endif 14108 #ifdef HAVE_PRI 14109 for (y = 0; y < NUM_SPANS; y++) 14110 ast_mutex_destroy(&pris[y].lock); 14111 #endif 14112 #ifdef HAVE_SS7 14113 for (y = 0; y < NUM_SPANS; y++) 14114 ast_mutex_destroy(&linksets[y].lock); 14115 #endif /* HAVE_SS7 */ 14116 return __unload_module(); 14117 }
| static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1948 of file chan_dahdi.c.
References ast_debug, dahdi_pvt::channel, conf_add(), conf_del(), dahdi_pvt::confno, dahdi_subchannel::dfd, GET_CHANNEL, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, isslavenative(), dahdi_pvt::master, MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_unlink(), and mkintf().
01949 { 01950 int needconf = 0; 01951 int x; 01952 int useslavenative; 01953 struct dahdi_pvt *slave = NULL; 01954 01955 useslavenative = isslavenative(p, &slave); 01956 /* Start with the obvious, general stuff */ 01957 for (x = 0; x < 3; x++) { 01958 /* Look for three way calls */ 01959 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01960 conf_add(p, &p->subs[x], x, 0); 01961 needconf++; 01962 } else { 01963 conf_del(p, &p->subs[x], x); 01964 } 01965 } 01966 /* If we have a slave, add him to our conference now. or DAX 01967 if this is slave native */ 01968 for (x = 0; x < MAX_SLAVES; x++) { 01969 if (p->slaves[x]) { 01970 if (useslavenative) 01971 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01972 else { 01973 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01974 needconf++; 01975 } 01976 } 01977 } 01978 /* If we're supposed to be in there, do so now */ 01979 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01980 if (useslavenative) 01981 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01982 else { 01983 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01984 needconf++; 01985 } 01986 } 01987 /* If we have a master, add ourselves to his conference */ 01988 if (p->master) { 01989 if (isslavenative(p->master, NULL)) { 01990 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01991 } else { 01992 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01993 } 01994 } 01995 if (!needconf) { 01996 /* Nobody is left (or should be left) in our conference. 01997 Kill it. */ 01998 p->confno = -1; 01999 } 02000 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02001 return 0; 02002 }
Definition at line 1315 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by pri_fixup_principle(), and swap_subs().
01319 { 01320 #ifdef HAVE_PRI 01321 if (pri) 01322 ast_mutex_unlock(&pri->lock); 01323 #endif 01324 for (;;) { 01325 if (p->subs[a].owner) { 01326 if (ast_channel_trylock(p->subs[a].owner)) { 01327 DEADLOCK_AVOIDANCE(&p->lock); 01328 } else { 01329 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01330 ast_channel_unlock(p->subs[a].owner); 01331 break; 01332 } 01333 } else 01334 break; 01335 } 01336 #ifdef HAVE_PRI 01337 if (pri) 01338 ast_mutex_lock(&pri->lock); 01339 #endif 01340 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "DAHDI Telephony w/PRI & SS7" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 15515 of file chan_dahdi.c.
| int alarm |
Definition at line 1713 of file chan_dahdi.c.
Referenced by alarm2str().
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
Definition at line 1289 of file chan_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 15515 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1270 of file chan_dahdi.c.
int cidrings[NUM_CADENCE_MAX] [static] |
cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
Definition at line 1281 of file chan_dahdi.c.
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 168 of file chan_dahdi.c.
int cur_adjpointcode = -1 [static] |
Definition at line 383 of file chan_dahdi.c.
int cur_cicbeginswith = -1 [static] |
Definition at line 382 of file chan_dahdi.c.
int cur_defaultdpc = -1 [static] |
Definition at line 385 of file chan_dahdi.c.
int cur_linkset = -1 [static] |
Definition at line 380 of file chan_dahdi.c.
int cur_networkindicator = -1 [static] |
Definition at line 384 of file chan_dahdi.c.
int cur_pointcode = -1 [static] |
Definition at line 381 of file chan_dahdi.c.
int cur_ss7type = -1 [static] |
Definition at line 379 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 13336 of file chan_dahdi.c.
struct ast_cli_entry dahdi_pri_cli[] [static] |
Definition at line 12467 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3252 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 3256 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static] |
Definition at line 3254 of file chan_dahdi.c.
struct ast_cli_entry dahdi_ss7_cli[] [static] |
Definition at line 14014 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1197 of file chan_dahdi.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 118 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 226 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 227 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 238 of file chan_dahdi.c.
char* events[] [static] |
Definition at line 1690 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 254 of file chan_dahdi.c.
Referenced by disa_exec().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 257 of file chan_dahdi.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 125 of file chan_dahdi.c.
Referenced by dahdi_new(), process_dahdi(), and setup_dahdi().
int ifcount = 0 [static] |
Definition at line 266 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), chandup(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_channel(), load_module(), mkintf(), and phone_request().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 263 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), dahdi_hangup(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), and setup_dahdi().
struct ast_channel inuse [static] |
Definition at line 245 of file chan_dahdi.c.
Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), pri_dchannel(), and update_call_counter().
const char* lbostr[] [static] |
Definition at line 106 of file chan_dahdi.c.
Definition at line 377 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), dahdi_ss7_error(), dahdi_ss7_message(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_debug(), handle_ss7_no_debug(), handle_ss7_show_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), load_module(), setup_dahdi(), ss7_resolve_linkset(), and unload_module().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 260 of file chan_dahdi.c.
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 278 of file chan_dahdi.c.
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 274 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), and restart_monitor().
ast_cond_t mwi_thread_complete [static] |
Definition at line 279 of file chan_dahdi.c.
int mwi_thread_count = 0 [static] |
Definition at line 284 of file chan_dahdi.c.
ast_mutex_t mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 281 of file chan_dahdi.c.
Referenced by dahdi_restart(), and mwi_send_thread().
int mwilevel = 512 [static] |
Definition at line 242 of file chan_dahdi.c.
char mwimonitornotify[PATH_MAX] = "" [static] |
Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled
Definition at line 232 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 233 of file chan_dahdi.c.
| char* name |
Definition at line 1714 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1267 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 286 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 240 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 229 of file chan_dahdi.c.
Referenced by __find_callno(), ast_iax2_new(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), func_channel_write(), gtalk_load_config(), gtalk_new(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 249 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 269 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), handle_pri_show_debug(), and handle_pri_unset_debug_file().
char pridebugfilename[1024] = "" [static] |
Definition at line 250 of file chan_dahdi.c.
Definition at line 447 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().
char progzone[10] = "" [static] |
Definition at line 235 of file chan_dahdi.c.
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 283 of file chan_dahdi.c.
Referenced by dahdi_restart().
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 341 of file chan_dahdi.c.
| struct dahdi_pvt* round_robin[32] |
Definition at line 1224 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 280 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 285 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 282 of file chan_dahdi.c.
Referenced by dahdi_restart(), and ss_thread().
char* subnames[] [static] |
{
"Real",
"Callwait",
"Threeway"
}
Definition at line 486 of file chan_dahdi.c.
const char tdesc[] [static] |
Definition at line 159 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 237 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1268 of file chan_dahdi.c.
1.6.1