DAHDI for Pseudo TDM. More...
#include "asterisk.h"#include <sys/signal.h>#include <sys/ioctl.h>#include <math.h>#include <ctype.h>#include <dahdi/user.h>#include <dahdi/tonezone.h>#include <libpri.h>#include <libss7.h>#include "asterisk/lock.h"#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/file.h"#include "asterisk/ulaw.h"#include "asterisk/alaw.h"#include "asterisk/callerid.h"#include "asterisk/adsi.h"#include "asterisk/cli.h"#include "asterisk/cdr.h"#include "asterisk/features.h"#include "asterisk/musiconhold.h"#include "asterisk/say.h"#include "asterisk/tdd.h"#include "asterisk/app.h"#include "asterisk/dsp.h"#include "asterisk/astdb.h"#include "asterisk/manager.h"#include "asterisk/causes.h"#include "asterisk/term.h"#include "asterisk/utils.h"#include "asterisk/transcap.h"#include "asterisk/stringfields.h"#include "asterisk/abstract_jb.h"#include "asterisk/smdi.h"#include "asterisk/astobj.h"#include "asterisk/event.h"#include "asterisk/devicestate.h"#include "asterisk/paths.h"
Go to the source code of this file.
Data Structures | |
| struct | dahdi_chan_conf |
| Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More... | |
| struct | dahdi_distRings |
| struct | dahdi_pri |
| struct | dahdi_pvt |
| struct | dahdi_ss7 |
| struct | dahdi_subchannel |
| struct | distRingData |
| struct | mwi_thread_data |
| struct | mwisend_info |
| struct | ringContextData |
Defines | |
| #define | ASCII_BYTES_PER_CHAR 80 |
| #define | AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
| #define | CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
| #define | CALLPROGRESS_FAX_INCOMING 4 |
| #define | CALLPROGRESS_FAX_OUTGOING 2 |
| #define | CALLPROGRESS_PROGRESS 1 |
| #define | CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
| #define | CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
| #define | CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
| #define | CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
| #define | CHAN_PSEUDO -2 |
| #define | CHANNEL_PSEUDO -12 |
| #define | CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define | CONF_USER_REAL (1 << 0) |
| #define | CONF_USER_THIRDCALL (1 << 1) |
| #define | DAHDI_CHAN_MAPPING_LOGICAL 1 |
| #define | DAHDI_CHAN_MAPPING_PHYSICAL 0 |
| #define | DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
| #define | DAHDI_OVERLAPDIAL_INCOMING 2 |
| #define | DAHDI_OVERLAPDIAL_NONE 0 |
| #define | DAHDI_OVERLAPDIAL_OUTGOING 1 |
| #define | DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
| #define | DCHAN_NOTINALARM (1 << 1) |
| #define | DCHAN_PROVISIONED (1 << 0) |
| #define | DCHAN_UP (1 << 2) |
| #define | DEFAULT_CIDRINGS 1 |
| Typically, how many rings before we should send Caller*ID. | |
| #define | DEFAULT_PRI_DEBUG 0 |
| #define | DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
| #define | END_SILENCE_LEN 400 |
| #define | FORMAT "%-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_MFCR2 DAHDI_SIG_CAS |
| #define | SIG_PRI DAHDI_SIG_CLEAR |
| #define | SIG_SF DAHDI_SIG_SF |
| #define | SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
| #define | SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
| #define | SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
| #define | SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
| #define | SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
| #define | SMDI_MD_WAIT_TIMEOUT 1500 |
| #define | SS7_NAI_DYNAMIC -1 |
| #define | SUB_CALLWAIT 1 |
| #define | SUB_REAL 0 |
| #define | SUB_THREEWAY 2 |
| #define | TRAILER_MS 5 |
| #define | TRANSFER 0 |
Enumerations | |
| enum | mwisend_states { MWI_SEND_NULL = 0, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE, MWI_SEND_SPILL, MWI_SEND_CLEANUP, MWI_SEND_DONE } |
Functions | |
| static struct ast_frame * | __dahdi_exception (struct ast_channel *ast) |
| static void | __reg_module (void) |
| static int | __unload_module (void) |
| static void | __unreg_module (void) |
| static int | action_dahdidialoffhook (struct mansession *s, const struct message *m) |
| static int | action_dahdidndoff (struct mansession *s, const struct message *m) |
| static int | action_dahdidndon (struct mansession *s, const struct message *m) |
| static int | action_dahdirestart (struct mansession *s, const struct message *m) |
| static int | action_dahdishowchannels (struct mansession *s, const struct message *m) |
| static int | action_transfer (struct mansession *s, const struct message *m) |
| static int | action_transferhangup (struct mansession *s, const struct message *m) |
| static char * | alarm2str (int alm) |
| static int | alloc_sub (struct dahdi_pvt *p, int x) |
| static void | apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan) |
| static int | attempt_transfer (struct dahdi_pvt *p) |
| static int | available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched) |
| static int | build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo) |
| static void | build_status (char *s, size_t len, int status, int active) |
| static int | bump_gains (struct dahdi_pvt *p) |
| static int | calc_energy (const unsigned char *buf, int len, int law) |
| static int | check_for_conference (struct dahdi_pvt *p) |
| static unsigned char | cid_pres2ss7pres (int cid_pres) |
| static unsigned char | cid_pres2ss7screen (int cid_pres) |
| static char * | complete_span_4 (const char *line, const char *word, int pos, int state) |
| static char * | complete_span_helper (const char *line, const char *word, int pos, int state, int rpos) |
| static int | conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel) |
| static int | conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx) |
| static int | dahdi_answer (struct ast_channel *ast) |
| static enum ast_bridge_result | dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| static int | dahdi_call (struct ast_channel *ast, char *rdest, int timeout) |
| static int | dahdi_callwait (struct ast_channel *ast) |
| static struct dahdi_chan_conf | dahdi_chan_conf_default (void) |
| static void | dahdi_close (int fd) |
| static void | dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num) |
| static void | dahdi_close_ss7_fd (struct dahdi_ss7 *ss7, int fd_num) |
| static void | dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num) |
| static int | dahdi_confmute (struct dahdi_pvt *p, int muted) |
| static char * | dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_destroy_channel_bynum (int channel) |
| static int | dahdi_digit_begin (struct ast_channel *ast, char digit) |
| static int | dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| static void | dahdi_disable_ec (struct dahdi_pvt *p) |
| static void | dahdi_dnd (struct dahdi_pvt *dahdichan, int on) |
| enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel | |
| static void | dahdi_enable_ec (struct dahdi_pvt *p) |
| static struct ast_frame * | dahdi_exception (struct ast_channel *ast) |
| static int | dahdi_fake_event (struct dahdi_pvt *p, int mode) |
| static int | dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static int | dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) |
| static int | dahdi_get_event (int fd) |
| Avoid the silly dahdi_getevent which ignores a bunch of events. | |
| static int | dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok) |
| static void | dahdi_handle_dtmfup (struct ast_channel *ast, int idx, struct ast_frame **dest) |
| static struct ast_frame * | dahdi_handle_event (struct ast_channel *ast) |
| static int | dahdi_hangup (struct ast_channel *ast) |
| static int | dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen) |
| static void | dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master) |
| static void | dahdi_loopback (struct dahdi_pvt *p, int enable) |
| static struct ast_channel * | dahdi_new (struct dahdi_pvt *, int, int, int, int, int) |
| static int | dahdi_open (char *fn) |
| static void | dahdi_pri_error (struct pri *pri, char *s) |
| static void | dahdi_pri_message (struct pri *pri, char *s) |
| static void | dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, void *data) |
| static struct ast_frame * | dahdi_read (struct ast_channel *ast) |
| static struct ast_channel * | dahdi_request (const char *type, int format, void *data, int *cause) |
| static int | dahdi_restart (void) |
| static char * | dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_ring_phone (struct dahdi_pvt *p) |
| static int | dahdi_send_keypad_facility_exec (struct ast_channel *chan, void *data) |
| static int | dahdi_sendtext (struct ast_channel *c, const char *text) |
| static char * | dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_set_hook (int fd, int hs) |
| static char * | dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | dahdi_setlaw (int dfd, int law) |
| static int | dahdi_setlinear (int dfd, int linear) |
| static int | dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen) |
| static char * | dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | dahdi_sig2str (int sig) |
| static void | dahdi_softhangup_all (void) |
| static void | dahdi_ss7_error (struct ss7 *ss7, char *s) |
| static void | dahdi_ss7_message (struct ss7 *ss7, char *s) |
| static void | dahdi_train_ec (struct dahdi_pvt *p) |
| static void | dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock) |
| static int | dahdi_wait_event (int fd) |
| Avoid the silly dahdi_waitevent which ignores a bunch of events. | |
| static int | dahdi_wink (struct dahdi_pvt *p, int idx) |
| static int | dahdi_write (struct ast_channel *ast, struct ast_frame *frame) |
| static void | destroy_all_channels (void) |
| static int | destroy_channel (struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now) |
| static void | destroy_dahdi_pvt (struct dahdi_pvt **pvt) |
| static char * | dialplan2str (int dialplan) |
| static int | digit_to_dtmfindex (char digit) |
| static void | disable_dtmf_detect (struct dahdi_pvt *p) |
| static void * | do_idle_thread (void *vchan) |
| static void * | do_monitor (void *data) |
| static struct dahdi_pvt * | duplicate_pseudo (struct dahdi_pvt *src) |
| static void | enable_dtmf_detect (struct dahdi_pvt *p) |
| static char * | event2str (int event) |
| static void | fill_rxgain (struct dahdi_gains *g, float gain, int law) |
| static void | fill_txgain (struct dahdi_gains *g, float gain, int law) |
| static struct dahdi_pvt * | find_channel (int channel) |
| static int | get_alarms (struct dahdi_pvt *p) |
| static void | handle_alarms (struct dahdi_pvt *p, int alms) |
| static char * | handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static struct dahdi_pvt * | handle_init_event (struct dahdi_pvt *i, int event) |
| static char * | handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_block_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_block_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_show_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_unblock_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_unblock_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_ss7_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static int | has_voicemail (struct dahdi_pvt *p) |
| static int | isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c) |
| static int | isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out) |
| static int | linkset_addsigchan (int sigchan) |
| static int | load_module (void) |
| static struct dahdi_pvt * | mkintf (int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading) |
| static void | mwi_event_cb (const struct ast_event *event, void *userdata) |
| static int | mwi_send_init (struct dahdi_pvt *pvt) |
| static int | mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read) |
| static int | mwi_send_process_event (struct dahdi_pvt *pvt, int event) |
| static void * | mwi_thread (void *data) |
| static int | my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear) |
| static int | my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms) |
| static void | notify_message (char *mailbox_full, int thereornot) |
| Send MWI state change. | |
| static unsigned int | parse_pointcode (const char *pcstring) |
| static int | pri_active_dchan_fd (struct dahdi_pri *pri) |
| static int | pri_assign_bearer (struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer) |
| static int | pri_check_restart (struct dahdi_pri *pri) |
| static int | pri_create_spanmap (int span, int trunkgroup, int logicalspan) |
| static int | pri_create_trunkgroup (int trunkgroup, int *channels) |
| static void * | pri_dchannel (void *vpri) |
| static struct dahdi_pvt * | pri_find_crv (struct dahdi_pri *pri, int crv) |
| static int | pri_find_dchan (struct dahdi_pri *pri) |
| static int | pri_find_empty_chan (struct dahdi_pri *pri, int backwards) |
| static int | pri_find_principle (struct dahdi_pri *pri, int channel) |
| static int | pri_fixup_principle (struct dahdi_pri *pri, int principle, q931_call *c) |
| static int | pri_grab (struct dahdi_pvt *pvt, struct dahdi_pri *pri) |
| static int | pri_hangup_all (struct dahdi_pvt *p, struct dahdi_pri *pri) |
| static int | pri_is_up (struct dahdi_pri *pri) |
| static char * | pri_order (int level) |
| static void | pri_rel (struct dahdi_pri *pri) |
| static int | pri_resolve_span (int *span, int channel, int offset, struct dahdi_spaninfo *si) |
| static int | process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options) |
| static void | process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line) |
| static char * | redirectingreason2str (int redirectingreason) |
| static int | reload (void) |
| static int | reset_conf (struct dahdi_pvt *p) |
| static int | restart_monitor (void) |
| static int | restore_conference (struct dahdi_pvt *p) |
| static int | restore_gains (struct dahdi_pvt *p) |
| static int | save_conference (struct dahdi_pvt *p) |
| static int | send_callerid (struct dahdi_pvt *p) |
| static int | send_cwcidspill (struct dahdi_pvt *p) |
| static int | set_actual_gain (int fd, int chan, float rxgain, float txgain, int law) |
| static int | set_actual_rxgain (int fd, int chan, float gain, int law) |
| static int | set_actual_txgain (int fd, int chan, float gain, int law) |
| static int | setup_dahdi (int reload) |
| static int | sigtype_to_signalling (int sigtype) |
| static void | ss7_apply_plan_to_number (char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai) |
| static void | ss7_block_cics (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block) |
| static int | ss7_find_cic (struct dahdi_ss7 *linkset, int cic, unsigned int dpc) |
| static int | ss7_grab (struct dahdi_pvt *pvt, struct dahdi_ss7 *pri) |
| static void | ss7_handle_cqm (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc) |
| static void | ss7_hangup_cics (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc) |
| static void | ss7_inservice (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc) |
| static void * | ss7_linkset (void *data) |
| static int | ss7_pres_scr2cid_pres (char presentation_ind, char screening_ind) |
| static void | ss7_rel (struct dahdi_ss7 *ss7) |
| static void | ss7_reset_linkset (struct dahdi_ss7 *linkset) |
| static struct dahdi_ss7 * | ss7_resolve_linkset (int linkset) |
| static void | ss7_start_call (struct dahdi_pvt *p, struct dahdi_ss7 *linkset) |
| static void * | ss_thread (void *data) |
| static int | start_pri (struct dahdi_pri *pri) |
| static void | swap_subs (struct dahdi_pvt *p, int a, int b) |
| static int | unalloc_sub (struct dahdi_pvt *p, int x) |
| static int | unload_module (void) |
| static int | update_conf (struct dahdi_pvt *p) |
| static void | wakeup_sub (struct dahdi_pvt *p, int a, struct dahdi_pri *pri) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } |
| struct { | |
| int alarm | |
| char * name | |
| } | alarms [] |
| static struct dahdi_ring_cadence | AS_RP_cadence = {{250, 10000}} |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
| static int | cidrings [NUM_CADENCE_MAX] |
| cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on. | |
| static const char | config [] = "chan_dahdi.conf" |
| static int | cur_adjpointcode = -1 |
| static int | cur_cicbeginswith = -1 |
| static int | cur_defaultdpc = -1 |
| static int | cur_linkset = -1 |
| static int | cur_networkindicator = -1 |
| static int | cur_pointcode = -1 |
| static int | cur_ss7type = -1 |
| static struct ast_cli_entry | dahdi_cli [] |
| static struct ast_cli_entry | dahdi_pri_cli [] |
| static char * | dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" |
| static struct ast_cli_entry | dahdi_ss7_cli [] |
| static struct ast_channel_tech | dahdi_tech |
| static struct ast_jb_conf | default_jbconf |
| static char | defaultcic [64] = "" |
| static char | defaultozz [64] = "" |
| static int | distinctiveringaftercid = 0 |
| static char * | events [] |
| static int | firstdigittimeout = 16000 |
| Wait up to 16 seconds for first digit (FXO logic). | |
| static int | gendigittimeout = 8000 |
| How long to wait for following digits (FXO logic). | |
| static struct ast_jb_conf | global_jbconf |
| static int | ifcount = 0 |
| static struct dahdi_pvt * | ifend |
| static struct dahdi_pvt * | iflist |
| static ast_mutex_t | iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| Protect the interface list (of dahdi_pvt's). | |
| static struct ast_channel | inuse |
| static const char * | lbostr [] |
| static struct dahdi_ss7 | linksets [NUM_SPANS] |
| static int | matchdigittimeout = 3000 |
| How long to wait for an extra digit, if there is an ambiguous match. | |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
| static ast_mutex_t | monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| static int | mwilevel = 512 |
| static char | mwimonitornotify [PATH_MAX] = "" |
| static int | mwisend_rpas = 0 |
| static int | num_cadence = 4 |
| static int | num_restart_pending = 0 |
| static int | numbufs = 4 |
| static char | parkinglot [AST_MAX_EXTENSION] = "" |
| static int | pridebugfd = -1 |
| static ast_mutex_t | pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static char | pridebugfilename [1024] = "" |
| static struct dahdi_pri | pris [NUM_SPANS] |
| static char | progzone [10] = "" |
| static ast_mutex_t | restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static int | ringt_base = DEFAULT_RINGT |
| Configured ring timeout base. | |
| struct dahdi_pvt * | round_robin [32] |
| static ast_cond_t | ss_thread_complete |
| static int | ss_thread_count = 0 |
| static ast_mutex_t | ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
| static char * | subnames [] |
| static const char | tdesc [] |
| static int | usedistinctiveringdetection = 0 |
| static int | user_has_defined_cadences = 0 |
DAHDI for Pseudo TDM.
Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.
You need to install libraries before you attempt to compile and install the DAHDI channel.
Definition in file chan_dahdi.c.
| #define ASCII_BYTES_PER_CHAR 80 |
Referenced by dahdi_sendtext().
| #define AST_LAW | ( | p | ) | (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW) |
Definition at line 209 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), do_monitor(), mwi_send_init(), mwi_thread(), send_cwcidspill(), and ss_thread().
| #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) |
Definition at line 294 of file chan_dahdi.c.
Referenced by dahdi_handle_dtmfup(), and process_dahdi().
| #define CALLPROGRESS_FAX_INCOMING 4 |
Definition at line 293 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_FAX_OUTGOING 2 |
Definition at line 292 of file chan_dahdi.c.
Referenced by dahdi_new(), and process_dahdi().
| #define CALLPROGRESS_PROGRESS 1 |
Definition at line 291 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 402 of file chan_dahdi.c.
| #define CANBUSYDETECT | ( | p | ) | (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) |
Definition at line 1500 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 1501 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_handle_event(), and dahdi_new().
| #define CHAN_PSEUDO -2 |
Definition at line 277 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), mkintf(), and process_dahdi().
| #define CHANNEL_PSEUDO -12 |
Definition at line 207 of file chan_dahdi.c.
| #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
| #define CONF_USER_REAL (1 << 0) |
Definition at line 625 of file chan_dahdi.c.
| #define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 626 of file chan_dahdi.c.
| #define DAHDI_CHAN_MAPPING_LOGICAL 1 |
Definition at line 339 of file chan_dahdi.c.
Referenced by process_dahdi(), and start_pri().
| #define DAHDI_CHAN_MAPPING_PHYSICAL 0 |
Definition at line 338 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default(), and process_dahdi().
| #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING) |
Definition at line 289 of file chan_dahdi.c.
Referenced by process_dahdi(), and start_pri().
| #define DAHDI_OVERLAPDIAL_INCOMING 2 |
Definition at line 288 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_read(), handle_pri_show_span(), pri_dchannel(), process_dahdi(), and ss_thread().
| #define DAHDI_OVERLAPDIAL_NONE 0 |
Definition at line 286 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define DAHDI_OVERLAPDIAL_OUTGOING 1 |
Definition at line 287 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 283 of file chan_dahdi.c.
Referenced by pri_find_dchan(), and pri_is_up().
| #define DCHAN_NOTINALARM (1 << 1) |
Definition at line 280 of file chan_dahdi.c.
Referenced by build_status(), pri_dchannel(), and start_pri().
| #define DCHAN_PROVISIONED (1 << 0) |
Definition at line 279 of file chan_dahdi.c.
Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().
| #define DCHAN_UP (1 << 2) |
Definition at line 281 of file chan_dahdi.c.
Referenced by build_status(), and pri_dchannel().
| #define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 205 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
| #define DEFAULT_PRI_DEBUG 0 |
Definition at line 566 of file chan_dahdi.c.
Referenced by start_pri().
| #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 406 of file chan_dahdi.c.
| #define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
| #define FORMAT "%-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" |
Referenced by __iax2_show_peers(), _sip_show_peers(), alias_show(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), gtalk_show_channels(), handle_cli_core_show_channeltypes(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_cli_keys_show(), handle_core_show_image_formats(), handle_show_routes(), handle_show_version_files(), jingle_show_channels(), show_channels_cb(), show_chanstats_cb(), sip_show_domains(), sip_show_inuse(), sip_show_mwi(), sip_show_registry(), sip_show_tcp(), and sip_show_users().
| #define 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" |
Referenced by __iax2_show_peers(), _sip_show_peers(), dahdi_show_channels(), dahdi_show_status(), dundi_show_mappings(), dundi_show_peers(), dundi_show_precache(), dundi_show_requests(), dundi_show_trans(), handle_cli_core_show_file_formats(), handle_cli_iax2_show_channels(), handle_cli_iax2_show_registry(), handle_cli_iax2_show_users(), handle_core_show_image_formats(), sip_show_channels(), sip_show_channelstats(), sip_show_inuse(), sip_show_registry(), and sip_show_tcp().
| #define GET_CHANNEL | ( | p | ) | ((p)->bearer ? (p)->bearer->channel : p->channel) |
Definition at line 1423 of file chan_dahdi.c.
Referenced by update_conf().
| #define HANGUP 1 |
Definition at line 15183 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 1497 of file chan_dahdi.c.
Referenced by dahdi_indicate(), and ss_thread().
| #define LINKSET_FLAG_EXPLICITACM (1 << 0) |
Definition at line 425 of file chan_dahdi.c.
Referenced by process_dahdi(), and ss7_start_call().
| #define LINKSTATE_DOWN (1 << 3) |
Definition at line 421 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_INALARM (1 << 0) |
Definition at line 418 of file chan_dahdi.c.
Referenced by linkset_addsigchan(), and ss7_linkset().
| #define LINKSTATE_STARTING (1 << 1) |
Definition at line 419 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define LINKSTATE_UP (1 << 2) |
Definition at line 420 of file chan_dahdi.c.
Referenced by ss7_linkset().
| #define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 399 of file chan_dahdi.c.
| #define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 400 of file chan_dahdi.c.
| #define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 16038 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 275 of file chan_dahdi.c.
Referenced by mkintf().
| #define MAX_SLAVES 4 |
Definition at line 628 of file chan_dahdi.c.
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 213 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
| #define NUM_CADENCE_MAX 25 |
Definition at line 1472 of file chan_dahdi.c.
Referenced by process_dahdi().
| #define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 274 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_pri_error(), dahdi_pri_message(), dahdi_restart(), handle_pri_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), linkset_addsigchan(), load_module(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), pri_is_up(), setup_dahdi(), and start_pri().
| #define NUM_SPANS 32 |
Definition at line 272 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_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_debug(), handle_ss7_show_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), linkset_addsigchan(), 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 584 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), ss_thread(), and unalloc_sub().
| #define POLARITY_REV 1 |
Definition at line 585 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 503 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PRI_EXPLICIT | ( | p | ) | (((p) >> 16) & 0x01) |
Definition at line 505 of file chan_dahdi.c.
Referenced by pri_find_principle().
| #define PRI_SPAN | ( | p | ) | (((p) >> 8) & 0xff) |
Definition at line 504 of file chan_dahdi.c.
Referenced by pri_dchannel(), and pri_find_principle().
| #define PROC_DAHDI_OPT_NOCHAN (1 << 0) |
process_dahdi() - ignore keyword 'channel' and similar
Definition at line 16092 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 16094 of file chan_dahdi.c.
Referenced by process_dahdi(), and setup_dahdi().
| #define PVT_TO_CHANNEL | ( | p | ) | (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0)) |
Definition at line 502 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), pri_check_restart(), pri_dchannel(), and ss_thread().
| #define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 397 of file chan_dahdi.c.
Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().
| #define sig2str dahdi_sig2str |
Definition at line 2476 of file chan_dahdi.c.
Referenced by action_dahdishowchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR) |
Definition at line 256 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR) |
Definition at line 257 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), pri_find_dchan(), process_dahdi(), ss_thread(), and start_pri().
| #define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 245 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM DAHDI_SIG_EM |
Definition at line 240 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 265 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 241 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 244 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 242 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 243 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 246 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 247 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 248 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 253 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 254 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXOLS DAHDI_SIG_FXOLS |
Definition at line 252 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 250 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
| #define SIG_FXSKS DAHDI_SIG_FXSKS |
Definition at line 251 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), pri_dchannel(), process_dahdi(), and ss_thread().
| #define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 249 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 266 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
Definition at line 267 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SIG_MFCR2 DAHDI_SIG_CAS |
Definition at line 259 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_sig2str(), do_monitor(), mkintf(), and process_dahdi().
| #define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 255 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF DAHDI_SIG_SF |
Definition at line 260 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 264 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 262 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 263 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), and ss_thread().
| #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 261 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
| #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR) |
Definition at line 258 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
| #define SMDI_MD_WAIT_TIMEOUT 1500 |
Definition at line 159 of file chan_dahdi.c.
Referenced by ss_thread().
| #define SS7_NAI_DYNAMIC -1 |
Definition at line 423 of file chan_dahdi.c.
Referenced by dahdi_call(), and process_dahdi().
| #define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 580 of file chan_dahdi.c.
Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), dahdi_show_channel(), and ss_thread().
| #define SUB_REAL 0 |
Active call
Definition at line 579 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), build_device(), bump_gains(), 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(), duplicate_pseudo(), enable_dtmf_detect(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), 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 581 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 TRAILER_MS 5 |
Referenced by dahdi_sendtext().
| #define TRANSFER 0 |
Definition at line 15182 of file chan_dahdi.c.
Referenced by action_transfer(), dahdi_fake_event(), send_agent_complete(), and try_calling().
| enum mwisend_states |
| MWI_SEND_NULL | |
| MWI_SEND_SA | |
| MWI_SEND_SA_WAIT | |
| MWI_SEND_PAUSE | |
| MWI_SEND_SPILL | |
| MWI_SEND_CLEANUP | |
| MWI_SEND_DONE |
Definition at line 633 of file chan_dahdi.c.
00633 { 00634 MWI_SEND_NULL = 0, 00635 MWI_SEND_SA, 00636 MWI_SEND_SA_WAIT, 00637 MWI_SEND_PAUSE, 00638 MWI_SEND_SPILL, 00639 MWI_SEND_CLEANUP, 00640 MWI_SEND_DONE, 00641 } mwisend_states;
| static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 6601 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, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().
Referenced by dahdi_exception(), and dahdi_read().
06602 { 06603 struct dahdi_pvt *p = ast->tech_pvt; 06604 int res; 06605 int usedindex=-1; 06606 int idx; 06607 struct ast_frame *f; 06608 06609 06610 idx = dahdi_get_index(ast, p, 1); 06611 06612 p->subs[idx].f.frametype = AST_FRAME_NULL; 06613 p->subs[idx].f.datalen = 0; 06614 p->subs[idx].f.samples = 0; 06615 p->subs[idx].f.mallocd = 0; 06616 p->subs[idx].f.offset = 0; 06617 p->subs[idx].f.subclass = 0; 06618 p->subs[idx].f.delivery = ast_tv(0,0); 06619 p->subs[idx].f.src = "dahdi_exception"; 06620 p->subs[idx].f.data.ptr = NULL; 06621 06622 06623 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 06624 /* If nobody owns us, absorb the event appropriately, otherwise 06625 we loop indefinitely. This occurs when, during call waiting, the 06626 other end hangs up our channel so that it no longer exists, but we 06627 have neither FLASH'd nor ONHOOK'd to signify our desire to 06628 change to the other channel. */ 06629 if (p->fake_event) { 06630 res = p->fake_event; 06631 p->fake_event = 0; 06632 } else 06633 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 06634 /* Switch to real if there is one and this isn't something really silly... */ 06635 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 06636 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 06637 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); 06638 p->owner = p->subs[SUB_REAL].owner; 06639 if (p->owner && ast_bridged_channel(p->owner)) 06640 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 06641 p->subs[SUB_REAL].needunhold = 1; 06642 } 06643 switch (res) { 06644 case DAHDI_EVENT_ONHOOK: 06645 dahdi_disable_ec(p); 06646 if (p->owner) { 06647 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name); 06648 dahdi_ring_phone(p); 06649 p->callwaitingrepeat = 0; 06650 p->cidcwexpire = 0; 06651 } else 06652 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 06653 update_conf(p); 06654 break; 06655 case DAHDI_EVENT_RINGOFFHOOK: 06656 dahdi_enable_ec(p); 06657 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06658 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 06659 p->subs[SUB_REAL].needanswer = 1; 06660 p->dialing = 0; 06661 } 06662 break; 06663 case DAHDI_EVENT_HOOKCOMPLETE: 06664 case DAHDI_EVENT_RINGERON: 06665 case DAHDI_EVENT_RINGEROFF: 06666 /* Do nothing */ 06667 break; 06668 case DAHDI_EVENT_WINKFLASH: 06669 p->flashtime = ast_tvnow(); 06670 if (p->owner) { 06671 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 06672 if (p->owner->_state != AST_STATE_UP) { 06673 /* Answer if necessary */ 06674 usedindex = dahdi_get_index(p->owner, p, 0); 06675 if (usedindex > -1) { 06676 p->subs[usedindex].needanswer = 1; 06677 } 06678 ast_setstate(p->owner, AST_STATE_UP); 06679 } 06680 p->callwaitingrepeat = 0; 06681 p->cidcwexpire = 0; 06682 if (ast_bridged_channel(p->owner)) 06683 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 06684 p->subs[SUB_REAL].needunhold = 1; 06685 } else 06686 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 06687 update_conf(p); 06688 break; 06689 default: 06690 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 06691 } 06692 f = &p->subs[idx].f; 06693 return f; 06694 } 06695 if (!(p->radio || (p->oprmode < 0))) 06696 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 06697 /* If it's not us, return NULL immediately */ 06698 if (ast != p->owner) { 06699 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 06700 f = &p->subs[idx].f; 06701 return f; 06702 } 06703 f = dahdi_handle_event(ast); 06704 return f; 06705 }
| static void __reg_module | ( | void | ) | [static] |
Definition at line 17500 of file chan_dahdi.c.
| static int __unload_module | ( | void | ) | [static] |
Definition at line 15849 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_DCHANS, NUM_SPANS, dahdi_pvt::owner, and pris.
Referenced by load_module(), and unload_module().
15850 { 15851 struct dahdi_pvt *p; 15852 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15853 int i, j; 15854 #endif 15855 15856 #ifdef HAVE_PRI 15857 for (i = 0; i < NUM_SPANS; i++) { 15858 if (pris[i].master != AST_PTHREADT_NULL) 15859 pthread_cancel(pris[i].master); 15860 } 15861 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 15862 ast_unregister_application(dahdi_send_keypad_facility_app); 15863 #ifdef HAVE_PRI_PROG_W_CAUSE 15864 ast_unregister_application(dahdi_send_callrerouting_facility_app); 15865 #endif 15866 #endif 15867 #if defined(HAVE_SS7) 15868 for (i = 0; i < NUM_SPANS; i++) { 15869 if (linksets[i].master != AST_PTHREADT_NULL) 15870 pthread_cancel(linksets[i].master); 15871 } 15872 ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 15873 #endif 15874 #if defined(HAVE_OPENR2) 15875 dahdi_r2_destroy_links(); 15876 ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli)); 15877 ast_unregister_application(dahdi_accept_r2_call_app); 15878 #endif 15879 15880 ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 15881 ast_manager_unregister( "DAHDIDialOffhook" ); 15882 ast_manager_unregister( "DAHDIHangup" ); 15883 ast_manager_unregister( "DAHDITransfer" ); 15884 ast_manager_unregister( "DAHDIDNDoff" ); 15885 ast_manager_unregister( "DAHDIDNDon" ); 15886 ast_manager_unregister("DAHDIShowChannels"); 15887 ast_manager_unregister("DAHDIRestart"); 15888 ast_channel_unregister(&dahdi_tech); 15889 ast_mutex_lock(&iflock); 15890 /* Hangup all interfaces if they have an owner */ 15891 p = iflist; 15892 while (p) { 15893 if (p->owner) 15894 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 15895 p = p->next; 15896 } 15897 ast_mutex_unlock(&iflock); 15898 ast_mutex_lock(&monlock); 15899 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 15900 pthread_cancel(monitor_thread); 15901 pthread_kill(monitor_thread, SIGURG); 15902 pthread_join(monitor_thread, NULL); 15903 } 15904 monitor_thread = AST_PTHREADT_STOP; 15905 ast_mutex_unlock(&monlock); 15906 15907 destroy_all_channels(); 15908 15909 #if defined(HAVE_PRI) 15910 for (i = 0; i < NUM_SPANS; i++) { 15911 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 15912 pthread_join(pris[i].master, NULL); 15913 for (j = 0; j < NUM_DCHANS; j++) { 15914 dahdi_close_pri_fd(&(pris[i]), j); 15915 } 15916 } 15917 #endif 15918 15919 #if defined(HAVE_SS7) 15920 for (i = 0; i < NUM_SPANS; i++) { 15921 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) 15922 pthread_join(linksets[i].master, NULL); 15923 for (j = 0; j < NUM_DCHANS; j++) { 15924 dahdi_close_ss7_fd(&(linksets[i]), j); 15925 } 15926 } 15927 #endif 15928 ast_cond_destroy(&ss_thread_complete); 15929 return 0; 15930 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 17500 of file chan_dahdi.c.
| static int action_dahdidialoffhook | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15289 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().
15290 { 15291 struct dahdi_pvt *p = NULL; 15292 const char *channel = astman_get_header(m, "DAHDIChannel"); 15293 const char *number = astman_get_header(m, "Number"); 15294 int i; 15295 15296 if (ast_strlen_zero(channel)) { 15297 astman_send_error(s, m, "No channel specified"); 15298 return 0; 15299 } 15300 if (ast_strlen_zero(number)) { 15301 astman_send_error(s, m, "No number specified"); 15302 return 0; 15303 } 15304 p = find_channel(atoi(channel)); 15305 if (!p) { 15306 astman_send_error(s, m, "No such channel"); 15307 return 0; 15308 } 15309 if (!p->owner) { 15310 astman_send_error(s, m, "Channel does not have it's owner"); 15311 return 0; 15312 } 15313 for (i = 0; i < strlen(number); i++) { 15314 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 15315 dahdi_queue_frame(p, &f, NULL); 15316 } 15317 astman_send_ack(s, m, "DAHDIDialOffhook"); 15318 return 0; 15319 }
| static int action_dahdidndoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15232 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().
15233 { 15234 struct dahdi_pvt *p = NULL; 15235 const char *channel = astman_get_header(m, "DAHDIChannel"); 15236 15237 if (ast_strlen_zero(channel)) { 15238 astman_send_error(s, m, "No channel specified"); 15239 return 0; 15240 } 15241 p = find_channel(atoi(channel)); 15242 if (!p) { 15243 astman_send_error(s, m, "No such channel"); 15244 return 0; 15245 } 15246 p->dnd = 0; 15247 astman_send_ack(s, m, "DND Disabled"); 15248 return 0; 15249 }
| static int action_dahdidndon | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15213 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().
15214 { 15215 struct dahdi_pvt *p = NULL; 15216 const char *channel = astman_get_header(m, "DAHDIChannel"); 15217 15218 if (ast_strlen_zero(channel)) { 15219 astman_send_error(s, m, "No channel specified"); 15220 return 0; 15221 } 15222 p = find_channel(atoi(channel)); 15223 if (!p) { 15224 astman_send_error(s, m, "No such channel"); 15225 return 0; 15226 } 15227 p->dnd = 1; 15228 astman_send_ack(s, m, "DND Enabled"); 15229 return 0; 15230 }
| static int action_dahdirestart | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 14475 of file chan_dahdi.c.
References astman_send_ack(), astman_send_error(), and dahdi_restart().
Referenced by load_module().
14476 { 14477 if (dahdi_restart() != 0) { 14478 astman_send_error(s, m, "Failed rereading DAHDI configuration"); 14479 return 1; 14480 } 14481 astman_send_ack(s, m, "DAHDIRestart: Success"); 14482 return 0; 14483 }
| static int action_dahdishowchannels | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15321 of file chan_dahdi.c.
References ast_channel::accountcode, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_pvt::dnd, get_alarms(), iflist, iflock, ast_channel::name, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.
Referenced by load_module().
15322 { 15323 struct dahdi_pvt *tmp = NULL; 15324 const char *id = astman_get_header(m, "ActionID"); 15325 const char *dahdichannel = astman_get_header(m, "DAHDIChannel"); 15326 char idText[256] = ""; 15327 int channels = 0; 15328 int dahdichanquery = -1; 15329 if (!ast_strlen_zero(dahdichannel)) { 15330 dahdichanquery = atoi(dahdichannel); 15331 } 15332 15333 astman_send_ack(s, m, "DAHDI channel status will follow"); 15334 if (!ast_strlen_zero(id)) 15335 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 15336 15337 ast_mutex_lock(&iflock); 15338 15339 tmp = iflist; 15340 while (tmp) { 15341 if (tmp->channel > 0) { 15342 int alm = get_alarms(tmp); 15343 15344 /* If a specific channel is queried for, only deliver status for that channel */ 15345 if (dahdichanquery > 0 && tmp->channel != dahdichanquery) 15346 continue; 15347 15348 channels++; 15349 if (tmp->owner) { 15350 /* Add data if we have a current call */ 15351 astman_append(s, 15352 "Event: DAHDIShowChannels\r\n" 15353 "DAHDIChannel: %d\r\n" 15354 "Channel: %s\r\n" 15355 "Uniqueid: %s\r\n" 15356 "AccountCode: %s\r\n" 15357 "Signalling: %s\r\n" 15358 "SignallingCode: %d\r\n" 15359 "Context: %s\r\n" 15360 "DND: %s\r\n" 15361 "Alarm: %s\r\n" 15362 "%s" 15363 "\r\n", 15364 tmp->channel, 15365 tmp->owner->name, 15366 tmp->owner->uniqueid, 15367 tmp->owner->accountcode, 15368 sig2str(tmp->sig), 15369 tmp->sig, 15370 tmp->context, 15371 tmp->dnd ? "Enabled" : "Disabled", 15372 alarm2str(alm), idText); 15373 } else { 15374 astman_append(s, 15375 "Event: DAHDIShowChannels\r\n" 15376 "DAHDIChannel: %d\r\n" 15377 "Signalling: %s\r\n" 15378 "SignallingCode: %d\r\n" 15379 "Context: %s\r\n" 15380 "DND: %s\r\n" 15381 "Alarm: %s\r\n" 15382 "%s" 15383 "\r\n", 15384 tmp->channel, sig2str(tmp->sig), tmp->sig, 15385 tmp->context, 15386 tmp->dnd ? "Enabled" : "Disabled", 15387 alarm2str(alm), idText); 15388 } 15389 } 15390 15391 tmp = tmp->next; 15392 } 15393 15394 ast_mutex_unlock(&iflock); 15395 15396 astman_append(s, 15397 "Event: DAHDIShowChannelsComplete\r\n" 15398 "%s" 15399 "Items: %d\r\n" 15400 "\r\n", 15401 idText, 15402 channels); 15403 return 0; 15404 }
| static int action_transfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15251 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().
15252 { 15253 struct dahdi_pvt *p = NULL; 15254 const char *channel = astman_get_header(m, "DAHDIChannel"); 15255 15256 if (ast_strlen_zero(channel)) { 15257 astman_send_error(s, m, "No channel specified"); 15258 return 0; 15259 } 15260 p = find_channel(atoi(channel)); 15261 if (!p) { 15262 astman_send_error(s, m, "No such channel"); 15263 return 0; 15264 } 15265 dahdi_fake_event(p,TRANSFER); 15266 astman_send_ack(s, m, "DAHDITransfer"); 15267 return 0; 15268 }
| static int action_transferhangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 15270 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().
15271 { 15272 struct dahdi_pvt *p = NULL; 15273 const char *channel = astman_get_header(m, "DAHDIChannel"); 15274 15275 if (ast_strlen_zero(channel)) { 15276 astman_send_error(s, m, "No channel specified"); 15277 return 0; 15278 } 15279 p = find_channel(atoi(channel)); 15280 if (!p) { 15281 astman_send_error(s, m, "No such channel"); 15282 return 0; 15283 } 15284 dahdi_fake_event(p,HANGUP); 15285 astman_send_ack(s, m, "DAHDIHangup"); 15286 return 0; 15287 }
| static char* alarm2str | ( | int | alm | ) | [static] |
Definition at line 2379 of file chan_dahdi.c.
References alarms, and ARRAY_LEN.
Referenced by action_dahdishowchannels(), and handle_alarms().
| static int alloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 2175 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().
02176 { 02177 struct dahdi_bufferinfo bi; 02178 int res; 02179 if (p->subs[x].dfd >= 0) { 02180 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 02181 return -1; 02182 } 02183 02184 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 02185 if (p->subs[x].dfd <= -1) { 02186 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 02187 return -1; 02188 } 02189 02190 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 02191 if (!res) { 02192 bi.txbufpolicy = p->buf_policy; 02193 bi.rxbufpolicy = p->buf_policy; 02194 bi.numbufs = p->buf_no; 02195 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 02196 if (res < 0) { 02197 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 02198 } 02199 } else 02200 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 02201 02202 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 02203 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 02204 dahdi_close_sub(p, x); 02205 p->subs[x].dfd = -1; 02206 return -1; 02207 } 02208 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 02209 return 0; 02210 }
| 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 12362 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().
12363 { 12364 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */ 12365 snprintf(buf, size, "%s", number); 12366 return; 12367 } 12368 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 12369 if (size) { 12370 *buf = '\0'; 12371 } 12372 return; 12373 } 12374 switch (plan) { 12375 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */ 12376 snprintf(buf, size, "%s%s", pri->internationalprefix, number); 12377 break; 12378 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */ 12379 snprintf(buf, size, "%s%s", pri->nationalprefix, number); 12380 break; 12381 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */ 12382 snprintf(buf, size, "%s%s", pri->localprefix, number); 12383 break; 12384 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */ 12385 snprintf(buf, size, "%s%s", pri->privateprefix, number); 12386 break; 12387 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */ 12388 snprintf(buf, size, "%s%s", pri->unknownprefix, number); 12389 break; 12390 default: /* other Q.931 dialplan => don't twiddle with callingnum */ 12391 snprintf(buf, size, "%s", number); 12392 break; 12393 } 12394 }
| static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5502 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, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by dahdi_handle_event().
05503 { 05504 /* In order to transfer, we need at least one of the channels to 05505 actually be in a call bridge. We can't conference two applications 05506 together (but then, why would we want to?) */ 05507 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 05508 /* The three-way person we're about to transfer to could still be in MOH, so 05509 stop if now if appropriate */ 05510 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 05511 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 05512 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 05513 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 05514 } 05515 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 05516 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 05517 } 05518 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 05519 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 05520 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 05521 return -1; 05522 } 05523 /* Orphan the channel after releasing the lock */ 05524 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 05525 unalloc_sub(p, SUB_THREEWAY); 05526 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 05527 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 05528 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 05529 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 05530 } 05531 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 05532 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05533 } 05534 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 05535 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 05536 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 05537 return -1; 05538 } 05539 /* Three-way is now the REAL */ 05540 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05541 ast_channel_unlock(p->subs[SUB_REAL].owner); 05542 unalloc_sub(p, SUB_THREEWAY); 05543 /* Tell the caller not to hangup */ 05544 return 1; 05545 } else { 05546 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n", 05547 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 05548 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05549 return -1; 05550 } 05551 return 0; 05552 }
| static int available | ( | struct dahdi_pvt * | p, | |
| int | channelmatch, | |||
| ast_group_t | groupmatch, | |||
| int * | busy, | |||
| int * | channelmatched, | |||
| int * | groupmatched | |||
| ) | [inline, static] |
Definition at line 10640 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().
10641 { 10642 int res; 10643 struct dahdi_params par; 10644 10645 /* First, check group matching */ 10646 if (groupmatch) { 10647 if ((p->group & groupmatch) != groupmatch) 10648 return 0; 10649 *groupmatched = 1; 10650 } 10651 /* Check to see if we have a channel match */ 10652 if (channelmatch != -1) { 10653 if (p->channel != channelmatch) 10654 return 0; 10655 *channelmatched = 1; 10656 } 10657 /* We're at least busy at this point */ 10658 if (busy) { 10659 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 10660 *busy = 1; 10661 } 10662 /* If do not disturb, definitely not */ 10663 if (p->dnd) 10664 return 0; 10665 /* If guard time, definitely not */ 10666 if (p->guardtime && (time(NULL) < p->guardtime)) 10667 return 0; 10668 10669 if (p->locallyblocked || p->remotelyblocked) 10670 return 0; 10671 10672 /* If no owner definitely available */ 10673 if (!p->owner) { 10674 #ifdef HAVE_PRI 10675 /* Trust PRI */ 10676 if (p->pri) { 10677 if (p->resetting || p->call) 10678 return 0; 10679 else 10680 return 1; 10681 } 10682 #endif 10683 #ifdef HAVE_SS7 10684 /* Trust SS7 */ 10685 if (p->ss7) { 10686 if (p->ss7call) 10687 return 0; 10688 else 10689 return 1; 10690 } 10691 #endif 10692 #ifdef HAVE_OPENR2 10693 /* Trust MFC/R2 */ 10694 if (p->mfcr2) { 10695 if (p->mfcr2call) 10696 return 0; 10697 else 10698 return 1; 10699 } 10700 #endif 10701 if (!(p->radio || (p->oprmode < 0))) 10702 { 10703 if (!p->sig || (p->sig == SIG_FXSLS)) 10704 return 1; 10705 /* Check hook state */ 10706 if (p->subs[SUB_REAL].dfd > -1) { 10707 memset(&par, 0, sizeof(par)); 10708 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 10709 } else { 10710 /* Assume not off hook on CVRS */ 10711 res = 0; 10712 par.rxisoffhook = 0; 10713 } 10714 if (res) { 10715 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 10716 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 10717 /* When "onhook" that means no battery on the line, and thus 10718 it is out of service..., if it's on a TDM card... If it's a channel 10719 bank, there is no telling... */ 10720 if (par.rxbits > -1) 10721 return 1; 10722 if (par.rxisoffhook) 10723 return 1; 10724 else 10725 return 0; 10726 } else if (par.rxisoffhook) { 10727 ast_debug(1, "Channel %d off hook, can't use\n", p->channel); 10728 /* Not available when the other end is off hook */ 10729 #ifdef DAHDI_CHECK_HOOKSTATE 10730 return 0; 10731 #else 10732 return 1; 10733 #endif 10734 } 10735 } 10736 return 1; 10737 } 10738 10739 /* If it's not an FXO, forget about call wait */ 10740 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 10741 return 0; 10742 10743 if (!p->callwaiting) { 10744 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 10745 return 0; 10746 } 10747 10748 if (p->subs[SUB_CALLWAIT].dfd > -1) { 10749 /* If there is already a call waiting call, then we can't take a second one */ 10750 return 0; 10751 } 10752 10753 if ((p->owner->_state != AST_STATE_UP) && 10754 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 10755 /* If the current call is not up, then don't allow the call */ 10756 return 0; 10757 } 10758 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 10759 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 10760 return 0; 10761 } 10762 /* We're cool */ 10763 return 1; 10764 }
| 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 15948 of file chan_dahdi.c.
References ast_log(), ast_verb, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_chan_conf::is_sig_auto, LOG_ERROR, LOG_WARNING, mkintf(), NUM_SPANS, dahdi_pri::pri, pris, dahdi_pvt::sig, sig2str, and dahdi_pri::trunkgroup.
Referenced by process_dahdi().
15949 { 15950 char *c, *chan; 15951 int x, start, finish; 15952 struct dahdi_pvt *tmp; 15953 #ifdef HAVE_PRI 15954 struct dahdi_pri *pri; 15955 int trunkgroup, y; 15956 #endif 15957 15958 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) { 15959 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 15960 return -1; 15961 } 15962 15963 c = ast_strdupa(value); 15964 15965 #ifdef HAVE_PRI 15966 pri = NULL; 15967 if (iscrv) { 15968 if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) { 15969 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno); 15970 return -1; 15971 } 15972 if (trunkgroup < 1) { 15973 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno); 15974 return -1; 15975 } 15976 c += y; 15977 for (y = 0; y < NUM_SPANS; y++) { 15978 if (pris[y].trunkgroup == trunkgroup) { 15979 pri = pris + y; 15980 break; 15981 } 15982 } 15983 if (!pri) { 15984 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno); 15985 return -1; 15986 } 15987 } 15988 #endif 15989 15990 while ((chan = strsep(&c, ","))) { 15991 if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) { 15992 /* Range */ 15993 } else if (sscanf(chan, "%30d", &start)) { 15994 /* Just one */ 15995 finish = start; 15996 } else if (!strcasecmp(chan, "pseudo")) { 15997 finish = start = CHAN_PSEUDO; 15998 if (found_pseudo) 15999 *found_pseudo = 1; 16000 } else { 16001 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 16002 return -1; 16003 } 16004 if (finish < start) { 16005 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 16006 x = finish; 16007 finish = start; 16008 start = x; 16009 } 16010 16011 for (x = start; x <= finish; x++) { 16012 #ifdef HAVE_PRI 16013 tmp = mkintf(x, conf, pri, reload); 16014 #else 16015 tmp = mkintf(x, conf, NULL, reload); 16016 #endif 16017 16018 if (tmp) { 16019 #ifdef HAVE_PRI 16020 if (pri) 16021 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 16022 else 16023 #endif 16024 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 16025 } else { 16026 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 16027 (reload == 1) ? "reconfigure" : "register", value); 16028 return -1; 16029 } 16030 } 16031 } 16032 16033 return 0; 16034 }
| static void build_status | ( | char * | s, | |
| size_t | len, | |||
| int | status, | |||
| int | active | |||
| ) | [static] |
Definition at line 13770 of file chan_dahdi.c.
References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.
Referenced by handle_pri_show_span(), and handle_pri_show_spans().
13771 { 13772 if (!s || len < 1) { 13773 return; 13774 } 13775 s[0] = '\0'; 13776 if (status & DCHAN_PROVISIONED) 13777 strncat(s, "Provisioned, ", len - strlen(s) - 1); 13778 if (!(status & DCHAN_NOTINALARM)) 13779 strncat(s, "In Alarm, ", len - strlen(s) - 1); 13780 if (status & DCHAN_UP) 13781 strncat(s, "Up", len - strlen(s) - 1); 13782 else 13783 strncat(s, "Down", len - strlen(s) - 1); 13784 if (active) 13785 strncat(s, ", Active", len - strlen(s) - 1); 13786 else 13787 strncat(s, ", Standby", len - strlen(s) - 1); 13788 s[len - 1] = '\0'; 13789 }
| static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2836 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().
02837 { 02838 int res; 02839 02840 /* Bump receive gain by value stored in cid_rxgain */ 02841 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law); 02842 if (res) { 02843 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 02844 return -1; 02845 } 02846 02847 return 0; 02848 }
| static int calc_energy | ( | const unsigned char * | buf, | |
| int | len, | |||
| int | law | |||
| ) | [static] |
Definition at line 8911 of file chan_dahdi.c.
References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.
Referenced by do_monitor(), and mwi_thread().
| static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5554 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().
05555 { 05556 struct dahdi_confinfo ci; 05557 /* Fine if we already have a master, etc */ 05558 if (p->master || (p->confno > -1)) 05559 return 0; 05560 memset(&ci, 0, sizeof(ci)); 05561 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 05562 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 05563 return 0; 05564 } 05565 /* If we have no master and don't have a confno, then 05566 if we're in a conference, it's probably a MeetMe room or 05567 some such, so don't let us 3-way out! */ 05568 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 05569 ast_verb(3, "Avoiding 3-way call when in an external conference\n"); 05570 return 1; 05571 } 05572 return 0; 05573 }
| static unsigned char cid_pres2ss7pres | ( | int | cid_pres | ) | [static] |
Definition at line 3088 of file chan_dahdi.c.
Referenced by dahdi_call().
| static unsigned char cid_pres2ss7screen | ( | int | cid_pres | ) | [static] |
Definition at line 3095 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 13662 of file chan_dahdi.c.
References complete_span_helper().
Referenced by handle_pri_debug(), and handle_pri_show_span().
13663 { 13664 return complete_span_helper(line,word,pos,state,3); 13665 }
| static char* complete_span_helper | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state, | |||
| int | rpos | |||
| ) | [static] |
Definition at line 13641 of file chan_dahdi.c.
References asprintf, ast_log(), errno, LOG_WARNING, NUM_SPANS, and pris.
Referenced by complete_span_4().
13642 { 13643 int which, span; 13644 char *ret = NULL; 13645 13646 if (pos != rpos) 13647 return ret; 13648 13649 for (which = span = 0; span < NUM_SPANS; span++) { 13650 if (pris[span].pri && ++which > state) { 13651 if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */ 13652 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 13653 } 13654 break; 13655 } 13656 } 13657 return ret; 13658 }
| static int conf_add | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx, | |||
| int | slavechannel | |||
| ) | [static] |
Definition at line 2478 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().
02479 { 02480 /* If the conference already exists, and we're already in it 02481 don't bother doing anything */ 02482 struct dahdi_confinfo zi; 02483 02484 memset(&zi, 0, sizeof(zi)); 02485 zi.chan = 0; 02486 02487 if (slavechannel > 0) { 02488 /* If we have only one slave, do a digital mon */ 02489 zi.confmode = DAHDI_CONF_DIGITALMON; 02490 zi.confno = slavechannel; 02491 } else { 02492 if (!idx) { 02493 /* Real-side and pseudo-side both participate in conference */ 02494 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 02495 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 02496 } else 02497 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 02498 zi.confno = p->confno; 02499 } 02500 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 02501 return 0; 02502 if (c->dfd < 0) 02503 return 0; 02504 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02505 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 02506 return -1; 02507 } 02508 if (slavechannel < 1) { 02509 p->confno = zi.confno; 02510 } 02511 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02512 ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02513 return 0; 02514 }
| static int conf_del | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c, | |||
| int | idx | |||
| ) | [static] |
Definition at line 2527 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().
02528 { 02529 struct dahdi_confinfo zi; 02530 if (/* Can't delete if there's no dfd */ 02531 (c->dfd < 0) || 02532 /* Don't delete from the conference if it's not our conference */ 02533 !isourconf(p, c) 02534 /* Don't delete if we don't think it's conferenced at all (implied) */ 02535 ) return 0; 02536 memset(&zi, 0, sizeof(zi)); 02537 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 02538 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 02539 return -1; 02540 } 02541 ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 02542 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 02543 return 0; 02544 }
| static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4718 of file chan_dahdi.c.
References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tvnow(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_enable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_train_ec(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::hanguponpolarityswitch, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, dahdi_pvt::span, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.
04719 { 04720 struct dahdi_pvt *p = ast->tech_pvt; 04721 int res = 0; 04722 int idx; 04723 int oldstate = ast->_state; 04724 ast_setstate(ast, AST_STATE_UP); 04725 ast_mutex_lock(&p->lock); 04726 idx = dahdi_get_index(ast, p, 0); 04727 if (idx < 0) 04728 idx = SUB_REAL; 04729 /* nothing to do if a radio channel */ 04730 if ((p->radio || (p->oprmode < 0))) { 04731 ast_mutex_unlock(&p->lock); 04732 return 0; 04733 } 04734 switch (p->sig) { 04735 case SIG_FXSLS: 04736 case SIG_FXSGS: 04737 case SIG_FXSKS: 04738 p->ringt = 0; 04739 /* Fall through */ 04740 case SIG_EM: 04741 case SIG_EM_E1: 04742 case SIG_EMWINK: 04743 case SIG_FEATD: 04744 case SIG_FEATDMF: 04745 case SIG_FEATDMF_TA: 04746 case SIG_E911: 04747 case SIG_FGC_CAMA: 04748 case SIG_FGC_CAMAMF: 04749 case SIG_FEATB: 04750 case SIG_SF: 04751 case SIG_SFWINK: 04752 case SIG_SF_FEATD: 04753 case SIG_SF_FEATDMF: 04754 case SIG_SF_FEATB: 04755 case SIG_FXOLS: 04756 case SIG_FXOGS: 04757 case SIG_FXOKS: 04758 /* Pick up the line */ 04759 ast_debug(1, "Took %s off hook\n", ast->name); 04760 if (p->hanguponpolarityswitch) { 04761 p->polaritydelaytv = ast_tvnow(); 04762 } 04763 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 04764 tone_zone_play_tone(p->subs[idx].dfd, -1); 04765 p->dialing = 0; 04766 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 04767 if (oldstate == AST_STATE_RINGING) { 04768 ast_debug(1, "Finally swapping real and threeway\n"); 04769 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 04770 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04771 p->owner = p->subs[SUB_REAL].owner; 04772 } 04773 } 04774 if (p->sig & __DAHDI_SIG_FXS) { 04775 dahdi_enable_ec(p); 04776 dahdi_train_ec(p); 04777 } 04778 break; 04779 #ifdef HAVE_PRI 04780 case SIG_BRI: 04781 case SIG_BRI_PTMP: 04782 case SIG_PRI: 04783 /* Send a pri acknowledge */ 04784 if (!pri_grab(p, p->pri)) { 04785 p->proceeding = 1; 04786 p->dialing = 0; 04787 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 04788 pri_rel(p->pri); 04789 } else { 04790 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 04791 res = -1; 04792 } 04793 break; 04794 #endif 04795 #ifdef HAVE_SS7 04796 case SIG_SS7: 04797 if (!ss7_grab(p, p->ss7)) { 04798 p->proceeding = 1; 04799 res = isup_anm(p->ss7->ss7, p->ss7call); 04800 ss7_rel(p->ss7); 04801 } else { 04802 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span); 04803 res = -1; 04804 } 04805 break; 04806 #endif 04807 #ifdef HAVE_OPENR2 04808 case SIG_MFCR2: 04809 if (!p->mfcr2_call_accepted) { 04810 /* The call was not accepted on offer nor the user, so it must be accepted now before answering, 04811 openr2_chan_answer_call will be called when the callback on_call_accepted is executed */ 04812 p->mfcr2_answer_pending = 1; 04813 if (p->mfcr2_charge_calls) { 04814 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel); 04815 openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE); 04816 } else { 04817 ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel); 04818 openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE); 04819 } 04820 } else { 04821 ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel); 04822 dahdi_r2_answer(p); 04823 } 04824 break; 04825 #endif 04826 case 0: 04827 ast_mutex_unlock(&p->lock); 04828 return 0; 04829 default: 04830 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 04831 res = -1; 04832 } 04833 ast_mutex_unlock(&p->lock); 04834 return res; 04835 }
| 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 5156 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(), ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, master, ast_channel::name, 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().
05157 { 05158 struct ast_channel *who; 05159 struct dahdi_pvt *p0, *p1, *op0, *op1; 05160 struct dahdi_pvt *master = NULL, *slave = NULL; 05161 struct ast_frame *f; 05162 int inconf = 0; 05163 int nothingok = 1; 05164 int ofd0, ofd1; 05165 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 05166 int os0 = -1, os1 = -1; 05167 int priority = 0; 05168 struct ast_channel *oc0, *oc1; 05169 enum ast_bridge_result res; 05170 05171 #ifdef PRI_2BCT 05172 int triedtopribridge = 0; 05173 q931_call *q931c0 = NULL, *q931c1 = NULL; 05174 #endif 05175 05176 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 05177 There is code below to handle it properly until DTMF is actually seen, 05178 but due to currently unresolved issues it's ignored... 05179 */ 05180 05181 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 05182 return AST_BRIDGE_FAILED_NOWARN; 05183 05184 ast_channel_lock(c0); 05185 while (ast_channel_trylock(c1)) { 05186 CHANNEL_DEADLOCK_AVOIDANCE(c0); 05187 } 05188 05189 p0 = c0->tech_pvt; 05190 p1 = c1->tech_pvt; 05191 /* cant do pseudo-channels here */ 05192 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 05193 ast_channel_unlock(c0); 05194 ast_channel_unlock(c1); 05195 return AST_BRIDGE_FAILED_NOWARN; 05196 } 05197 05198 oi0 = dahdi_get_index(c0, p0, 0); 05199 oi1 = dahdi_get_index(c1, p1, 0); 05200 if ((oi0 < 0) || (oi1 < 0)) { 05201 ast_channel_unlock(c0); 05202 ast_channel_unlock(c1); 05203 return AST_BRIDGE_FAILED; 05204 } 05205 05206 op0 = p0 = c0->tech_pvt; 05207 op1 = p1 = c1->tech_pvt; 05208 ofd0 = c0->fds[0]; 05209 ofd1 = c1->fds[0]; 05210 oc0 = p0->owner; 05211 oc1 = p1->owner; 05212 05213 if (ast_mutex_trylock(&p0->lock)) { 05214 /* Don't block, due to potential for deadlock */ 05215 ast_channel_unlock(c0); 05216 ast_channel_unlock(c1); 05217 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 05218 return AST_BRIDGE_RETRY; 05219 } 05220 if (ast_mutex_trylock(&p1->lock)) { 05221 /* Don't block, due to potential for deadlock */ 05222 ast_mutex_unlock(&p0->lock); 05223 ast_channel_unlock(c0); 05224 ast_channel_unlock(c1); 05225 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 05226 return AST_BRIDGE_RETRY; 05227 } 05228 05229 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 05230 if (p0->owner && p1->owner) { 05231 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 05232 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 05233 master = p0; 05234 slave = p1; 05235 inconf = 1; 05236 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 05237 master = p1; 05238 slave = p0; 05239 inconf = 1; 05240 } else { 05241 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 05242 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 05243 p0->channel, 05244 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 05245 p0->subs[SUB_REAL].inthreeway, p0->channel, 05246 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 05247 p1->subs[SUB_REAL].inthreeway); 05248 } 05249 nothingok = 0; 05250 } 05251 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 05252 if (p1->subs[SUB_THREEWAY].inthreeway) { 05253 master = p1; 05254 slave = p0; 05255 nothingok = 0; 05256 } 05257 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 05258 if (p0->subs[SUB_THREEWAY].inthreeway) { 05259 master = p0; 05260 slave = p1; 05261 nothingok = 0; 05262 } 05263 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 05264 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 05265 don't put us in anything */ 05266 if (p1->subs[SUB_CALLWAIT].inthreeway) { 05267 master = p1; 05268 slave = p0; 05269 nothingok = 0; 05270 } 05271 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 05272 /* Same as previous */ 05273 if (p0->subs[SUB_CALLWAIT].inthreeway) { 05274 master = p0; 05275 slave = p1; 05276 nothingok = 0; 05277 } 05278 } 05279 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n", 05280 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 05281 if (master && slave) { 05282 /* Stop any tones, or play ringtone as appropriate. If they're bridged 05283 in an active threeway call with a channel that is ringing, we should 05284 indicate ringing. */ 05285 if ((oi1 == SUB_THREEWAY) && 05286 p1->subs[SUB_THREEWAY].inthreeway && 05287 p1->subs[SUB_REAL].owner && 05288 p1->subs[SUB_REAL].inthreeway && 05289 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 05290 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 05291 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 05292 os1 = p1->subs[SUB_REAL].owner->_state; 05293 } else { 05294 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 05295 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 05296 } 05297 if ((oi0 == SUB_THREEWAY) && 05298 p0->subs[SUB_THREEWAY].inthreeway && 05299 p0->subs[SUB_REAL].owner && 05300 p0->subs[SUB_REAL].inthreeway && 05301 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 05302 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 05303 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 05304 os0 = p0->subs[SUB_REAL].owner->_state; 05305 } else { 05306 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 05307 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 05308 } 05309 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 05310 if (!p0->echocanbridged || !p1->echocanbridged) { 05311 /* Disable echo cancellation if appropriate */ 05312 dahdi_disable_ec(p0); 05313 dahdi_disable_ec(p1); 05314 } 05315 } 05316 dahdi_link(slave, master); 05317 master->inconference = inconf; 05318 } else if (!nothingok) 05319 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 05320 05321 update_conf(p0); 05322 update_conf(p1); 05323 t0 = p0->subs[SUB_REAL].inthreeway; 05324 t1 = p1->subs[SUB_REAL].inthreeway; 05325 05326 ast_mutex_unlock(&p0->lock); 05327 ast_mutex_unlock(&p1->lock); 05328 05329 ast_channel_unlock(c0); 05330 ast_channel_unlock(c1); 05331 05332 /* Native bridge failed */ 05333 if ((!master || !slave) && !nothingok) { 05334 dahdi_enable_ec(p0); 05335 dahdi_enable_ec(p1); 05336 return AST_BRIDGE_FAILED; 05337 } 05338 05339 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name); 05340 05341 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 05342 disable_dtmf_detect(op0); 05343 05344 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 05345 disable_dtmf_detect(op1); 05346 05347 for (;;) { 05348 struct ast_channel *c0_priority[2] = {c0, c1}; 05349 struct ast_channel *c1_priority[2] = {c1, c0}; 05350 05351 /* Here's our main loop... Start by locking things, looking for private parts, 05352 and then balking if anything is wrong */ 05353 05354 ast_channel_lock(c0); 05355 while (ast_channel_trylock(c1)) { 05356 CHANNEL_DEADLOCK_AVOIDANCE(c0); 05357 } 05358 05359 p0 = c0->tech_pvt; 05360 p1 = c1->tech_pvt; 05361 05362 if (op0 == p0) 05363 i0 = dahdi_get_index(c0, p0, 1); 05364 if (op1 == p1) 05365 i1 = dahdi_get_index(c1, p1, 1); 05366 05367 ast_channel_unlock(c0); 05368 ast_channel_unlock(c1); 05369 05370 if (!timeoutms || 05371 (op0 != p0) || 05372 (op1 != p1) || 05373 (ofd0 != c0->fds[0]) || 05374 (ofd1 != c1->fds[0]) || 05375 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 05376 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 05377 (oc0 != p0->owner) || 05378 (oc1 != p1->owner) || 05379 (t0 != p0->subs[SUB_REAL].inthreeway) || 05380 (t1 != p1->subs[SUB_REAL].inthreeway) || 05381 (oi0 != i0) || 05382 (oi1 != i1)) { 05383 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 05384 op0->channel, oi0, op1->channel, oi1); 05385 res = AST_BRIDGE_RETRY; 05386 goto return_from_bridge; 05387 } 05388 05389 #ifdef PRI_2BCT 05390 q931c0 = p0->call; 05391 q931c1 = p1->call; 05392 if (p0->transfer && p1->transfer 05393 && q931c0 && q931c1 05394 && !triedtopribridge) { 05395 pri_channel_bridge(q931c0, q931c1); 05396 triedtopribridge = 1; 05397 } 05398 #endif 05399 05400 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 05401 if (!who) { 05402 ast_debug(1, "Ooh, empty read...\n"); 05403 continue; 05404 } 05405 f = ast_read(who); 05406 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 05407 *fo = f; 05408 *rc = who; 05409 res = AST_BRIDGE_COMPLETE; 05410 goto return_from_bridge; 05411 } 05412 if (f->frametype == AST_FRAME_DTMF) { 05413 if ((who == c0) && p0->pulsedial) { 05414 ast_write(c1, f); 05415 } else if ((who == c1) && p1->pulsedial) { 05416 ast_write(c0, f); 05417 } else { 05418 *fo = f; 05419 *rc = who; 05420 res = AST_BRIDGE_COMPLETE; 05421 goto return_from_bridge; 05422 } 05423 } 05424 ast_frfree(f); 05425 05426 /* Swap who gets priority */ 05427 priority = !priority; 05428 } 05429 05430 return_from_bridge: 05431 if (op0 == p0) 05432 dahdi_enable_ec(p0); 05433 05434 if (op1 == p1) 05435 dahdi_enable_ec(p1); 05436 05437 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 05438 enable_dtmf_detect(op0); 05439 05440 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 05441 enable_dtmf_detect(op1); 05442 05443 dahdi_unlink(slave, master, 1); 05444 05445 return res; 05446 }
| static int dahdi_call | ( | struct ast_channel * | ast, | |
| char * | rdest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 3101 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::answeronpolarityswitch, ast_callerid_generate(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_OFFHOOK, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_tvnow(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_ref_pc, dahdi_ss7::called_nai, dahdi_ss7::calling_nai, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, CANPROGRESSDETECT, dahdi_pvt::channel, dahdi_pvt::cic, ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, cid_pres2ss7pres(), cid_pres2ss7screen(), ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::dpc, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, dahdi_pvt::gen_add_nai, dahdi_pvt::gen_add_num_plan, dahdi_pvt::gen_add_pres_ind, dahdi_pvt::gen_add_type, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, dahdi_ss7::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::lspi_ident, MAX_CALLERID_SIZE, ast_channel::name, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), SS7_NAI_DYNAMIC, ss7_rel(), dahdi_pvt::ss7call, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::waitfordialtone, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.
03102 { 03103 struct dahdi_pvt *p = ast->tech_pvt; 03104 int x, res, idx,mysig; 03105 char *c, *n, *l; 03106 #ifdef HAVE_PRI 03107 char *s = NULL; 03108 #endif 03109 char dest[256]; /* must be same length as p->dialdest */ 03110 ast_mutex_lock(&p->lock); 03111 ast_copy_string(dest, rdest, sizeof(dest)); 03112 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 03113 if ((ast->_state == AST_STATE_BUSY)) { 03114 p->subs[SUB_REAL].needbusy = 1; 03115 ast_mutex_unlock(&p->lock); 03116 return 0; 03117 } 03118 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 03119 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 03120 ast_mutex_unlock(&p->lock); 03121 return -1; 03122 } 03123 p->waitingfordt.tv_sec = 0; 03124 p->dialednone = 0; 03125 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 03126 { 03127 /* Special pseudo -- automatically up */ 03128 ast_setstate(ast, AST_STATE_UP); 03129 ast_mutex_unlock(&p->lock); 03130 return 0; 03131 } 03132 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 03133 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 03134 if (res) 03135 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 03136 p->outgoing = 1; 03137 03138 if (IS_DIGITAL(ast->transfercapability)){ 03139 set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law); 03140 } else { 03141 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 03142 } 03143 03144 mysig = p->sig; 03145 if (p->outsigmod > -1) 03146 mysig = p->outsigmod; 03147 03148 switch (mysig) { 03149 case SIG_FXOLS: 03150 case SIG_FXOGS: 03151 case SIG_FXOKS: 03152 if (p->owner == ast) { 03153 /* Normal ring, on hook */ 03154 03155 /* Don't send audio while on hook, until the call is answered */ 03156 p->dialing = 1; 03157 if (p->use_callerid) { 03158 /* Generate the Caller-ID spill if desired */ 03159 if (p->cidspill) { 03160 ast_log(LOG_WARNING, "cidspill already exists??\n"); 03161 ast_free(p->cidspill); 03162 } 03163 p->callwaitcas = 0; 03164 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 03165 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 03166 p->cidpos = 0; 03167 send_callerid(p); 03168 } 03169 } 03170 /* Choose proper cadence */ 03171 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 03172 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 03173 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 03174 p->cidrings = cidrings[p->distinctivering - 1]; 03175 } else { 03176 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 03177 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 03178 p->cidrings = p->sendcalleridafter; 03179 } 03180 03181 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 03182 c = strchr(dest, '/'); 03183 if (c) 03184 c++; 03185 if (c && (strlen(c) < p->stripmsd)) { 03186 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03187 c = NULL; 03188 } 03189 if (c) { 03190 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03191 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 03192 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c); 03193 } else { 03194 p->dop.dialstr[0] = '\0'; 03195 } 03196 x = DAHDI_RING; 03197 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 03198 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 03199 ast_mutex_unlock(&p->lock); 03200 return -1; 03201 } 03202 p->dialing = 1; 03203 } else { 03204 /* Call waiting call */ 03205 p->callwaitrings = 0; 03206 if (ast->cid.cid_num) 03207 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 03208 else 03209 p->callwait_num[0] = '\0'; 03210 if (ast->cid.cid_name) 03211 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 03212 else 03213 p->callwait_name[0] = '\0'; 03214 /* Call waiting tone instead */ 03215 if (dahdi_callwait(ast)) { 03216 ast_mutex_unlock(&p->lock); 03217 return -1; 03218 } 03219 /* Make ring-back */ 03220 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 03221 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 03222 } 03223 n = ast->cid.cid_name; 03224 l = ast->cid.cid_num; 03225 if (l) 03226 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 03227 else 03228 p->lastcid_num[0] = '\0'; 03229 if (n) 03230 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 03231 else 03232 p->lastcid_name[0] = '\0'; 03233 ast_setstate(ast, AST_STATE_RINGING); 03234 idx = dahdi_get_index(ast, p, 0); 03235 if (idx > -1) { 03236 p->subs[idx].needringing = 1; 03237 } 03238 break; 03239 case SIG_FXSLS: 03240 case SIG_FXSGS: 03241 case SIG_FXSKS: 03242 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 03243 ast_debug(1, "Ignore possible polarity reversal on line seizure\n"); 03244 p->polaritydelaytv = ast_tvnow(); 03245 } 03246 /* fall through */ 03247 case SIG_EMWINK: 03248 case SIG_EM: 03249 case SIG_EM_E1: 03250 case SIG_FEATD: 03251 case SIG_FEATDMF: 03252 case SIG_E911: 03253 case SIG_FGC_CAMA: 03254 case SIG_FGC_CAMAMF: 03255 case SIG_FEATB: 03256 case SIG_SFWINK: 03257 case SIG_SF: 03258 case SIG_SF_FEATD: 03259 case SIG_SF_FEATDMF: 03260 case SIG_FEATDMF_TA: 03261 case SIG_SF_FEATB: 03262 c = strchr(dest, '/'); 03263 if (c) 03264 c++; 03265 else 03266 c = ""; 03267 if (strlen(c) < p->stripmsd) { 03268 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03269 ast_mutex_unlock(&p->lock); 03270 return -1; 03271 } 03272 #ifdef HAVE_PRI 03273 /* Start the trunk, if not GR-303 */ 03274 if (!p->pri) { 03275 #endif 03276 x = DAHDI_START; 03277 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03278 if (res < 0) { 03279 if (errno != EINPROGRESS) { 03280 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 03281 ast_mutex_unlock(&p->lock); 03282 return -1; 03283 } 03284 } 03285 #ifdef HAVE_PRI 03286 } 03287 #endif 03288 ast_debug(1, "Dialing '%s'\n", c); 03289 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03290 03291 c += p->stripmsd; 03292 03293 switch (mysig) { 03294 case SIG_FEATD: 03295 l = ast->cid.cid_num; 03296 if (l) 03297 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 03298 else 03299 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 03300 break; 03301 case SIG_FEATDMF: 03302 l = ast->cid.cid_num; 03303 if (l) 03304 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 03305 else 03306 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 03307 break; 03308 case SIG_FEATDMF_TA: 03309 { 03310 const char *cic, *ozz; 03311 03312 /* If you have to go through a Tandem Access point you need to use this */ 03313 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 03314 if (!ozz) 03315 ozz = defaultozz; 03316 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 03317 if (!cic) 03318 cic = defaultcic; 03319 if (!ozz || !cic) { 03320 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 03321 ast_mutex_unlock(&p->lock); 03322 return -1; 03323 } 03324 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 03325 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 03326 p->whichwink = 0; 03327 } 03328 break; 03329 case SIG_E911: 03330 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 03331 break; 03332 case SIG_FGC_CAMA: 03333 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 03334 break; 03335 case SIG_FGC_CAMAMF: 03336 case SIG_FEATB: 03337 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 03338 break; 03339 default: 03340 if (p->pulse) 03341 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 03342 else 03343 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 03344 break; 03345 } 03346 03347 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 03348 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 03349 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 03350 p->echorest[sizeof(p->echorest) - 1] = '\0'; 03351 p->echobreak = 1; 03352 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 03353 } else 03354 p->echobreak = 0; 03355 03356 /* waitfordialtone ? */ 03357 #ifdef HAVE_PRI 03358 if (!p->pri) { 03359 #endif 03360 if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) { 03361 ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone); 03362 gettimeofday(&p->waitingfordt,NULL); 03363 ast_setstate(ast, AST_STATE_OFFHOOK); 03364 break; 03365 } 03366 #ifdef HAVE_PRI 03367 } 03368 #endif 03369 if (!res) { 03370 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 03371 int saveerr = errno; 03372 03373 x = DAHDI_ONHOOK; 03374 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03375 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 03376 ast_mutex_unlock(&p->lock); 03377 return -1; 03378 } 03379 } else 03380 ast_debug(1, "Deferring dialing...\n"); 03381 03382 p->dialing = 1; 03383 if (ast_strlen_zero(c)) 03384 p->dialednone = 1; 03385 ast_setstate(ast, AST_STATE_DIALING); 03386 break; 03387 case 0: 03388 /* Special pseudo -- automatically up*/ 03389 ast_setstate(ast, AST_STATE_UP); 03390 break; 03391 case SIG_PRI: 03392 case SIG_BRI: 03393 case SIG_BRI_PTMP: 03394 case SIG_SS7: 03395 case SIG_MFCR2: 03396 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 03397 p->dialdest[0] = '\0'; 03398 p->dialing = 1; 03399 break; 03400 default: 03401 ast_debug(1, "not yet implemented\n"); 03402 ast_mutex_unlock(&p->lock); 03403 return -1; 03404 } 03405 #ifdef HAVE_SS7 03406 if (p->ss7) { 03407 char ss7_called_nai; 03408 int called_nai_strip; 03409 char ss7_calling_nai; 03410 int calling_nai_strip; 03411 const char *charge_str = NULL; 03412 const char *gen_address = NULL; 03413 const char *gen_digits = NULL; 03414 const char *gen_dig_type = NULL; 03415 const char *gen_dig_scheme = NULL; 03416 const char *gen_name = NULL; 03417 const char *jip_digits = NULL; 03418 const char *lspi_ident = NULL; 03419 const char *rlt_flag = NULL; 03420 const char *call_ref_id = NULL; 03421 const char *call_ref_pc = NULL; 03422 const char *send_far = NULL; 03423 03424 c = strchr(dest, '/'); 03425 if (c) { 03426 c++; 03427 } else { 03428 c = ""; 03429 } 03430 if (strlen(c) < p->stripmsd) { 03431 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03432 ast_mutex_unlock(&p->lock); 03433 return -1; 03434 } 03435 03436 if (!p->hidecallerid) { 03437 l = ast->cid.cid_num; 03438 } else { 03439 l = NULL; 03440 } 03441 03442 if (ss7_grab(p, p->ss7)) { 03443 ast_log(LOG_WARNING, "Failed to grab SS7!\n"); 03444 ast_mutex_unlock(&p->lock); 03445 return -1; 03446 } 03447 p->digital = IS_DIGITAL(ast->transfercapability); 03448 p->ss7call = isup_new_call(p->ss7->ss7); 03449 03450 if (!p->ss7call) { 03451 ss7_rel(p->ss7); 03452 ast_mutex_unlock(&p->lock); 03453 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n"); 03454 return -1; 03455 } 03456 03457 called_nai_strip = 0; 03458 ss7_called_nai = p->ss7->called_nai; 03459 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */ 03460 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 03461 called_nai_strip = strlen(p->ss7->internationalprefix); 03462 ss7_called_nai = SS7_NAI_INTERNATIONAL; 03463 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 03464 called_nai_strip = strlen(p->ss7->nationalprefix); 03465 ss7_called_nai = SS7_NAI_NATIONAL; 03466 } else { 03467 ss7_called_nai = SS7_NAI_SUBSCRIBER; 03468 } 03469 } 03470 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7); 03471 03472 calling_nai_strip = 0; 03473 ss7_calling_nai = p->ss7->calling_nai; 03474 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */ 03475 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) { 03476 calling_nai_strip = strlen(p->ss7->internationalprefix); 03477 ss7_calling_nai = SS7_NAI_INTERNATIONAL; 03478 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) { 03479 calling_nai_strip = strlen(p->ss7->nationalprefix); 03480 ss7_calling_nai = SS7_NAI_NATIONAL; 03481 } else { 03482 ss7_calling_nai = SS7_NAI_SUBSCRIBER; 03483 } 03484 } 03485 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai, 03486 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED), 03487 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED ); 03488 03489 isup_set_oli(p->ss7call, ast->cid.cid_ani2); 03490 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc); 03491 03492 ast_channel_lock(ast); 03493 /* Set the charge number if it is set */ 03494 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER"); 03495 if (charge_str) 03496 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10); 03497 03498 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS"); 03499 if (gen_address) 03500 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 */ 03501 03502 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS"); 03503 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE"); 03504 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME"); 03505 if (gen_digits) 03506 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 03507 03508 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME"); 03509 if (gen_name) 03510 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED); 03511 03512 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP"); 03513 if (jip_digits) 03514 isup_set_jip_digits(p->ss7call, jip_digits); 03515 03516 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT"); 03517 if (lspi_ident) 03518 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 03519 03520 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON"); 03521 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) { 03522 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */ 03523 } 03524 03525 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT"); 03526 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC"); 03527 if (call_ref_id && call_ref_pc) { 03528 isup_set_callref(p->ss7call, atoi(call_ref_id), 03529 call_ref_pc ? atoi(call_ref_pc) : 0); 03530 } 03531 03532 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR"); 03533 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 )) 03534 (isup_far(p->ss7->ss7, p->ss7call)); 03535 03536 ast_channel_unlock(ast); 03537 03538 isup_iam(p->ss7->ss7, p->ss7call); 03539 ast_setstate(ast, AST_STATE_DIALING); 03540 ss7_rel(p->ss7); 03541 } 03542 #endif /* HAVE_SS7 */ 03543 #ifdef HAVE_OPENR2 03544 if (p->mfcr2) { 03545 openr2_calling_party_category_t chancat; 03546 int callres = 0; 03547 char *c, *l; 03548 03549 c = strchr(dest, '/'); 03550 if (c) { 03551 c++; 03552 } else { 03553 c = ""; 03554 } 03555 if (!p->hidecallerid) { 03556 l = ast->cid.cid_num; 03557 } else { 03558 l = NULL; 03559 } 03560 if (strlen(c) < p->stripmsd) { 03561 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03562 ast_mutex_unlock(&p->lock); 03563 return -1; 03564 } 03565 p->dialing = 1; 03566 ast_channel_lock(ast); 03567 chancat = dahdi_r2_get_channel_category(ast); 03568 ast_channel_unlock(ast); 03569 callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat); 03570 if (-1 == callres) { 03571 ast_mutex_unlock(&p->lock); 03572 ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n"); 03573 return -1; 03574 } 03575 ast_setstate(ast, AST_STATE_DIALING); 03576 } 03577 #endif /* HAVE_OPENR2 */ 03578 #ifdef HAVE_PRI 03579 if (p->pri) { 03580 struct pri_sr *sr; 03581 #ifdef SUPPORT_USERUSER 03582 const char *useruser; 03583 #endif 03584 int pridialplan; 03585 int dp_strip; 03586 int prilocaldialplan; 03587 int ldp_strip; 03588 int exclusive; 03589 const char *rr_str; 03590 int redirect_reason; 03591 03592 c = strchr(dest, '/'); 03593 if (c) { 03594 c++; 03595 } else { 03596 c = ""; 03597 } 03598 03599 l = NULL; 03600 n = NULL; 03601 if (!p->hidecallerid) { 03602 l = ast->cid.cid_num; 03603 if (!p->hidecalleridname) { 03604 n = ast->cid.cid_name; 03605 } 03606 } 03607 03608 if (strlen(c) < p->stripmsd) { 03609 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 03610 ast_mutex_unlock(&p->lock); 03611 return -1; 03612 } 03613 if (mysig != SIG_FXSKS) { 03614 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03615 s = strchr(c + p->stripmsd, 'w'); 03616 if (s) { 03617 if (strlen(s) > 1) 03618 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 03619 else 03620 p->dop.dialstr[0] = '\0'; 03621 *s = '\0'; 03622 } else { 03623 p->dop.dialstr[0] = '\0'; 03624 } 03625 } 03626 if (pri_grab(p, p->pri)) { 03627 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03628 ast_mutex_unlock(&p->lock); 03629 return -1; 03630 } 03631 if (!(p->call = pri_new_call(p->pri->pri))) { 03632 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 03633 pri_rel(p->pri); 03634 ast_mutex_unlock(&p->lock); 03635 return -1; 03636 } 03637 if (!(sr = pri_sr_new())) { 03638 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 03639 pri_rel(p->pri); 03640 ast_mutex_unlock(&p->lock); 03641 } 03642 if (p->bearer || (mysig == SIG_FXSKS)) { 03643 if (p->bearer) { 03644 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 03645 p->bearer->call = p->call; 03646 } else 03647 ast_debug(1, "I'm being setup with no bearer right now...\n"); 03648 03649 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 03650 } 03651 p->digital = IS_DIGITAL(ast->transfercapability); 03652 03653 /* Should the picked channel be used exclusively? */ 03654 if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) { 03655 exclusive = 1; 03656 } else { 03657 exclusive = 0; 03658 } 03659 03660 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 03661 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 03662 (p->digital ? -1 : 03663 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 03664 if (p->pri->facilityenable) 03665 pri_facility_enable(p->pri->pri); 03666 03667 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 03668 03669 dp_strip = 0; 03670 pridialplan = p->pri->dialplan - 1; 03671 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */ 03672 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03673 if (pridialplan == -2) { 03674 dp_strip = strlen(p->pri->internationalprefix); 03675 } 03676 pridialplan = PRI_INTERNATIONAL_ISDN; 03677 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03678 if (pridialplan == -2) { 03679 dp_strip = strlen(p->pri->nationalprefix); 03680 } 03681 pridialplan = PRI_NATIONAL_ISDN; 03682 } else { 03683 pridialplan = PRI_LOCAL_ISDN; 03684 } 03685 } 03686 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') { 03687 switch (c[p->stripmsd]) { 03688 case 'U': 03689 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf); 03690 break; 03691 case 'I': 03692 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf); 03693 break; 03694 case 'N': 03695 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf); 03696 break; 03697 case 'L': 03698 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf); 03699 break; 03700 case 'S': 03701 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf); 03702 break; 03703 case 'V': 03704 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf); 03705 break; 03706 case 'R': 03707 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf); 03708 break; 03709 case 'u': 03710 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0); 03711 break; 03712 case 'e': 03713 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0); 03714 break; 03715 case 'x': 03716 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0); 03717 break; 03718 case 'f': 03719 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0); 03720 break; 03721 case 'n': 03722 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0); 03723 break; 03724 case 'p': 03725 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0); 03726 break; 03727 case 'r': 03728 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0); 03729 break; 03730 default: 03731 if (isalpha(c[p->stripmsd])) { 03732 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", 03733 c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]); 03734 } 03735 break; 03736 } 03737 c++; 03738 } 03739 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 03740 03741 ldp_strip = 0; 03742 prilocaldialplan = p->pri->localdialplan - 1; 03743 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */ 03744 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 03745 if (prilocaldialplan == -2) { 03746 ldp_strip = strlen(p->pri->internationalprefix); 03747 } 03748 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 03749 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 03750 if (prilocaldialplan == -2) { 03751 ldp_strip = strlen(p->pri->nationalprefix); 03752 } 03753 prilocaldialplan = PRI_NATIONAL_ISDN; 03754 } else { 03755 prilocaldialplan = PRI_LOCAL_ISDN; 03756 } 03757 } 03758 if (l != NULL) { 03759 while (*l > '9' && *l != '*' && *l != '#') { 03760 switch (*l) { 03761 case 'U': 03762 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf); 03763 break; 03764 case 'I': 03765 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf); 03766 break; 03767 case 'N': 03768 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf); 03769 break; 03770 case 'L': 03771 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf); 03772 break; 03773 case 'S': 03774 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf); 03775 break; 03776 case 'V': 03777 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf); 03778 break; 03779 case 'R': 03780 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf); 03781 break; 03782 case 'u': 03783 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0); 03784 break; 03785 case 'e': 03786 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0); 03787 break; 03788 case 'x': 03789 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0); 03790 break; 03791 case 'f': 03792 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0); 03793 break; 03794 case 'n': 03795 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0); 03796 break; 03797 case 'p': 03798 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0); 03799 break; 03800 case 'r': 03801 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0); 03802 break; 03803 default: 03804 if (isalpha(*l)) { 03805 ast_log(LOG_WARNING, 03806 "Unrecognized prilocaldialplan %s modifier: %c\n", 03807 *l > 'Z' ? "NPI" : "TON", *l); 03808 } 03809 break; 03810 } 03811 l++; 03812 } 03813 } 03814 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 03815 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 03816 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 03817 if (!strcasecmp(rr_str, "UNKNOWN")) 03818 redirect_reason = 0; 03819 else if (!strcasecmp(rr_str, "BUSY")) 03820 redirect_reason = 1; 03821 else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER")) 03822 /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */ 03823 redirect_reason = 2; 03824 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 03825 redirect_reason = 15; 03826 else 03827 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03828 } else 03829 redirect_reason = PRI_REDIR_UNCONDITIONAL; 03830 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 03831 03832 #ifdef SUPPORT_USERUSER 03833 /* User-user info */ 03834 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 03835 if (useruser) 03836 pri_sr_set_useruser(sr, useruser); 03837 #endif 03838 03839 if (pri_setup(p->pri->pri, p->call, sr)) { 03840 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 03841 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 03842 pri_rel(p->pri); 03843 ast_mutex_unlock(&p->lock); 03844 pri_sr_free(sr); 03845 return -1; 03846 } 03847 pri_sr_free(sr); 03848 ast_setstate(ast, AST_STATE_DIALING); 03849 pri_rel(p->pri); 03850 } 03851 #endif 03852 ast_mutex_unlock(&p->lock); 03853 return 0; 03854 }
| static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3059 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().
03060 { 03061 struct dahdi_pvt *p = ast->tech_pvt; 03062 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 03063 if (p->cidspill) { 03064 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 03065 ast_free(p->cidspill); 03066 } 03067 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 03068 return -1; 03069 save_conference(p); 03070 /* Silence */ 03071 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 03072 if (!p->callwaitrings && p->callwaitingcallerid) { 03073 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 03074 p->callwaitcas = 1; 03075 p->cidlen = 2400 + 680 + READ_SIZE * 4; 03076 } else { 03077 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 03078 p->callwaitcas = 0; 03079 p->cidlen = 2400 + READ_SIZE * 4; 03080 } 03081 p->cidpos = 0; 03082 send_callerid(p); 03083 03084 return 0; 03085 }
| static struct dahdi_chan_conf dahdi_chan_conf_default | ( | void | ) | [static, read] |
returns a new dahdi_chan_conf with default values (by-value)
Definition at line 1266 of file chan_dahdi.c.
References CID_SIG_BELL, CID_START_RING, DAHDI_CHAN_MAPPING_PHYSICAL, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.
Referenced by process_dahdi(), and setup_dahdi().
01267 { 01268 /* recall that if a field is not included here it is initialized 01269 * to 0 or equivalent 01270 */ 01271 struct dahdi_chan_conf conf = { 01272 #ifdef HAVE_PRI 01273 .pri = { 01274 .nsf = PRI_NSF_NONE, 01275 .switchtype = PRI_SWITCH_NI2, 01276 .dialplan = PRI_UNKNOWN + 1, 01277 .localdialplan = PRI_NATIONAL_ISDN + 1, 01278 .nodetype = PRI_CPE, 01279 .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL, 01280 01281 .minunused = 2, 01282 .idleext = "", 01283 .idledial = "", 01284 .internationalprefix = "", 01285 .nationalprefix = "", 01286 .localprefix = "", 01287 .privateprefix = "", 01288 .unknownprefix = "", 01289 .resetinterval = -1, 01290 }, 01291 #endif 01292 #ifdef HAVE_SS7 01293 .ss7 = { 01294 .called_nai = SS7_NAI_NATIONAL, 01295 .calling_nai = SS7_NAI_NATIONAL, 01296 .internationalprefix = "", 01297 .nationalprefix = "", 01298 .subscriberprefix = "", 01299 .unknownprefix = "" 01300 }, 01301 #endif 01302 #ifdef HAVE_OPENR2 01303 .mfcr2 = { 01304 .variant = OR2_VAR_ITU, 01305 .mfback_timeout = -1, 01306 .metering_pulse_timeout = -1, 01307 .max_ani = 10, 01308 .max_dnis = 4, 01309 .get_ani_first = -1, 01310 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 01311 .skip_category_request = -1, 01312 #endif 01313 .call_files = 0, 01314 .allow_collect_calls = 0, 01315 .charge_calls = 1, 01316 .accept_on_offer = 1, 01317 .forced_release = 0, 01318 .double_answer = 0, 01319 .immediate_accept = -1, 01320 .logdir = "", 01321 .r2proto_file = "", 01322 .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING, 01323 .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER 01324 }, 01325 #endif 01326 .chan = { 01327 .context = "default", 01328 .cid_num = "", 01329 .cid_name = "", 01330 .mohinterpret = "default", 01331 .mohsuggest = "", 01332 .parkinglot = "", 01333 .transfertobusy = 1, 01334 01335 .cid_signalling = CID_SIG_BELL, 01336 .cid_start = CID_START_RING, 01337 .dahditrcallerid = 0, 01338 .use_callerid = 1, 01339 .sig = -1, 01340 .outsigmod = -1, 01341 01342 .cid_rxgain = +5.0, 01343 01344 .tonezone = -1, 01345 01346 .echocancel.head.tap_length = 1, 01347 01348 .busycount = 3, 01349 01350 .accountcode = "", 01351 01352 .mailbox = "", 01353 01354 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 01355 .mwisend_fsk = 1, 01356 #endif 01357 .polarityonanswerdelay = 600, 01358 01359 .sendcalleridafter = DEFAULT_CIDRINGS, 01360 01361 .buf_policy = DAHDI_POLICY_IMMEDIATE, 01362 .buf_no = numbufs, 01363 .usefaxbuffers = 0, 01364 .faxbuf_policy = DAHDI_POLICY_IMMEDIATE, 01365 .faxbuf_no = numbufs, 01366 }, 01367 .timing = { 01368 .prewinktime = -1, 01369 .preflashtime = -1, 01370 .winktime = -1, 01371 .flashtime = -1, 01372 .starttime = -1, 01373 .rxwinktime = -1, 01374 .rxflashtime = -1, 01375 .debouncetime = -1 01376 }, 01377 .is_sig_auto = 1, 01378 .smdi_port = "/dev/ttyS0", 01379 }; 01380 01381 return conf; 01382 }
| static void dahdi_close | ( | int | fd | ) | [static] |
Definition at line 2137 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 2150 of file chan_dahdi.c.
References dahdi_close(), and dahdi_pri::fds.
Referenced by __unload_module(), dahdi_restart(), and start_pri().
02151 { 02152 dahdi_close(pri->fds[fd_num]); 02153 pri->fds[fd_num] = -1; 02154 }
| static void dahdi_close_ss7_fd | ( | struct dahdi_ss7 * | ss7, | |
| int | fd_num | |||
| ) | [static] |
Definition at line 2158 of file chan_dahdi.c.
References dahdi_close(), and dahdi_ss7::fds.
Referenced by __unload_module(), dahdi_restart(), and linkset_addsigchan().
02159 { 02160 dahdi_close(ss7->fds[fd_num]); 02161 ss7->fds[fd_num] = -1; 02162 }
| static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
| int | sub_num | |||
| ) | [static] |
Definition at line 2143 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().
02144 { 02145 dahdi_close(chan_pvt->subs[sub_num].dfd); 02146 chan_pvt->subs[sub_num].dfd = -1; 02147 }
| static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
| int | muted | |||
| ) | [inline, static] |
Definition at line 2880 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().
02881 { 02882 int x, y, res; 02883 x = muted; 02884 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 02885 y = 1; 02886 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 02887 if (res) 02888 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 02889 } 02890 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 02891 if (res < 0) 02892 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 02893 return res; 02894 }
| static char* dahdi_destroy_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14287 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.
14288 { 14289 int channel; 14290 int ret; 14291 switch (cmd) { 14292 case CLI_INIT: 14293 e->command = "dahdi destroy channel"; 14294 e->usage = 14295 "Usage: dahdi destroy channel <chan num>\n" 14296 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"; 14297 return NULL; 14298 case CLI_GENERATE: 14299 return NULL; 14300 } 14301 if (a->argc != 4) 14302 return CLI_SHOWUSAGE; 14303 14304 channel = atoi(a->argv[3]); 14305 ret = dahdi_destroy_channel_bynum(channel); 14306 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE; 14307 }
| static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 9249 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().
09250 { 09251 struct dahdi_pvt *tmp = NULL; 09252 struct dahdi_pvt *prev = NULL; 09253 09254 tmp = iflist; 09255 while (tmp) { 09256 if (tmp->channel == channel) { 09257 int x = DAHDI_FLASH; 09258 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 */ 09259 destroy_channel(prev, tmp, 1); 09260 ast_module_unref(ast_module_info->self); 09261 return RESULT_SUCCESS; 09262 } 09263 prev = tmp; 09264 tmp = tmp->next; 09265 } 09266 return RESULT_FAILURE; 09267 }
| static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
| char | digit | |||
| ) | [static] |
Definition at line 2245 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.
02246 { 02247 struct dahdi_pvt *pvt; 02248 int idx; 02249 int dtmf = -1; 02250 02251 pvt = chan->tech_pvt; 02252 02253 ast_mutex_lock(&pvt->lock); 02254 02255 idx = dahdi_get_index(chan, pvt, 0); 02256 02257 if ((idx != SUB_REAL) || !pvt->owner) 02258 goto out; 02259 02260 #ifdef HAVE_PRI 02261 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 02262 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 02263 if (pvt->setup_ack) { 02264 if (!pri_grab(pvt, pvt->pri)) { 02265 pri_information(pvt->pri->pri, pvt->call, digit); 02266 pri_rel(pvt->pri); 02267 } else 02268 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 02269 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 02270 int res; 02271 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit); 02272 res = strlen(pvt->dialdest); 02273 pvt->dialdest[res++] = digit; 02274 pvt->dialdest[res] = '\0'; 02275 } 02276 goto out; 02277 } 02278 #endif 02279 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 02280 goto out; 02281 02282 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 02283 int res; 02284 struct dahdi_dialoperation zo = { 02285 .op = DAHDI_DIAL_OP_APPEND, 02286 }; 02287 02288 zo.dialstr[0] = 'T'; 02289 zo.dialstr[1] = digit; 02290 zo.dialstr[2] = '\0'; 02291 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 02292 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 02293 else 02294 pvt->dialing = 1; 02295 } else { 02296 ast_debug(1, "Started VLDTMF digit '%c'\n", digit); 02297 pvt->dialing = 1; 02298 pvt->begindigit = digit; 02299 } 02300 02301 out: 02302 ast_mutex_unlock(&pvt->lock); 02303 02304 return 0; 02305 }
| static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 2307 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.
02308 { 02309 struct dahdi_pvt *pvt; 02310 int res = 0; 02311 int idx; 02312 int x; 02313 02314 pvt = chan->tech_pvt; 02315 02316 ast_mutex_lock(&pvt->lock); 02317 02318 idx = dahdi_get_index(chan, pvt, 0); 02319 02320 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse) 02321 goto out; 02322 02323 #ifdef HAVE_PRI 02324 /* This means that the digit was already sent via PRI signalling */ 02325 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 02326 && !pvt->begindigit) 02327 goto out; 02328 #endif 02329 02330 if (pvt->begindigit) { 02331 x = -1; 02332 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit); 02333 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 02334 pvt->dialing = 0; 02335 pvt->begindigit = 0; 02336 } 02337 02338 out: 02339 ast_mutex_unlock(&pvt->lock); 02340 02341 return res; 02342 }
| static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2709 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().
02710 { 02711 int res; 02712 02713 if (p->echocanon) { 02714 struct dahdi_echocanparams ecp = { .tap_length = 0 }; 02715 02716 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp); 02717 02718 if (res) 02719 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 02720 else 02721 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel); 02722 } 02723 02724 p->echocanon = 0; 02725 }
| 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 7662 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().
07663 { 07664 /* Do not disturb */ 07665 dahdichan->dnd = on; 07666 ast_verb(3, "%s DND on channel %d\n", 07667 on? "Enabled" : "Disabled", 07668 dahdichan->channel); 07669 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 07670 "Channel: DAHDI/%d\r\n" 07671 "Status: %s\r\n", dahdichan->channel, 07672 on? "enabled" : "disabled"); 07673 }
| static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2660 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().
02661 { 02662 int x; 02663 int res; 02664 if (!p) 02665 return; 02666 if (p->echocanon) { 02667 ast_debug(1, "Echo cancellation already on\n"); 02668 return; 02669 } 02670 if (p->digital) { 02671 ast_debug(1, "Echo cancellation isn't required on digital connection\n"); 02672 return; 02673 } 02674 if (p->echocancel.head.tap_length) { 02675 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) { 02676 x = 1; 02677 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 02678 if (res) 02679 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 02680 } 02681 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel); 02682 if (res) { 02683 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 02684 } else { 02685 p->echocanon = 1; 02686 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel); 02687 } 02688 } else 02689 ast_debug(1, "No echo cancellation requested\n"); 02690 }
| static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 6707 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, and ast_channel::tech_pvt.
06708 { 06709 struct dahdi_pvt *p = ast->tech_pvt; 06710 struct ast_frame *f; 06711 ast_mutex_lock(&p->lock); 06712 f = __dahdi_exception(ast); 06713 ast_mutex_unlock(&p->lock); 06714 return f; 06715 }
| static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
| int | mode | |||
| ) | [static] |
Definition at line 15185 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::fake_event, HANGUP, LOG_WARNING, ast_channel::name, dahdi_pvt::owner, and TRANSFER.
Referenced by action_transfer(), and action_transferhangup().
15186 { 15187 if (p) { 15188 switch (mode) { 15189 case TRANSFER: 15190 p->fake_event = DAHDI_EVENT_WINKFLASH; 15191 break; 15192 case HANGUP: 15193 p->fake_event = DAHDI_EVENT_ONHOOK; 15194 break; 15195 default: 15196 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 15197 } 15198 } 15199 return 0; 15200 }
| static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 5448 of file chan_dahdi.c.
References ast_channel::_state, AST_CONTROL_RINGING, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, dahdi_pvt::channel, dahdi_indicate(), dahdi_unlink(), dahdi_pvt::lock, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().
05449 { 05450 struct dahdi_pvt *p = newchan->tech_pvt; 05451 int x; 05452 ast_mutex_lock(&p->lock); 05453 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name); 05454 if (p->owner == oldchan) { 05455 p->owner = newchan; 05456 } 05457 for (x = 0; x < 3; x++) 05458 if (p->subs[x].owner == oldchan) { 05459 if (!x) 05460 dahdi_unlink(NULL, p, 0); 05461 p->subs[x].owner = newchan; 05462 } 05463 if (newchan->_state == AST_STATE_RINGING) 05464 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 05465 update_conf(p); 05466 ast_mutex_unlock(&p->lock); 05467 return 0; 05468 }
| static int dahdi_func_read | ( | struct ast_channel * | chan, | |
| const char * | function, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 5025 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.
05026 { 05027 struct dahdi_pvt *p = chan->tech_pvt; 05028 05029 if (!strcasecmp(data, "rxgain")) { 05030 ast_mutex_lock(&p->lock); 05031 snprintf(buf, len, "%f", p->rxgain); 05032 ast_mutex_unlock(&p->lock); 05033 } else if (!strcasecmp(data, "txgain")) { 05034 ast_mutex_lock(&p->lock); 05035 snprintf(buf, len, "%f", p->txgain); 05036 ast_mutex_unlock(&p->lock); 05037 } else { 05038 ast_copy_string(buf, "", len); 05039 } 05040 return 0; 05041 }
| static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 376 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), do_monitor(), mwi_thread(), and ss_thread().
| static int dahdi_get_index | ( | struct ast_channel * | ast, | |
| struct dahdi_pvt * | p, | |||
| int | nullok | |||
| ) | [static] |
Definition at line 1503 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().
01504 { 01505 int res; 01506 if (p->subs[SUB_REAL].owner == ast) 01507 res = 0; 01508 else if (p->subs[SUB_CALLWAIT].owner == ast) 01509 res = 1; 01510 else if (p->subs[SUB_THREEWAY].owner == ast) 01511 res = 2; 01512 else { 01513 res = -1; 01514 if (!nullok) 01515 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 01516 } 01517 return res; 01518 }
| static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
| int | idx, | |||
| struct ast_frame ** | dest | |||
| ) | [static] |
Definition at line 5607 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::bufsize, dahdi_pvt::callprogress, CALLPROGRESS_FAX, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), dahdi_subchannel::dfd, errno, ast_channel::exten, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxbuffersinuse, dahdi_pvt::faxhandled, ast_frame::frametype, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::usefaxbuffers.
Referenced by dahdi_handle_event(), and dahdi_read().
05608 { 05609 struct dahdi_pvt *p = ast->tech_pvt; 05610 struct ast_frame *f = *dest; 05611 05612 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name); 05613 05614 if (p->confirmanswer) { 05615 ast_debug(1, "Confirm answer on %s!\n", ast->name); 05616 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 05617 of a DTMF digit */ 05618 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05619 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05620 *dest = &p->subs[idx].f; 05621 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 05622 p->confirmanswer = 0; 05623 } else if (p->callwaitcas) { 05624 if ((f->subclass == 'A') || (f->subclass == 'D')) { 05625 ast_debug(1, "Got some DTMF, but it's for the CAS\n"); 05626 if (p->cidspill) 05627 ast_free(p->cidspill); 05628 send_cwcidspill(p); 05629 } 05630 p->callwaitcas = 0; 05631 p->subs[idx].f.frametype = AST_FRAME_NULL; 05632 p->subs[idx].f.subclass = 0; 05633 *dest = &p->subs[idx].f; 05634 } else if (f->subclass == 'f') { 05635 /* Fax tone -- Handle and return NULL */ 05636 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) { 05637 /* If faxbuffers are configured, use them for the fax transmission */ 05638 if (p->usefaxbuffers && !p->faxbuffersinuse) { 05639 struct dahdi_bufferinfo bi = { 05640 .txbufpolicy = p->faxbuf_policy, 05641 .bufsize = p->bufsize, 05642 .numbufs = p->faxbuf_no 05643 }; 05644 int res; 05645 05646 if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 05647 ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno)); 05648 } else { 05649 p->faxbuffersinuse = 1; 05650 } 05651 } 05652 p->faxhandled = 1; 05653 if (strcmp(ast->exten, "fax")) { 05654 const char *target_context = S_OR(ast->macrocontext, ast->context); 05655 05656 /* We need to unlock 'ast' here because ast_exists_extension has the 05657 * potential to start autoservice on the channel. Such action is prone 05658 * to deadlock. 05659 */ 05660 ast_mutex_unlock(&p->lock); 05661 ast_channel_unlock(ast); 05662 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 05663 ast_channel_lock(ast); 05664 ast_mutex_lock(&p->lock); 05665 ast_verb(3, "Redirecting %s to fax extension\n", ast->name); 05666 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 05667 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 05668 if (ast_async_goto(ast, target_context, "fax", 1)) 05669 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 05670 } else { 05671 ast_channel_lock(ast); 05672 ast_mutex_lock(&p->lock); 05673 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 05674 } 05675 } else { 05676 ast_debug(1, "Already in a fax extension, not redirecting\n"); 05677 } 05678 } else { 05679 ast_debug(1, "Fax already handled\n"); 05680 } 05681 dahdi_confmute(p, 0); 05682 p->subs[idx].f.frametype = AST_FRAME_NULL; 05683 p->subs[idx].f.subclass = 0; 05684 *dest = &p->subs[idx].f; 05685 } 05686 }
| 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 5699 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, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, dahdi_pvt::fxsoffhookstate, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_event, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, 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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), update_conf(), dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
05700 { 05701 int res, x; 05702 int idx, mysig; 05703 char *c; 05704 struct dahdi_pvt *p = ast->tech_pvt; 05705 pthread_t threadid; 05706 struct ast_channel *chan; 05707 struct ast_frame *f; 05708 05709 idx = dahdi_get_index(ast, p, 0); 05710 mysig = p->sig; 05711 if (p->outsigmod > -1) 05712 mysig = p->outsigmod; 05713 p->subs[idx].f.frametype = AST_FRAME_NULL; 05714 p->subs[idx].f.subclass = 0; 05715 p->subs[idx].f.datalen = 0; 05716 p->subs[idx].f.samples = 0; 05717 p->subs[idx].f.mallocd = 0; 05718 p->subs[idx].f.offset = 0; 05719 p->subs[idx].f.src = "dahdi_handle_event"; 05720 p->subs[idx].f.data.ptr = NULL; 05721 f = &p->subs[idx].f; 05722 05723 if (idx < 0) 05724 return &p->subs[idx].f; 05725 if (p->fake_event) { 05726 res = p->fake_event; 05727 p->fake_event = 0; 05728 } else 05729 res = dahdi_get_event(p->subs[idx].dfd); 05730 05731 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx); 05732 05733 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 05734 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 05735 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 05736 #ifdef HAVE_PRI 05737 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 05738 /* absorb event */ 05739 } else { 05740 #endif 05741 dahdi_confmute(p, 0); 05742 p->subs[idx].f.frametype = AST_FRAME_DTMF_END; 05743 p->subs[idx].f.subclass = res & 0xff; 05744 #ifdef HAVE_PRI 05745 } 05746 #endif 05747 dahdi_handle_dtmfup(ast, idx, &f); 05748 return f; 05749 } 05750 05751 if (res & DAHDI_EVENT_DTMFDOWN) { 05752 ast_debug(1, "DTMF Down '%c'\n", res & 0xff); 05753 /* Mute conference */ 05754 dahdi_confmute(p, 1); 05755 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN; 05756 p->subs[idx].f.subclass = res & 0xff; 05757 return &p->subs[idx].f; 05758 } 05759 05760 switch (res) { 05761 case DAHDI_EVENT_EC_DISABLED: 05762 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel); 05763 p->echocanon = 0; 05764 break; 05765 case DAHDI_EVENT_BITSCHANGED: 05766 #ifdef HAVE_OPENR2 05767 if (p->sig != SIG_MFCR2) { 05768 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 05769 } else { 05770 ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel); 05771 openr2_chan_handle_cas(p->r2chan); 05772 } 05773 #else 05774 ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig)); 05775 #endif 05776 case DAHDI_EVENT_PULSE_START: 05777 /* Stop tone if there's a pulse start and the PBX isn't started */ 05778 if (!ast->pbx) 05779 tone_zone_play_tone(p->subs[idx].dfd, -1); 05780 break; 05781 case DAHDI_EVENT_DIALCOMPLETE: 05782 #ifdef HAVE_OPENR2 05783 if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) { 05784 /* we don't need to do anything for this event for R2 signaling 05785 if the call is being setup */ 05786 break; 05787 } 05788 #endif 05789 if (p->inalarm) break; 05790 if ((p->radio || (p->oprmode < 0))) break; 05791 if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) { 05792 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 05793 return NULL; 05794 } 05795 if (!x) { /* if not still dialing in driver */ 05796 dahdi_enable_ec(p); 05797 if (p->echobreak) { 05798 dahdi_train_ec(p); 05799 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 05800 p->dop.op = DAHDI_DIAL_OP_REPLACE; 05801 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 05802 p->echobreak = 0; 05803 } else { 05804 p->dialing = 0; 05805 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 05806 /* if thru with dialing after offhook */ 05807 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 05808 ast_setstate(ast, AST_STATE_UP); 05809 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05810 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05811 break; 05812 } else { /* if to state wait for offhook to dial rest */ 05813 /* we now wait for off hook */ 05814 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 05815 } 05816 } 05817 if (ast->_state == AST_STATE_DIALING) { 05818 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 05819 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n"); 05820 } else if (p->confirmanswer || (!p->dialednone 05821 && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) 05822 || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) 05823 || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) 05824 || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) 05825 || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) 05826 || (mysig == SIG_SF) || (mysig == SIG_SFWINK) 05827 || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) 05828 || (mysig == SIG_SF_FEATB)))) { 05829 ast_setstate(ast, AST_STATE_RINGING); 05830 } else if (!p->answeronpolarityswitch) { 05831 ast_setstate(ast, AST_STATE_UP); 05832 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05833 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 05834 /* If aops=0 and hops=1, this is necessary */ 05835 p->polarity = POLARITY_REV; 05836 } else { 05837 /* Start clean, so we can catch the change to REV polarity when party answers */ 05838 p->polarity = POLARITY_IDLE; 05839 } 05840 } 05841 } 05842 } 05843 break; 05844 case DAHDI_EVENT_ALARM: 05845 #ifdef HAVE_PRI 05846 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 05847 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 05848 /* T309 is not enabled : hangup calls when alarm occurs */ 05849 if (p->call) { 05850 if (p->pri && p->pri->pri) { 05851 if (!pri_grab(p, p->pri)) { 05852 pri_hangup(p->pri->pri, p->call, -1); 05853 pri_destroycall(p->pri->pri, p->call); 05854 p->call = NULL; 05855 pri_rel(p->pri); 05856 } else 05857 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 05858 } else 05859 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 05860 } 05861 if (p->owner) 05862 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 05863 } 05864 } 05865 if (p->bearer) 05866 p->bearer->inalarm = 1; 05867 else 05868 #endif 05869 p->inalarm = 1; 05870 res = get_alarms(p); 05871 handle_alarms(p, res); 05872 #ifdef HAVE_PRI 05873 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 05874 /* fall through intentionally */ 05875 } else { 05876 break; 05877 } 05878 #endif 05879 #ifdef HAVE_SS7 05880 if (p->sig == SIG_SS7) 05881 break; 05882 #endif 05883 #ifdef HAVE_OPENR2 05884 if (p->sig == SIG_MFCR2) 05885 break; 05886 #endif 05887 case DAHDI_EVENT_ONHOOK: 05888 if (p->radio) { 05889 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 05890 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 05891 break; 05892 } 05893 if (p->oprmode < 0) 05894 { 05895 if (p->oprmode != -1) break; 05896 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 05897 { 05898 /* Make sure it starts ringing */ 05899 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 05900 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 05901 save_conference(p->oprpeer); 05902 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 05903 } 05904 break; 05905 } 05906 switch (p->sig) { 05907 case SIG_FXOLS: 05908 case SIG_FXOGS: 05909 case SIG_FXOKS: 05910 p->onhooktime = time(NULL); 05911 p->fxsoffhookstate = 0; 05912 p->msgstate = -1; 05913 /* Check for some special conditions regarding call waiting */ 05914 if (idx == SUB_REAL) { 05915 /* The normal line was hung up */ 05916 if (p->subs[SUB_CALLWAIT].owner) { 05917 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 05918 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 05919 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); 05920 unalloc_sub(p, SUB_CALLWAIT); 05921 #if 0 05922 p->subs[idx].needanswer = 0; 05923 p->subs[idx].needringing = 0; 05924 #endif 05925 p->callwaitingrepeat = 0; 05926 p->cidcwexpire = 0; 05927 p->owner = NULL; 05928 /* Don't start streaming audio yet if the incoming call isn't up yet */ 05929 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 05930 p->dialing = 1; 05931 dahdi_ring_phone(p); 05932 } else if (p->subs[SUB_THREEWAY].owner) { 05933 unsigned int mssinceflash; 05934 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 05935 the private structure -- not especially easy or clean */ 05936 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) { 05937 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 05938 DLA_UNLOCK(&p->lock); 05939 CHANNEL_DEADLOCK_AVOIDANCE(ast); 05940 /* We can grab ast and p in that order, without worry. We should make sure 05941 nothing seriously bad has happened though like some sort of bizarre double 05942 masquerade! */ 05943 DLA_LOCK(&p->lock); 05944 if (p->owner != ast) { 05945 ast_log(LOG_WARNING, "This isn't good...\n"); 05946 return NULL; 05947 } 05948 } 05949 if (!p->subs[SUB_THREEWAY].owner) { 05950 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 05951 return NULL; 05952 } 05953 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 05954 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash); 05955 if (mssinceflash < MIN_MS_SINCE_FLASH) { 05956 /* It hasn't been long enough since the last flashook. This is probably a bounce on 05957 hanging up. Hangup both channels now */ 05958 if (p->subs[SUB_THREEWAY].owner) 05959 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); 05960 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05961 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 05962 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 05963 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 05964 if (p->transfer) { 05965 /* In any case this isn't a threeway call anymore */ 05966 p->subs[SUB_REAL].inthreeway = 0; 05967 p->subs[SUB_THREEWAY].inthreeway = 0; 05968 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 05969 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 05970 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 05971 /* Swap subs and dis-own channel */ 05972 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05973 p->owner = NULL; 05974 /* Ring the phone */ 05975 dahdi_ring_phone(p); 05976 } else { 05977 if ((res = attempt_transfer(p)) < 0) { 05978 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05979 if (p->subs[SUB_THREEWAY].owner) 05980 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 05981 } else if (res) { 05982 /* Don't actually hang up at this point */ 05983 if (p->subs[SUB_THREEWAY].owner) 05984 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 05985 break; 05986 } 05987 } 05988 } else { 05989 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 05990 if (p->subs[SUB_THREEWAY].owner) 05991 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 05992 } 05993 } else { 05994 ast_channel_unlock(p->subs[SUB_THREEWAY].owner); 05995 /* Swap subs and dis-own channel */ 05996 swap_subs(p, SUB_THREEWAY, SUB_REAL); 05997 p->owner = NULL; 05998 /* Ring the phone */ 05999 dahdi_ring_phone(p); 06000 } 06001 } 06002 } else { 06003 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx); 06004 } 06005 /* Fall through */ 06006 default: 06007 dahdi_disable_ec(p); 06008 return NULL; 06009 } 06010 break; 06011 case DAHDI_EVENT_RINGOFFHOOK: 06012 if (p->inalarm) break; 06013 if (p->oprmode < 0) 06014 { 06015 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 06016 { 06017 /* Make sure it stops ringing */ 06018 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 06019 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 06020 restore_conference(p->oprpeer); 06021 } 06022 break; 06023 } 06024 if (p->radio) 06025 { 06026 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06027 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 06028 break; 06029 } 06030 /* for E911, its supposed to wait for offhook then dial 06031 the second half of the dial string */ 06032 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 06033 c = strchr(p->dialdest, '/'); 06034 if (c) 06035 c++; 06036 else 06037 c = p->dialdest; 06038 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 06039 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 06040 if (strlen(p->dop.dialstr) > 4) { 06041 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 06042 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 06043 p->echorest[sizeof(p->echorest) - 1] = '\0'; 06044 p->echobreak = 1; 06045 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 06046 } else 06047 p->echobreak = 0; 06048 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 06049 int saveerr = errno; 06050 06051 x = DAHDI_ONHOOK; 06052 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 06053 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 06054 return NULL; 06055 } 06056 p->dialing = 1; 06057 return &p->subs[idx].f; 06058 } 06059 switch (p->sig) { 06060 case SIG_FXOLS: 06061 case SIG_FXOGS: 06062 case SIG_FXOKS: 06063 p->fxsoffhookstate = 1; 06064 switch (ast->_state) { 06065 case AST_STATE_RINGING: 06066 dahdi_enable_ec(p); 06067 dahdi_train_ec(p); 06068 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06069 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 06070 /* Make sure it stops ringing */ 06071 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 06072 ast_debug(1, "channel %d answered\n", p->channel); 06073 if (p->cidspill) { 06074 /* Cancel any running CallerID spill */ 06075 ast_free(p->cidspill); 06076 p->cidspill = NULL; 06077 } 06078 p->dialing = 0; 06079 p->callwaitcas = 0; 06080 if (p->confirmanswer) { 06081 /* Ignore answer if "confirm answer" is enabled */ 06082 p->subs[idx].f.frametype = AST_FRAME_NULL; 06083 p->subs[idx].f.subclass = 0; 06084 } else if (!ast_strlen_zero(p->dop.dialstr)) { 06085 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 06086 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 06087 if (res < 0) { 06088 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 06089 p->dop.dialstr[0] = '\0'; 06090 return NULL; 06091 } else { 06092 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 06093 p->subs[idx].f.frametype = AST_FRAME_NULL; 06094 p->subs[idx].f.subclass = 0; 06095 p->dialing = 1; 06096 } 06097 p->dop.dialstr[0] = '\0'; 06098 ast_setstate(ast, AST_STATE_DIALING); 06099 } else 06100 ast_setstate(ast, AST_STATE_UP); 06101 return &p->subs[idx].f; 06102 case AST_STATE_DOWN: 06103 ast_setstate(ast, AST_STATE_RING); 06104 ast->rings = 1; 06105 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06106 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK; 06107 ast_debug(1, "channel %d picked up\n", p->channel); 06108 return &p->subs[idx].f; 06109 case AST_STATE_UP: 06110 /* Make sure it stops ringing */ 06111 dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 06112 /* Okay -- probably call waiting*/ 06113 if (ast_bridged_channel(p->owner)) 06114 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 06115 p->subs[idx].needunhold = 1; 06116 break; 06117 case AST_STATE_RESERVED: 06118 /* Start up dialtone */ 06119 if (has_voicemail(p)) 06120 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 06121 else 06122 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 06123 break; 06124 default: 06125 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 06126 } 06127 break; 06128 case SIG_FXSLS: 06129 case SIG_FXSGS: 06130 case SIG_FXSKS: 06131 if (ast->_state == AST_STATE_RING) { 06132 p->ringt = p->ringt_base; 06133 } 06134 06135 /* If we get a ring then we cannot be in 06136 * reversed polarity. So we reset to idle */ 06137 ast_debug(1, "Setting IDLE polarity due " 06138 "to ring. Old polarity was %d\n", 06139 p->polarity); 06140 p->polarity = POLARITY_IDLE; 06141 06142 /* Fall through */ 06143 case SIG_EM: 06144 case SIG_EM_E1: 06145 case SIG_EMWINK: 06146 case SIG_FEATD: 06147 case SIG_FEATDMF: 06148 case SIG_FEATDMF_TA: 06149 case SIG_E911: 06150 case SIG_FGC_CAMA: 06151 case SIG_FGC_CAMAMF: 06152 case SIG_FEATB: 06153 case SIG_SF: 06154 case SIG_SFWINK: 06155 case SIG_SF_FEATD: 06156 case SIG_SF_FEATDMF: 06157 case SIG_SF_FEATB: 06158 if (ast->_state == AST_STATE_PRERING) 06159 ast_setstate(ast, AST_STATE_RING); 06160 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 06161 ast_debug(1, "Ring detected\n"); 06162 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06163 p->subs[idx].f.subclass = AST_CONTROL_RING; 06164 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 06165 ast_debug(1, "Line answered\n"); 06166 if (p->confirmanswer) { 06167 p->subs[idx].f.frametype = AST_FRAME_NULL; 06168 p->subs[idx].f.subclass = 0; 06169 } else { 06170 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06171 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 06172 ast_setstate(ast, AST_STATE_UP); 06173 } 06174 } else if (ast->_state != AST_STATE_RING) 06175 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 06176 break; 06177 default: 06178 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 06179 } 06180 break; 06181 case DAHDI_EVENT_RINGBEGIN: 06182 switch (p->sig) { 06183 case SIG_FXSLS: 06184 case SIG_FXSGS: 06185 case SIG_FXSKS: 06186 if (ast->_state == AST_STATE_RING) { 06187 p->ringt = p->ringt_base; 06188 } 06189 break; 06190 } 06191 break; 06192 case DAHDI_EVENT_RINGEROFF: 06193 if (p->inalarm) break; 06194 if ((p->radio || (p->oprmode < 0))) break; 06195 ast->rings++; 06196 if ((ast->rings > p->cidrings) && (p->cidspill)) { 06197 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 06198 ast_free(p->cidspill); 06199 p->cidspill = NULL; 06200 p->callwaitcas = 0; 06201 } 06202 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06203 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 06204 break; 06205 case DAHDI_EVENT_RINGERON: 06206 break; 06207 case DAHDI_EVENT_NOALARM: 06208 p->inalarm = 0; 06209 #ifdef HAVE_PRI 06210 /* Extremely unlikely but just in case */ 06211 if (p->bearer) 06212 p->bearer->inalarm = 0; 06213 #endif 06214 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 06215 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 06216 "Channel: %d\r\n", p->channel); 06217 break; 06218 case DAHDI_EVENT_WINKFLASH: 06219 if (p->inalarm) break; 06220 if (p->radio) break; 06221 if (p->oprmode < 0) break; 06222 if (p->oprmode > 1) 06223 { 06224 struct dahdi_params par; 06225 06226 memset(&par, 0, sizeof(par)); 06227 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 06228 { 06229 if (!par.rxisoffhook) 06230 { 06231 /* Make sure it stops ringing */ 06232 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 06233 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 06234 save_conference(p); 06235 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 06236 } 06237 } 06238 break; 06239 } 06240 /* Remember last time we got a flash-hook */ 06241 p->flashtime = ast_tvnow(); 06242 switch (mysig) { 06243 case SIG_FXOLS: 06244 case SIG_FXOGS: 06245 case SIG_FXOKS: 06246 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 06247 idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 06248 p->callwaitcas = 0; 06249 06250 if (idx != SUB_REAL) { 06251 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel); 06252 goto winkflashdone; 06253 } 06254 06255 if (p->subs[SUB_CALLWAIT].owner) { 06256 /* Swap to call-wait */ 06257 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 06258 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 06259 p->owner = p->subs[SUB_REAL].owner; 06260 ast_debug(1, "Making %s the new owner\n", p->owner->name); 06261 if (p->owner->_state == AST_STATE_RINGING) { 06262 ast_setstate(p->owner, AST_STATE_UP); 06263 p->subs[SUB_REAL].needanswer = 1; 06264 } 06265 p->callwaitingrepeat = 0; 06266 p->cidcwexpire = 0; 06267 /* Start music on hold if appropriate */ 06268 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 06269 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 06270 S_OR(p->mohsuggest, NULL), 06271 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06272 } 06273 p->subs[SUB_CALLWAIT].needhold = 1; 06274 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 06275 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 06276 S_OR(p->mohsuggest, NULL), 06277 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06278 } 06279 p->subs[SUB_REAL].needunhold = 1; 06280 } else if (!p->subs[SUB_THREEWAY].owner) { 06281 if (!p->threewaycalling) { 06282 /* Just send a flash if no 3-way calling */ 06283 p->subs[SUB_REAL].needflash = 1; 06284 goto winkflashdone; 06285 } else if (!check_for_conference(p)) { 06286 char cid_num[256]; 06287 char cid_name[256]; 06288 06289 cid_num[0] = 0; 06290 cid_name[0] = 0; 06291 if (p->dahditrcallerid && p->owner) { 06292 if (p->owner->cid.cid_num) 06293 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 06294 if (p->owner->cid.cid_name) 06295 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 06296 } 06297 /* XXX This section needs much more error checking!!! XXX */ 06298 /* Start a 3-way call if feasible */ 06299 if (!((ast->pbx) || 06300 (ast->_state == AST_STATE_UP) || 06301 (ast->_state == AST_STATE_RING))) { 06302 ast_debug(1, "Flash when call not up or ringing\n"); 06303 goto winkflashdone; 06304 } 06305 if (alloc_sub(p, SUB_THREEWAY)) { 06306 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 06307 goto winkflashdone; 06308 } 06309 /* Make new channel */ 06310 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 06311 if (p->dahditrcallerid) { 06312 if (!p->origcid_num) 06313 p->origcid_num = ast_strdup(p->cid_num); 06314 if (!p->origcid_name) 06315 p->origcid_name = ast_strdup(p->cid_name); 06316 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 06317 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 06318 } 06319 /* Swap things around between the three-way and real call */ 06320 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06321 /* Disable echo canceller for better dialing */ 06322 dahdi_disable_ec(p); 06323 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 06324 if (res) 06325 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 06326 p->owner = chan; 06327 if (!chan) { 06328 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 06329 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 06330 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 06331 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06332 dahdi_enable_ec(p); 06333 ast_hangup(chan); 06334 } else { 06335 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 06336 int way3bridge = 0, cdr3way = 0; 06337 06338 if (!other) { 06339 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 06340 } else 06341 way3bridge = 1; 06342 06343 if (p->subs[SUB_THREEWAY].owner->cdr) 06344 cdr3way = 1; 06345 06346 ast_verb(3, "Started three way call on channel %d\n", p->channel); 06347 06348 /* Start music on hold if appropriate */ 06349 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06350 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 06351 S_OR(p->mohsuggest, NULL), 06352 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 06353 } 06354 p->subs[SUB_THREEWAY].needhold = 1; 06355 } 06356 } 06357 } else { 06358 /* Already have a 3 way call */ 06359 if (p->subs[SUB_THREEWAY].inthreeway) { 06360 /* Call is already up, drop the last person */ 06361 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel); 06362 /* If the primary call isn't answered yet, use it */ 06363 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 06364 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 06365 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06366 p->owner = p->subs[SUB_REAL].owner; 06367 } 06368 /* Drop the last call and stop the conference */ 06369 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 06370 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 06371 p->subs[SUB_REAL].inthreeway = 0; 06372 p->subs[SUB_THREEWAY].inthreeway = 0; 06373 } else { 06374 /* Lets see what we're up to */ 06375 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 06376 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 06377 int otherindex = SUB_THREEWAY; 06378 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 06379 int way3bridge = 0, cdr3way = 0; 06380 06381 if (!other) { 06382 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 06383 } else 06384 way3bridge = 1; 06385 06386 if (p->subs[SUB_THREEWAY].owner->cdr) 06387 cdr3way = 1; 06388 06389 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 06390 /* Put them in the threeway, and flip */ 06391 p->subs[SUB_THREEWAY].inthreeway = 1; 06392 p->subs[SUB_REAL].inthreeway = 1; 06393 if (ast->_state == AST_STATE_UP) { 06394 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06395 otherindex = SUB_REAL; 06396 } 06397 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 06398 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 06399 p->subs[otherindex].needunhold = 1; 06400 p->owner = p->subs[SUB_REAL].owner; 06401 if (ast->_state == AST_STATE_RINGING) { 06402 ast_debug(1, "Enabling ringtone on real and threeway\n"); 06403 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 06404 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 06405 } 06406 } else { 06407 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 06408 swap_subs(p, SUB_THREEWAY, SUB_REAL); 06409 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 06410 p->owner = p->subs[SUB_REAL].owner; 06411 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 06412 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06413 p->subs[SUB_REAL].needunhold = 1; 06414 dahdi_enable_ec(p); 06415 } 06416 } 06417 } 06418 winkflashdone: 06419 update_conf(p); 06420 break; 06421 case SIG_EM: 06422 case SIG_EM_E1: 06423 case SIG_FEATD: 06424 case SIG_SF: 06425 case SIG_SFWINK: 06426 case SIG_SF_FEATD: 06427 case SIG_FXSLS: 06428 case SIG_FXSGS: 06429 if (option_debug) { 06430 if (p->dialing) 06431 ast_debug(1, "Ignoring wink on channel %d\n", p->channel); 06432 else 06433 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 06434 } 06435 break; 06436 case SIG_FEATDMF_TA: 06437 switch (p->whichwink) { 06438 case 0: 06439 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 06440 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 06441 break; 06442 case 1: 06443 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 06444 break; 06445 case 2: 06446 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 06447 return NULL; 06448 } 06449 p->whichwink++; 06450 /* Fall through */ 06451 case SIG_FEATDMF: 06452 case SIG_E911: 06453 case SIG_FGC_CAMAMF: 06454 case SIG_FGC_CAMA: 06455 case SIG_FEATB: 06456 case SIG_SF_FEATDMF: 06457 case SIG_SF_FEATB: 06458 case SIG_EMWINK: 06459 /* FGD MF and EMWINK *Must* wait for wink */ 06460 if (!ast_strlen_zero(p->dop.dialstr)) { 06461 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 06462 if (res < 0) { 06463 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 06464 p->dop.dialstr[0] = '\0'; 06465 return NULL; 06466 } else 06467 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 06468 } 06469 p->dop.dialstr[0] = '\0'; 06470 break; 06471 default: 06472 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 06473 } 06474 break; 06475 case DAHDI_EVENT_HOOKCOMPLETE: 06476 if (p->inalarm) break; 06477 if ((p->radio || (p->oprmode < 0))) break; 06478 if (p->waitingfordt.tv_sec) break; 06479 switch (mysig) { 06480 case SIG_FXSLS: /* only interesting for FXS */ 06481 case SIG_FXSGS: 06482 case SIG_FXSKS: 06483 case SIG_EM: 06484 case SIG_EM_E1: 06485 case SIG_EMWINK: 06486 case SIG_FEATD: 06487 case SIG_SF: 06488 case SIG_SFWINK: 06489 case SIG_SF_FEATD: 06490 if (!ast_strlen_zero(p->dop.dialstr)) { 06491 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 06492 if (res < 0) { 06493 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 06494 p->dop.dialstr[0] = '\0'; 06495 return NULL; 06496 } else 06497 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr); 06498 } 06499 p->dop.dialstr[0] = '\0'; 06500 p->dop.op = DAHDI_DIAL_OP_REPLACE; 06501 break; 06502 case SIG_FEATDMF: 06503 case SIG_FEATDMF_TA: 06504 case SIG_E911: 06505 case SIG_FGC_CAMA: 06506 case SIG_FGC_CAMAMF: 06507 case SIG_FEATB: 06508 case SIG_SF_FEATDMF: 06509 case SIG_SF_FEATB: 06510 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 06511 break; 06512 default: 06513 break; 06514 } 06515 break; 06516 case DAHDI_EVENT_POLARITY: 06517 /* 06518 * If we get a Polarity Switch event, this could be 06519 * due to line seizure, remote end connect or remote end disconnect. 06520 * 06521 * Check to see if we should change the polarity state and 06522 * mark the channel as UP or if this is an indication 06523 * of remote end disconnect. 06524 */ 06525 06526 if (p->polarityonanswerdelay > 0) { 06527 /* check if event is not too soon after OffHook or Answer */ 06528 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 06529 switch (ast->_state) { 06530 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 06531 case AST_STATE_RINGING: /*!< Remote end is ringing */ 06532 if (p->answeronpolarityswitch) { 06533 ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel); 06534 ast_setstate(p->owner, AST_STATE_UP); 06535 p->polarity = POLARITY_REV; 06536 if (p->hanguponpolarityswitch) { 06537 p->polaritydelaytv = ast_tvnow(); 06538 } 06539 } else { 06540 ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel); 06541 } 06542 break; 06543 06544 case AST_STATE_UP: /*!< Line is up */ 06545 case AST_STATE_RING: /*!< Line is ringing */ 06546 if (p->hanguponpolarityswitch) { 06547 ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel); 06548 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 06549 p->polarity = POLARITY_IDLE; 06550 } else { 06551 ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel); 06552 } 06553 break; 06554 06555 case AST_STATE_DOWN: /*!< Channel is down and available */ 06556 case AST_STATE_RESERVED: /*!< Channel is down, but reserved */ 06557 case AST_STATE_OFFHOOK: /*!< Channel is off hook */ 06558 case AST_STATE_BUSY: /*!< Line is busy */ 06559 case AST_STATE_DIALING_OFFHOOK: /*!< Digits (or equivalent) have been dialed while offhook */ 06560 case AST_STATE_PRERING: /*!< Channel has detected an incoming call and is waiting for ring */ 06561 default: 06562 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 06563 ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state); 06564 } 06565 } 06566 06567 } else { 06568 /* event is too soon after OffHook or Answer */ 06569 switch (ast->_state) { 06570 case AST_STATE_DIALING: /*!< Digits (or equivalent) have been dialed */ 06571 case AST_STATE_RINGING: /*!< Remote end is ringing */ 06572 if (p->answeronpolarityswitch) { 06573 ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state); 06574 } 06575 break; 06576 06577 case AST_STATE_UP: /*!< Line is up */ 06578 case AST_STATE_RING: /*!< Line is ringing */ 06579 if (p->hanguponpolarityswitch) { 06580 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); 06581 } 06582 break; 06583 06584 default: 06585 if (p->answeronpolarityswitch || p->hanguponpolarityswitch) { 06586 ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state); 06587 } 06588 } 06589 } 06590 } 06591 06592 /* Added more log_debug information below to provide a better indication of what is going on */ 06593 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) ); 06594 break; 06595 default: 06596 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel); 06597 } 06598 return &p->subs[idx].f; 06599 }
| static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4313 of file chan_dahdi.c.
References ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_set_digitmode(), ast_free, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxbuffersinuse, dahdi_pvt::faxhandled, dahdi_pvt::fxsoffhookstate, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, 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_MFCR2, SIG_PRI, SIG_SS7, dahdi_pvt::span, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and dahdi_pvt::waitingfordt.
Referenced by pri_dchannel().
04314 { 04315 int res; 04316 int idx,x, law; 04317 /*static int restore_gains(struct dahdi_pvt *p);*/ 04318 struct dahdi_pvt *p = ast->tech_pvt; 04319 struct dahdi_pvt *tmp = NULL; 04320 struct dahdi_pvt *prev = NULL; 04321 struct dahdi_params par; 04322 04323 ast_debug(1, "dahdi_hangup(%s)\n", ast->name); 04324 if (!ast->tech_pvt) { 04325 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 04326 return 0; 04327 } 04328 04329 ast_mutex_lock(&p->lock); 04330 04331 idx = dahdi_get_index(ast, p, 1); 04332 04333 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04334 x = 1; 04335 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 04336 p->cid_num[0] = '\0'; 04337 p->cid_name[0] = '\0'; 04338 } 04339 04340 x = 0; 04341 dahdi_confmute(p, 0); 04342 p->muting = 0; 04343 restore_gains(p); 04344 if (p->origcid_num) { 04345 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 04346 ast_free(p->origcid_num); 04347 p->origcid_num = NULL; 04348 } 04349 if (p->origcid_name) { 04350 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 04351 ast_free(p->origcid_name); 04352 p->origcid_name = NULL; 04353 } 04354 if (p->dsp) 04355 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 04356 p->exten[0] = '\0'; 04357 04358 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 04359 p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 04360 p->ignoredtmf = 0; 04361 04362 if (idx > -1) { 04363 /* Real channel, do some fixup */ 04364 p->subs[idx].owner = NULL; 04365 p->subs[idx].needanswer = 0; 04366 p->subs[idx].needflash = 0; 04367 p->subs[idx].needringing = 0; 04368 p->subs[idx].needbusy = 0; 04369 p->subs[idx].needcongestion = 0; 04370 p->subs[idx].linear = 0; 04371 p->subs[idx].needcallerid = 0; 04372 p->polarity = POLARITY_IDLE; 04373 dahdi_setlinear(p->subs[idx].dfd, 0); 04374 if (idx == SUB_REAL) { 04375 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 04376 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n"); 04377 if (p->subs[SUB_CALLWAIT].inthreeway) { 04378 /* We had flipped over to answer a callwait and now it's gone */ 04379 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n"); 04380 /* Move to the call-wait, but un-own us until they flip back. */ 04381 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04382 unalloc_sub(p, SUB_CALLWAIT); 04383 p->owner = NULL; 04384 } else { 04385 /* The three way hung up, but we still have a call wait */ 04386 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 04387 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04388 unalloc_sub(p, SUB_THREEWAY); 04389 if (p->subs[SUB_REAL].inthreeway) { 04390 /* This was part of a three way call. Immediately make way for 04391 another call */ 04392 ast_debug(1, "Call was complete, setting owner to former third call\n"); 04393 p->owner = p->subs[SUB_REAL].owner; 04394 } else { 04395 /* This call hasn't been completed yet... Set owner to NULL */ 04396 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 04397 p->owner = NULL; 04398 } 04399 p->subs[SUB_REAL].inthreeway = 0; 04400 } 04401 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 04402 /* Move to the call-wait and switch back to them. */ 04403 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 04404 unalloc_sub(p, SUB_CALLWAIT); 04405 p->owner = p->subs[SUB_REAL].owner; 04406 if (p->owner->_state != AST_STATE_UP) 04407 p->subs[SUB_REAL].needanswer = 1; 04408 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 04409 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04410 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 04411 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04412 unalloc_sub(p, SUB_THREEWAY); 04413 if (p->subs[SUB_REAL].inthreeway) { 04414 /* This was part of a three way call. Immediately make way for 04415 another call */ 04416 ast_debug(1, "Call was complete, setting owner to former third call\n"); 04417 p->owner = p->subs[SUB_REAL].owner; 04418 } else { 04419 /* This call hasn't been completed yet... Set owner to NULL */ 04420 ast_debug(1, "Call was incomplete, setting owner to NULL\n"); 04421 p->owner = NULL; 04422 } 04423 p->subs[SUB_REAL].inthreeway = 0; 04424 } 04425 } else if (idx == SUB_CALLWAIT) { 04426 /* Ditch the holding callwait call, and immediately make it availabe */ 04427 if (p->subs[SUB_CALLWAIT].inthreeway) { 04428 /* This is actually part of a three way, placed on hold. Place the third part 04429 on music on hold now */ 04430 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04431 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 04432 S_OR(p->mohsuggest, NULL), 04433 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04434 } 04435 p->subs[SUB_THREEWAY].inthreeway = 0; 04436 /* Make it the call wait now */ 04437 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 04438 unalloc_sub(p, SUB_THREEWAY); 04439 } else 04440 unalloc_sub(p, SUB_CALLWAIT); 04441 } else if (idx == SUB_THREEWAY) { 04442 if (p->subs[SUB_CALLWAIT].inthreeway) { 04443 /* The other party of the three way call is currently in a call-wait state. 04444 Start music on hold for them, and take the main guy out of the third call */ 04445 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 04446 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 04447 S_OR(p->mohsuggest, NULL), 04448 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04449 } 04450 p->subs[SUB_CALLWAIT].inthreeway = 0; 04451 } 04452 p->subs[SUB_REAL].inthreeway = 0; 04453 /* If this was part of a three way call index, let us make 04454 another three way call */ 04455 unalloc_sub(p, SUB_THREEWAY); 04456 } else { 04457 /* This wasn't any sort of call, but how are we an index? */ 04458 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 04459 } 04460 } 04461 04462 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 04463 p->owner = NULL; 04464 p->ringt = 0; 04465 p->distinctivering = 0; 04466 p->confirmanswer = 0; 04467 p->cidrings = 1; 04468 p->outgoing = 0; 04469 p->digital = 0; 04470 p->faxhandled = 0; 04471 p->pulsedial = 0; 04472 p->onhooktime = time(NULL); 04473 #if defined(HAVE_PRI) || defined(HAVE_SS7) 04474 p->proceeding = 0; 04475 p->dialing = 0; 04476 p->progress = 0; 04477 p->alerting = 0; 04478 p->setup_ack = 0; 04479 p->rlt = 0; 04480 #endif 04481 if (p->dsp) { 04482 ast_dsp_free(p->dsp); 04483 p->dsp = NULL; 04484 } 04485 04486 if (p->faxbuffersinuse) { 04487 /* faxbuffers are in use, revert them */ 04488 struct dahdi_bufferinfo bi = { 04489 .txbufpolicy = p->buf_policy, 04490 .rxbufpolicy = p->buf_policy, 04491 .bufsize = p->bufsize, 04492 .numbufs = p->buf_no 04493 }; 04494 int bpres; 04495 04496 if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) { 04497 ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno)); 04498 } 04499 p->faxbuffersinuse = 0; 04500 } 04501 04502 law = DAHDI_LAW_DEFAULT; 04503 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 04504 if (res < 0) 04505 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 04506 /* Perform low level hangup if no owner left */ 04507 #ifdef HAVE_SS7 04508 if (p->ss7) { 04509 if (p->ss7call) { 04510 if (!ss7_grab(p, p->ss7)) { 04511 if (!p->alreadyhungup) { 04512 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE"); 04513 int icause = ast->hangupcause ? ast->hangupcause : -1; 04514 04515 if (cause) { 04516 if (atoi(cause)) 04517 icause = atoi(cause); 04518 } 04519 isup_rel(p->ss7->ss7, p->ss7call, icause); 04520 ss7_rel(p->ss7); 04521 p->alreadyhungup = 1; 04522 } else 04523 ast_log(LOG_WARNING, "Trying to hangup twice!\n"); 04524 } else { 04525 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic); 04526 res = -1; 04527 } 04528 } 04529 } 04530 #endif 04531 #ifdef HAVE_OPENR2 04532 p->cid_num[0] = '\0'; 04533 p->cid_name[0] = '\0'; 04534 if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) { 04535 ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel); 04536 /* If it's an incoming call, check the mfcr2_forced_release setting */ 04537 if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) { 04538 dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE); 04539 } else { 04540 const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE"); 04541 int r2cause_user = r2causestr ? atoi(r2causestr) : 0; 04542 openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user) 04543 : dahdi_ast_cause_to_r2_cause(ast->hangupcause); 04544 dahdi_r2_disconnect_call(p, r2cause); 04545 } 04546 } else if (p->mfcr2call) { 04547 ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel); 04548 /* since ast_request() was called but not ast_call() we have not yet dialed 04549 and the openr2 stack will not call on_call_end callback, we need to unset 04550 the mfcr2call flag and bump the monitor count so the monitor thread can take 04551 care of this channel events from now on */ 04552 p->mfcr2call = 0; 04553 } 04554 #endif 04555 #ifdef HAVE_PRI 04556 if (p->pri) { 04557 #ifdef SUPPORT_USERUSER 04558 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 04559 #endif 04560 04561 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 04562 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 04563 if (!pri_grab(p, p->pri)) { 04564 if (p->alreadyhungup) { 04565 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n"); 04566 04567 #ifdef SUPPORT_USERUSER 04568 pri_call_set_useruser(p->call, useruser); 04569 #endif 04570 04571 pri_hangup(p->pri->pri, p->call, -1); 04572 p->call = NULL; 04573 if (p->bearer) 04574 p->bearer->call = NULL; 04575 } else { 04576 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 04577 int icause = ast->hangupcause ? ast->hangupcause : -1; 04578 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 04579 04580 #ifdef SUPPORT_USERUSER 04581 pri_call_set_useruser(p->call, useruser); 04582 #endif 04583 04584 p->alreadyhungup = 1; 04585 if (p->bearer) 04586 p->bearer->alreadyhungup = 1; 04587 if (cause) { 04588 if (atoi(cause)) 04589 icause = atoi(cause); 04590 } 04591 pri_hangup(p->pri->pri, p->call, icause); 04592 } 04593 if (res < 0) 04594 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 04595 pri_rel(p->pri); 04596 } else { 04597 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 04598 res = -1; 04599 } 04600 } else { 04601 if (p->bearer) 04602 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 04603 p->call = NULL; 04604 res = 0; 04605 } 04606 } 04607 #endif 04608 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) 04609 && (p->sig != SIG_BRI) 04610 && (p->sig != SIG_BRI_PTMP)) 04611 && (p->sig != SIG_MFCR2)) 04612 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 04613 if (res < 0) { 04614 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 04615 } 04616 switch (p->sig) { 04617 case SIG_FXOGS: 04618 case SIG_FXOLS: 04619 case SIG_FXOKS: 04620 memset(&par, 0, sizeof(par)); 04621 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 04622 if (!res) { 04623 #if 0 04624 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 04625 #endif 04626 /* If they're off hook, try playing congestion */ 04627 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 04628 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 04629 else 04630 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 04631 p->fxsoffhookstate = par.rxisoffhook; 04632 } 04633 break; 04634 case SIG_FXSGS: 04635 case SIG_FXSLS: 04636 case SIG_FXSKS: 04637 /* Make sure we're not made available for at least two seconds assuming 04638 we were actually used for an inbound or outbound call. */ 04639 if (ast->_state != AST_STATE_RESERVED) { 04640 time(&p->guardtime); 04641 p->guardtime += 2; 04642 } 04643 break; 04644 default: 04645 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 04646 } 04647 if (p->cidspill) 04648 ast_free(p->cidspill); 04649 if (p->sig) 04650 dahdi_disable_ec(p); 04651 x = 0; 04652 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 04653 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 04654 p->didtdd = 0; 04655 p->cidspill = NULL; 04656 p->callwaitcas = 0; 04657 p->callwaiting = p->permcallwaiting; 04658 p->hidecallerid = p->permhidecallerid; 04659 p->waitingfordt.tv_sec = 0; 04660 p->dialing = 0; 04661 p->rdnis[0] = '\0'; 04662 update_conf(p); 04663 reset_conf(p); 04664 /* Restore data mode */ 04665 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) { 04666 x = 0; 04667 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 04668 } 04669 #ifdef HAVE_PRI 04670 if (p->bearer) { 04671 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel); 04672 /* Free up the bearer channel as well, and 04673 don't use its file descriptor anymore */ 04674 update_conf(p->bearer); 04675 reset_conf(p->bearer); 04676 p->bearer->owner = NULL; 04677 p->bearer->realcall = NULL; 04678 p->bearer = NULL; 04679 p->subs[SUB_REAL].dfd = -1; 04680 p->pri = NULL; 04681 } 04682 #endif 04683 if (num_restart_pending == 0) 04684 restart_monitor(); 04685 } 04686 04687 p->callwaitingrepeat = 0; 04688 p->cidcwexpire = 0; 04689 p->oprmode = 0; 04690 ast->tech_pvt = NULL; 04691 ast_mutex_unlock(&p->lock); 04692 ast_module_unref(ast_module_info->self); 04693 ast_verb(3, "Hungup '%s'\n", ast->name); 04694 04695 ast_mutex_lock(&iflock); 04696 04697 if (p->restartpending) { 04698 num_restart_pending--; 04699 } 04700 04701 tmp = iflist; 04702 prev = NULL; 04703 if (p->destroy) { 04704 while (tmp) { 04705 if (tmp == p) { 04706 destroy_channel(prev, tmp, 0); 04707 break; 04708 } else { 04709 prev = tmp; 04710 tmp = tmp->next; 04711 } 04712 } 04713 } 04714 ast_mutex_unlock(&iflock); 04715 return 0; 04716 }
| static int dahdi_indicate | ( | struct ast_channel * | chan, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 7170 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, ast_channel::name, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::rlt, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SS7, dahdi_pvt::span, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
Referenced by dahdi_fixup().
07171 { 07172 struct dahdi_pvt *p = chan->tech_pvt; 07173 int res=-1; 07174 int idx; 07175 int func = DAHDI_FLASH; 07176 ast_mutex_lock(&p->lock); 07177 idx = dahdi_get_index(chan, p, 0); 07178 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name); 07179 #ifdef HAVE_OPENR2 07180 if (p->mfcr2 && !p->mfcr2_call_accepted) { 07181 ast_mutex_unlock(&p->lock); 07182 /* if this is an R2 call and the call is not yet accepted, we don't want the 07183 tone indications to mess up with the MF tones */ 07184 return 0; 07185 } 07186 #endif 07187 if (idx == SUB_REAL) { 07188 switch (condition) { 07189 case AST_CONTROL_BUSY: 07190 #ifdef HAVE_PRI 07191 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 07192 chan->hangupcause = AST_CAUSE_USER_BUSY; 07193 chan->_softhangup |= AST_SOFTHANGUP_DEV; 07194 res = 0; 07195 } else if (!p->progress && 07196 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 07197 && p->pri && !p->outgoing) { 07198 if (p->pri->pri) { 07199 if (!pri_grab(p, p->pri)) { 07200 #ifdef HAVE_PRI_PROG_W_CAUSE 07201 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */ 07202 #else 07203 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 07204 #endif 07205 pri_rel(p->pri); 07206 } 07207 else 07208 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07209 } 07210 p->progress = 1; 07211 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 07212 } else 07213 #endif 07214 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY); 07215 break; 07216 case AST_CONTROL_RINGING: 07217 #ifdef HAVE_PRI 07218 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 07219 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 07220 if (p->pri->pri) { 07221 if (!pri_grab(p, p->pri)) { 07222 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 07223 pri_rel(p->pri); 07224 } 07225 else 07226 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07227 } 07228 p->alerting = 1; 07229 } 07230 07231 #endif 07232 #ifdef HAVE_SS7 07233 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) { 07234 if (p->ss7->ss7) { 07235 ss7_grab(p, p->ss7); 07236 07237 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 07238 p->rlt = 1; 07239 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */ 07240 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING); 07241 p->alerting = 1; 07242 ss7_rel(p->ss7); 07243 } 07244 } 07245 #endif 07246 07247 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE); 07248 07249 if (chan->_state != AST_STATE_UP) { 07250 if ((chan->_state != AST_STATE_RING) || 07251 ((p->sig != SIG_FXSKS) && 07252 (p->sig != SIG_FXSLS) && 07253 (p->sig != SIG_FXSGS))) 07254 ast_setstate(chan, AST_STATE_RINGING); 07255 } 07256 break; 07257 case AST_CONTROL_PROCEEDING: 07258 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 07259 #ifdef HAVE_PRI 07260 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 07261 && p->pri && !p->outgoing) { 07262 if (p->pri->pri) { 07263 if (!pri_grab(p, p->pri)) { 07264 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 07265 pri_rel(p->pri); 07266 } 07267 else 07268 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07269 } 07270 p->proceeding = 1; 07271 p->dialing = 0; 07272 } 07273 #endif 07274 #ifdef HAVE_SS7 07275 /* This IF sends the FAR for an answered ALEG call */ 07276 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){ 07277 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) 07278 p->rlt = 1; 07279 } 07280 07281 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) { 07282 if (p->ss7->ss7) { 07283 ss7_grab(p, p->ss7); 07284 isup_acm(p->ss7->ss7, p->ss7call); 07285 p->proceeding = 1; 07286 ss7_rel(p->ss7); 07287 07288 } 07289 } 07290 #endif 07291 /* don't continue in ast_indicate */ 07292 res = 0; 07293 break; 07294 case AST_CONTROL_PROGRESS: 07295 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 07296 #ifdef HAVE_PRI 07297 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 07298 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 07299 && p->pri && !p->outgoing) { 07300 if (p->pri->pri) { 07301 if (!pri_grab(p, p->pri)) { 07302 #ifdef HAVE_PRI_PROG_W_CAUSE 07303 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1); /* no cause at all */ 07304 #else 07305 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 07306 #endif 07307 pri_rel(p->pri); 07308 } 07309 else 07310 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07311 } 07312 p->progress = 1; 07313 } 07314 #endif 07315 #ifdef HAVE_SS7 07316 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) { 07317 if (p->ss7->ss7) { 07318 ss7_grab(p, p->ss7); 07319 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO); 07320 p->progress = 1; 07321 ss7_rel(p->ss7); 07322 /* enable echo canceler here on SS7 calls */ 07323 dahdi_enable_ec(p); 07324 07325 } 07326 } 07327 #endif 07328 /* don't continue in ast_indicate */ 07329 res = 0; 07330 break; 07331 case AST_CONTROL_CONGESTION: 07332 chan->hangupcause = AST_CAUSE_CONGESTION; 07333 #ifdef HAVE_PRI 07334 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) { 07335 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 07336 chan->_softhangup |= AST_SOFTHANGUP_DEV; 07337 res = 0; 07338 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 07339 && p->pri && !p->outgoing) { 07340 if (p->pri) { 07341 if (!pri_grab(p, p->pri)) { 07342 #ifdef HAVE_PRI_PROG_W_CAUSE 07343 pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */ 07344 #else 07345 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 07346 #endif 07347 pri_rel(p->pri); 07348 } else 07349 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07350 } 07351 p->progress = 1; 07352 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07353 } else 07354 #endif 07355 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 07356 break; 07357 case AST_CONTROL_HOLD: 07358 #ifdef HAVE_PRI 07359 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 07360 if (!pri_grab(p, p->pri)) { 07361 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 07362 pri_rel(p->pri); 07363 } else 07364 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07365 } else 07366 #endif 07367 ast_moh_start(chan, data, p->mohinterpret); 07368 break; 07369 case AST_CONTROL_UNHOLD: 07370 #ifdef HAVE_PRI 07371 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 07372 if (!pri_grab(p, p->pri)) { 07373 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 07374 pri_rel(p->pri); 07375 } else 07376 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07377 } else 07378 #endif 07379 ast_moh_stop(chan); 07380 break; 07381 case AST_CONTROL_RADIO_KEY: 07382 if (p->radio) 07383 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); 07384 res = 0; 07385 break; 07386 case AST_CONTROL_RADIO_UNKEY: 07387 if (p->radio) 07388 res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF); 07389 res = 0; 07390 break; 07391 case AST_CONTROL_FLASH: 07392 /* flash hookswitch */ 07393 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 07394 /* Clear out the dial buffer */ 07395 p->dop.dialstr[0] = '\0'; 07396 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 07397 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 07398 chan->name, strerror(errno)); 07399 } else 07400 res = 0; 07401 } else 07402 res = 0; 07403 break; 07404 case AST_CONTROL_SRCUPDATE: 07405 res = 0; 07406 break; 07407 case -1: 07408 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 07409 break; 07410 } 07411 } else 07412 res = 0; 07413 ast_mutex_unlock(&p->lock); 07414 return res; 07415 }
Definition at line 5100 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().
05100 { 05101 int x; 05102 if (!slave || !master) { 05103 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 05104 return; 05105 } 05106 for (x = 0; x < MAX_SLAVES; x++) { 05107 if (!master->slaves[x]) { 05108 master->slaves[x] = slave; 05109 break; 05110 } 05111 } 05112 if (x >= MAX_SLAVES) { 05113 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 05114 master->slaves[MAX_SLAVES - 1] = slave; 05115 } 05116 if (slave->master) 05117 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 05118 slave->master = master; 05119 05120 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 05121 }
| static void dahdi_loopback | ( | struct dahdi_pvt * | p, | |
| int | enable | |||
| ) | [static] |
Definition at line 11221 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().
11222 { 11223 if (p->loopedback != enable) { 11224 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) { 11225 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno)); 11226 return; 11227 } 11228 p->loopedback = enable; 11229 } 11230 }
| 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 7417 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_buffer(), ast_str_set(), ast_strdup, ast_string_field_set, ast_strlen_zero(), AST_TRANS_CAP_DIGITAL, ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, ast_callerid::cid_ani2, ast_callerid::cid_dnid, dahdi_pvt::cid_name, dahdi_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, dahdi_pvt::context, dahdi_confmute(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, DSP_FEATURE_WAITDIALTONE, 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::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, SIG_SS7, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, ast_variable::value, dahdi_pvt::vars, dahdi_pvt::waitfordialtone, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_request(), handle_init_event(), mwi_thread(), pri_dchannel(), and ss7_start_call().
07418 { 07419 struct ast_channel *tmp; 07420 int deflaw; 07421 int res; 07422 int x,y; 07423 int features; 07424 struct ast_str *chan_name; 07425 struct ast_variable *v; 07426 struct dahdi_params ps; 07427 if (i->subs[idx].owner) { 07428 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]); 07429 return NULL; 07430 } 07431 y = 1; 07432 chan_name = ast_str_alloca(32); 07433 do { 07434 #ifdef HAVE_PRI 07435 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 07436 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y); 07437 else 07438 #endif 07439 if (i->channel == CHAN_PSEUDO) 07440 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random()); 07441 else 07442 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y); 07443 for (x = 0; x < 3; x++) { 07444 if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6)) 07445 break; 07446 } 07447 y++; 07448 } while (x < 3); 07449 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name)); 07450 if (!tmp) 07451 return NULL; 07452 tmp->tech = &dahdi_tech; 07453 memset(&ps, 0, sizeof(ps)); 07454 ps.channo = i->channel; 07455 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 07456 if (res) { 07457 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 07458 ps.curlaw = DAHDI_LAW_MULAW; 07459 } 07460 if (ps.curlaw == DAHDI_LAW_ALAW) 07461 deflaw = AST_FORMAT_ALAW; 07462 else 07463 deflaw = AST_FORMAT_ULAW; 07464 if (law) { 07465 if (law == DAHDI_LAW_ALAW) 07466 deflaw = AST_FORMAT_ALAW; 07467 else 07468 deflaw = AST_FORMAT_ULAW; 07469 } 07470 ast_channel_set_fd(tmp, 0, i->subs[idx].dfd); 07471 tmp->nativeformats = deflaw; 07472 /* Start out assuming ulaw since it's smaller :) */ 07473 tmp->rawreadformat = deflaw; 07474 tmp->readformat = deflaw; 07475 tmp->rawwriteformat = deflaw; 07476 tmp->writeformat = deflaw; 07477 i->subs[idx].linear = 0; 07478 dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear); 07479 features = 0; 07480 if (idx == SUB_REAL) { 07481 if (i->busydetect && CANBUSYDETECT(i)) 07482 features |= DSP_FEATURE_BUSY_DETECT; 07483 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i)) 07484 features |= DSP_FEATURE_CALL_PROGRESS; 07485 if ((i->waitfordialtone) && CANPROGRESSDETECT(i)) 07486 features |= DSP_FEATURE_WAITDIALTONE; 07487 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 07488 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) { 07489 features |= DSP_FEATURE_FAX_DETECT; 07490 } 07491 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 07492 if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) { 07493 i->hardwaredtmf = 0; 07494 features |= DSP_FEATURE_DIGIT_DETECT; 07495 } else if (NEED_MFDETECT(i)) { 07496 i->hardwaredtmf = 1; 07497 features |= DSP_FEATURE_DIGIT_DETECT; 07498 } 07499 } 07500 if (features) { 07501 if (i->dsp) { 07502 ast_debug(1, "Already have a dsp on %s?\n", tmp->name); 07503 } else { 07504 if (i->channel != CHAN_PSEUDO) 07505 i->dsp = ast_dsp_new(); 07506 else 07507 i->dsp = NULL; 07508 if (i->dsp) { 07509 i->dsp_features = features; 07510 #if defined(HAVE_PRI) || defined(HAVE_SS7) 07511 /* We cannot do progress detection until receives PROGRESS message */ 07512 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) { 07513 /* Remember requested DSP features, don't treat 07514 talking as ANSWER */ 07515 i->dsp_features = features & ~DSP_PROGRESS_TALK; 07516 features = 0; 07517 } 07518 #endif 07519 ast_dsp_set_features(i->dsp, features); 07520 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 07521 if (!ast_strlen_zero(progzone)) 07522 ast_dsp_set_call_progress_zone(i->dsp, progzone); 07523 if (i->busydetect && CANBUSYDETECT(i)) { 07524 ast_dsp_set_busy_count(i->dsp, i->busycount); 07525 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength); 07526 } 07527 } 07528 } 07529 } 07530 07531 if (state == AST_STATE_RING) 07532 tmp->rings = 1; 07533 tmp->tech_pvt = i; 07534 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 07535 /* Only FXO signalled stuff can be picked up */ 07536 tmp->callgroup = i->callgroup; 07537 tmp->pickupgroup = i->pickupgroup; 07538 } 07539 if (!ast_strlen_zero(i->parkinglot)) 07540 ast_string_field_set(tmp, parkinglot, i->parkinglot); 07541 if (!ast_strlen_zero(i->language)) 07542 ast_string_field_set(tmp, language, i->language); 07543 if (!i->owner) 07544 i->owner = tmp; 07545 if (!ast_strlen_zero(i->accountcode)) 07546 ast_string_field_set(tmp, accountcode, i->accountcode); 07547 if (i->amaflags) 07548 tmp->amaflags = i->amaflags; 07549 i->subs[idx].owner = tmp; 07550 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 07551 ast_string_field_set(tmp, call_forward, i->call_forward); 07552 /* If we've been told "no ADSI" then enforce it */ 07553 if (!i->adsi) 07554 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 07555 if (!ast_strlen_zero(i->exten)) 07556 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 07557 if (!ast_strlen_zero(i->rdnis)) 07558 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 07559 if (!ast_strlen_zero(i->dnid)) 07560 tmp->cid.cid_dnid = ast_strdup(i->dnid); 07561 07562 /* Don't use ast_set_callerid() here because it will 07563 * generate a needless NewCallerID event */ 07564 #ifdef PRI_ANI 07565 if (!ast_strlen_zero(i->cid_ani)) 07566 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 07567 else 07568 tmp->cid.cid_ani = ast_strdup(i->cid_num); 07569 #else 07570 tmp->cid.cid_ani = ast_strdup(i->cid_num); 07571 #endif 07572 tmp->cid.cid_pres = i->callingpres; 07573 tmp->cid.cid_ton = i->cid_ton; 07574 tmp->cid.cid_ani2 = i->cid_ani2; 07575 #if defined(HAVE_PRI) || defined(HAVE_SS7) 07576 tmp->transfercapability = transfercapability; 07577 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 07578 if (transfercapability & AST_TRANS_CAP_DIGITAL) 07579 i->digital = 1; 07580 /* Assume calls are not idle calls unless we're told differently */ 07581 i->isidlecall = 0; 07582 i->alreadyhungup = 0; 07583 #endif 07584 /* clear the fake event in case we posted one before we had ast_channel */ 07585 i->fake_event = 0; 07586 /* Assure there is no confmute on this channel */ 07587 dahdi_confmute(i, 0); 07588 i->muting = 0; 07589 /* Configure the new channel jb */ 07590 ast_jb_configure(tmp, &global_jbconf); 07591 07592 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name); 07593 07594 for (v = i->vars ; v ; v = v->next) 07595 pbx_builtin_setvar_helper(tmp, v->name, v->value); 07596 07597 if (startpbx) { 07598 #ifdef HAVE_OPENR2 07599 if (i->mfcr2call) { 07600 pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category)); 07601 } 07602 #endif 07603 if (ast_pbx_start(tmp)) { 07604 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 07605 ast_hangup(tmp); 07606 i->owner = NULL; 07607 return NULL; 07608 } 07609 } 07610 07611 ast_module_ref(ast_module_info->self); 07612 return tmp; 07613 }
| static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 2090 of file chan_dahdi.c.
References ast_log(), chan, errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), duplicate_pseudo(), and mkintf().
02091 { 02092 int fd; 02093 int isnum; 02094 int chan = 0; 02095 int bs; 02096 int x; 02097 isnum = 1; 02098 for (x = 0; x < strlen(fn); x++) { 02099 if (!isdigit(fn[x])) { 02100 isnum = 0; 02101 break; 02102 } 02103 } 02104 if (isnum) { 02105 chan = atoi(fn); 02106 if (chan < 1) { 02107 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 02108 return -1; 02109 } 02110 fn = "/dev/dahdi/channel"; 02111 } 02112 fd = open(fn, O_RDWR | O_NONBLOCK); 02113 if (fd < 0) { 02114 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 02115 return -1; 02116 } 02117 if (chan) { 02118 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 02119 x = errno; 02120 close(fd); 02121 errno = x; 02122 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 02123 return -1; 02124 } 02125 } 02126 bs = READ_SIZE; 02127 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 02128 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 02129 x = errno; 02130 close(fd); 02131 errno = x; 02132 return -1; 02133 } 02134 return fd; 02135 }
| static void dahdi_pri_error | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 12256 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().
12257 { 12258 int x, y; 12259 int dchan = -1, span = -1; 12260 int dchancount = 0; 12261 12262 if (pri) { 12263 for (x = 0; x < NUM_SPANS; x++) { 12264 for (y = 0; y < NUM_DCHANS; y++) { 12265 if (pris[x].dchans[y]) 12266 dchancount++; 12267 12268 if (pris[x].dchans[y] == pri) 12269 dchan = y; 12270 } 12271 if (dchan >= 0) { 12272 span = x; 12273 break; 12274 } 12275 dchancount = 0; 12276 } 12277 if ((dchancount > 1) && (span > -1)) 12278 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s); 12279 else 12280 ast_log(LOG_ERROR, "%s", s); 12281 } else 12282 ast_log(LOG_ERROR, "%s", s); 12283 12284 ast_mutex_lock(&pridebugfdlock); 12285 12286 if (pridebugfd >= 0) { 12287 if (write(pridebugfd, s, strlen(s)) < 0) { 12288 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 12289 } 12290 } 12291 12292 ast_mutex_unlock(&pridebugfdlock); 12293 }
| static void dahdi_pri_message | ( | struct pri * | pri, | |
| char * | s | |||
| ) | [static] |
Definition at line 12215 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().
12216 { 12217 int x, y; 12218 int dchan = -1, span = -1; 12219 int dchancount = 0; 12220 12221 if (pri) { 12222 for (x = 0; x < NUM_SPANS; x++) { 12223 for (y = 0; y < NUM_DCHANS; y++) { 12224 if (pris[x].dchans[y]) 12225 dchancount++; 12226 12227 if (pris[x].dchans[y] == pri) 12228 dchan = y; 12229 } 12230 if (dchan >= 0) { 12231 span = x; 12232 break; 12233 } 12234 dchancount = 0; 12235 } 12236 if (dchancount > 1 && (span > -1)) 12237 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s); 12238 else 12239 ast_verbose("%s", s); 12240 } else 12241 ast_verbose("%s", s); 12242 12243 ast_mutex_lock(&pridebugfdlock); 12244 12245 if (pridebugfd >= 0) { 12246 if (write(pridebugfd, s, strlen(s)) < 0) { 12247 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 12248 } 12249 } 12250 12251 ast_mutex_unlock(&pridebugfdlock); 12252 }
Definition at line 1544 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_ss7::lock, dahdi_pri::lock, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, and dahdi_ss7::ss7.
Referenced by action_dahdidialoffhook(), pri_dchannel(), and ss7_linkset().
01545 { 01546 #ifdef HAVE_PRI 01547 struct dahdi_pri *pri = (struct dahdi_pri*) data; 01548 #endif 01549 #ifdef HAVE_SS7 01550 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data; 01551 #endif 01552 /* We must unlock the PRI to avoid the possibility of a deadlock */ 01553 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01554 if (data) { 01555 switch (p->sig) { 01556 #ifdef HAVE_PRI 01557 case SIG_BRI: 01558 case SIG_BRI_PTMP: 01559 case SIG_PRI: 01560 ast_mutex_unlock(&pri->lock); 01561 break; 01562 #endif 01563 #ifdef HAVE_SS7 01564 case SIG_SS7: 01565 ast_mutex_unlock(&ss7->lock); 01566 break; 01567 #endif 01568 default: 01569 break; 01570 } 01571 } 01572 #endif 01573 for (;;) { 01574 if (p->owner) { 01575 if (ast_channel_trylock(p->owner)) { 01576 DEADLOCK_AVOIDANCE(&p->lock); 01577 } else { 01578 ast_queue_frame(p->owner, f); 01579 ast_channel_unlock(p->owner); 01580 break; 01581 } 01582 } else 01583 break; 01584 } 01585 #if defined(HAVE_PRI) || defined(HAVE_SS7) 01586 if (data) { 01587 switch (p->sig) { 01588 #ifdef HAVE_PRI 01589 case SIG_BRI: 01590 case SIG_BRI_PTMP: 01591 case SIG_PRI: 01592 ast_mutex_lock(&pri->lock); 01593 break; 01594 #endif 01595 #ifdef HAVE_SS7 01596 case SIG_SS7: 01597 ast_mutex_lock(&ss7->lock); 01598 break; 01599 #endif 01600 default: 01601 break; 01602 } 01603 } 01604 #endif 01605 }
| static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 6717 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_get_tcount(), ast_dsp_get_tstate(), ast_dsp_process(), ast_dsp_set_features(), ast_dsp_was_muted(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_confmute(), dahdi_get_index(), dahdi_handle_dtmfup(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::dsp, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_RINGING, errno, dahdi_subchannel::f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::proceeding, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.
06718 { 06719 struct dahdi_pvt *p = ast->tech_pvt; 06720 int res; 06721 int idx; 06722 void *readbuf; 06723 struct ast_frame *f; 06724 06725 while (ast_mutex_trylock(&p->lock)) { 06726 CHANNEL_DEADLOCK_AVOIDANCE(ast); 06727 } 06728 06729 idx = dahdi_get_index(ast, p, 0); 06730 06731 /* Hang up if we don't really exist */ 06732 if (idx < 0) { 06733 ast_log(LOG_WARNING, "We dont exist?\n"); 06734 ast_mutex_unlock(&p->lock); 06735 return NULL; 06736 } 06737 06738 if ((p->radio || (p->oprmode < 0)) && p->inalarm) { 06739 ast_mutex_unlock(&p->lock); 06740 return NULL; 06741 } 06742 06743 p->subs[idx].f.frametype = AST_FRAME_NULL; 06744 p->subs[idx].f.datalen = 0; 06745 p->subs[idx].f.samples = 0; 06746 p->subs[idx].f.mallocd = 0; 06747 p->subs[idx].f.offset = 0; 06748 p->subs[idx].f.subclass = 0; 06749 p->subs[idx].f.delivery = ast_tv(0,0); 06750 p->subs[idx].f.src = "dahdi_read"; 06751 p->subs[idx].f.data.ptr = NULL; 06752 06753 /* make sure it sends initial key state as first frame */ 06754 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 06755 { 06756 struct dahdi_params ps; 06757 06758 memset(&ps, 0, sizeof(ps)); 06759 ps.channo = p->channel; 06760 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 06761 ast_mutex_unlock(&p->lock); 06762 return NULL; 06763 } 06764 p->firstradio = 1; 06765 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06766 if (ps.rxisoffhook) 06767 { 06768 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY; 06769 } 06770 else 06771 { 06772 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY; 06773 } 06774 ast_mutex_unlock(&p->lock); 06775 return &p->subs[idx].f; 06776 } 06777 if (p->ringt == 1) { 06778 ast_mutex_unlock(&p->lock); 06779 return NULL; 06780 } 06781 else if (p->ringt > 0) 06782 p->ringt--; 06783 06784 #ifdef HAVE_OPENR2 06785 if (p->mfcr2) { 06786 openr2_chan_process_event(p->r2chan); 06787 } 06788 #endif 06789 06790 if (p->subs[idx].needringing) { 06791 /* Send ringing frame if requested */ 06792 p->subs[idx].needringing = 0; 06793 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06794 p->subs[idx].f.subclass = AST_CONTROL_RINGING; 06795 ast_setstate(ast, AST_STATE_RINGING); 06796 ast_mutex_unlock(&p->lock); 06797 return &p->subs[idx].f; 06798 } 06799 06800 if (p->subs[idx].needbusy) { 06801 /* Send busy frame if requested */ 06802 p->subs[idx].needbusy = 0; 06803 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06804 p->subs[idx].f.subclass = AST_CONTROL_BUSY; 06805 ast_mutex_unlock(&p->lock); 06806 return &p->subs[idx].f; 06807 } 06808 06809 if (p->subs[idx].needcongestion) { 06810 /* Send congestion frame if requested */ 06811 p->subs[idx].needcongestion = 0; 06812 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06813 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION; 06814 ast_mutex_unlock(&p->lock); 06815 return &p->subs[idx].f; 06816 } 06817 06818 if (p->subs[idx].needcallerid) { 06819 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 06820 S_OR(p->lastcid_name, NULL), 06821 S_OR(p->lastcid_num, NULL) 06822 ); 06823 p->subs[idx].needcallerid = 0; 06824 } 06825 06826 if (p->subs[idx].needanswer) { 06827 /* Send answer frame if requested */ 06828 p->subs[idx].needanswer = 0; 06829 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06830 p->subs[idx].f.subclass = AST_CONTROL_ANSWER; 06831 ast_mutex_unlock(&p->lock); 06832 return &p->subs[idx].f; 06833 } 06834 #ifdef HAVE_OPENR2 06835 if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) { 06836 /* openr2 took care of reading and handling any event 06837 (needanswer, needbusy etc), if we continue we will read() 06838 twice, lets just return a null frame. This should only 06839 happen when openr2 is dialing out */ 06840 ast_mutex_unlock(&p->lock); 06841 return &ast_null_frame; 06842 } 06843 #endif 06844 06845 if (p->subs[idx].needflash) { 06846 /* Send answer frame if requested */ 06847 p->subs[idx].needflash = 0; 06848 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06849 p->subs[idx].f.subclass = AST_CONTROL_FLASH; 06850 ast_mutex_unlock(&p->lock); 06851 return &p->subs[idx].f; 06852 } 06853 06854 if (p->subs[idx].needhold) { 06855 /* Send answer frame if requested */ 06856 p->subs[idx].needhold = 0; 06857 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06858 p->subs[idx].f.subclass = AST_CONTROL_HOLD; 06859 ast_mutex_unlock(&p->lock); 06860 ast_debug(1, "Sending hold on '%s'\n", ast->name); 06861 return &p->subs[idx].f; 06862 } 06863 06864 if (p->subs[idx].needunhold) { 06865 /* Send answer frame if requested */ 06866 p->subs[idx].needunhold = 0; 06867 p->subs[idx].f.frametype = AST_FRAME_CONTROL; 06868 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD; 06869 ast_mutex_unlock(&p->lock); 06870 ast_debug(1, "Sending unhold on '%s'\n", ast->name); 06871 return &p->subs[idx].f; 06872 } 06873 06874 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 06875 if (!p->subs[idx].linear) { 06876 p->subs[idx].linear = 1; 06877 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06878 if (res) 06879 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx); 06880 } 06881 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 06882 (ast->rawreadformat == AST_FORMAT_ALAW)) { 06883 if (p->subs[idx].linear) { 06884 p->subs[idx].linear = 0; 06885 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 06886 if (res) 06887 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx); 06888 } 06889 } else { 06890 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 06891 ast_mutex_unlock(&p->lock); 06892 return NULL; 06893 } 06894 readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET; 06895 CHECK_BLOCKING(ast); 06896 res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 06897 ast_clear_flag(ast, AST_FLAG_BLOCKING); 06898 /* Check for hangup */ 06899 if (res < 0) { 06900 f = NULL; 06901 if (res == -1) { 06902 if (errno == EAGAIN) { 06903 /* Return "NULL" frame if there is nobody there */ 06904 ast_mutex_unlock(&p->lock); 06905 return &p->subs[idx].f; 06906 } else if (errno == ELAST) { 06907 f = __dahdi_exception(ast); 06908 } else 06909 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 06910 } 06911 ast_mutex_unlock(&p->lock); 06912 return f; 06913 } 06914 if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { 06915 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); 06916 f = __dahdi_exception(ast); 06917 ast_mutex_unlock(&p->lock); 06918 return f; 06919 } 06920 if (p->tdd) { /* if in TDD mode, see if we receive that */ 06921 int c; 06922 06923 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 06924 if (c < 0) { 06925 ast_debug(1,"tdd_feed failed\n"); 06926 ast_mutex_unlock(&p->lock); 06927 return NULL; 06928 } 06929 if (c) { /* if a char to return */ 06930 p->subs[idx].f.subclass = 0; 06931 p->subs[idx].f.frametype = AST_FRAME_TEXT; 06932 p->subs[idx].f.mallocd = 0; 06933 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 06934 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET; 06935 p->subs[idx].f.datalen = 1; 06936 *((char *) p->subs[idx].f.data.ptr) = c; 06937 ast_mutex_unlock(&p->lock); 06938 return &p->subs[idx].f; 06939 } 06940 } 06941 /* Ensure the CW timer decrements only on a single subchannel */ 06942 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 06943 p->callwaitingrepeat--; 06944 } 06945 if (p->cidcwexpire) 06946 p->cidcwexpire--; 06947 /* Repeat callwaiting */ 06948 if (p->callwaitingrepeat == 1) { 06949 p->callwaitrings++; 06950 dahdi_callwait(ast); 06951 } 06952 /* Expire CID/CW */ 06953 if (p->cidcwexpire == 1) { 06954 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n"); 06955 restore_conference(p); 06956 } 06957 if (p->subs[idx].linear) { 06958 p->subs[idx].f.datalen = READ_SIZE * 2; 06959 } else 06960 p->subs[idx].f.datalen = READ_SIZE; 06961 06962 /* Handle CallerID Transmission */ 06963 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 06964 send_callerid(p); 06965 } 06966 06967 p->subs[idx].f.frametype = AST_FRAME_VOICE; 06968 p->subs[idx].f.subclass = ast->rawreadformat; 06969 p->subs[idx].f.samples = READ_SIZE; 06970 p->subs[idx].f.mallocd = 0; 06971 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET; 06972 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]); 06973 #if 0 06974 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name); 06975 #endif 06976 if (p->dialing || /* Transmitting something */ 06977 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 06978 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 06979 ) { 06980 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 06981 don't send anything */ 06982 p->subs[idx].f.frametype = AST_FRAME_NULL; 06983 p->subs[idx].f.subclass = 0; 06984 p->subs[idx].f.samples = 0; 06985 p->subs[idx].f.mallocd = 0; 06986 p->subs[idx].f.offset = 0; 06987 p->subs[idx].f.data.ptr = NULL; 06988 p->subs[idx].f.datalen= 0; 06989 } 06990 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) { 06991 /* Perform busy detection etc on the dahdi line */ 06992 int mute; 06993 06994 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f); 06995 06996 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */ 06997 mute = ast_dsp_was_muted(p->dsp); 06998 if (p->muting != mute) { 06999 p->muting = mute; 07000 dahdi_confmute(p, mute); 07001 } 07002 07003 if (f) { 07004 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 07005 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 07006 /* Treat this as a "hangup" instead of a "busy" on the assumption that 07007 a busy */ 07008 f = NULL; 07009 } 07010 } else if (f->frametype == AST_FRAME_DTMF) { 07011 #ifdef HAVE_PRI 07012 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 07013 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) || 07014 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) { 07015 /* Don't accept in-band DTMF when in overlap dial mode */ 07016 f->frametype = AST_FRAME_NULL; 07017 f->subclass = 0; 07018 } 07019 #endif 07020 /* DSP clears us of being pulse */ 07021 p->pulsedial = 0; 07022 } else if (p->waitingfordt.tv_sec) { 07023 if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) { 07024 p->waitingfordt.tv_sec = 0; 07025 ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel); 07026 f=NULL; 07027 } else if (f->frametype == AST_FRAME_VOICE) { 07028 f->frametype = AST_FRAME_NULL; 07029 f->subclass = 0; 07030 if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) { 07031 p->waitingfordt.tv_sec = 0; 07032 p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE; 07033 ast_dsp_set_features(p->dsp, p->dsp_features); 07034 ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n"); 07035 if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */ 07036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 07037 if (res < 0) { 07038 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel); 07039 p->dop.dialstr[0] = '\0'; 07040 ast_mutex_unlock(&p->lock); 07041 return NULL; 07042 } else { 07043 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 07044 p->dialing = 1; 07045 p->dop.dialstr[0] = '\0'; 07046 p->dop.op = DAHDI_DIAL_OP_REPLACE; 07047 ast_setstate(ast, AST_STATE_DIALING); 07048 } 07049 } 07050 } 07051 } 07052 } 07053 } 07054 } else 07055 f = &p->subs[idx].f; 07056 07057 if (f && (f->frametype == AST_FRAME_DTMF)) 07058 dahdi_handle_dtmfup(ast, idx, &f); 07059 07060 /* If we have a fake_event, trigger exception to handle it */ 07061 if (p->fake_event) 07062 ast_set_flag(ast, AST_FLAG_EXCEPTION); 07063 07064 ast_mutex_unlock(&p->lock); 07065 return f; 07066 }
| static struct ast_channel * dahdi_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 10834 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_TRANS_CAP_DIGITAL, ast_verbose, available(), dahdi_pvt::bearer, ast_channel::cdrflags, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::distinctivering, duplicate_pseudo(), iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::lock, dahdi_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::name, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), s, dahdi_pvt::sig, SIG_FXSKS, dahdi_pri::span, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.
Referenced by pri_dchannel().
10835 { 10836 ast_group_t groupmatch = 0; 10837 int channelmatch = -1; 10838 int roundrobin = 0; 10839 int callwait = 0; 10840 int busy = 0; 10841 struct dahdi_pvt *p; 10842 struct ast_channel *tmp = NULL; 10843 char *dest=NULL; 10844 int x; 10845 char *s; 10846 char opt=0; 10847 int res=0, y=0; 10848 int backwards = 0; 10849 #ifdef HAVE_PRI 10850 int crv; 10851 int bearer = -1; 10852 int trunkgroup; 10853 struct dahdi_pri *pri=NULL; 10854 #endif 10855 struct dahdi_pvt *exitpvt, *start, *end; 10856 ast_mutex_t *lock; 10857 int channelmatched = 0; 10858 int groupmatched = 0; 10859 10860 /* 10861 * data is ---v 10862 * Dial(DAHDI/pseudo[/extension]) 10863 * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension]) 10864 * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension]) 10865 * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension]) 10866 * 10867 * g - channel group allocation search forward 10868 * G - channel group allocation search backward 10869 * r - channel group allocation round robin search forward 10870 * R - channel group allocation round robin search backward 10871 * 10872 * c - Wait for DTMF digit to confirm answer 10873 * r<cadance#> - Set distintive ring cadance number 10874 * d - Force bearer capability for ISDN/SS7 call to digital. 10875 */ 10876 10877 /* Assume we're locking the iflock */ 10878 lock = &iflock; 10879 start = iflist; 10880 end = ifend; 10881 if (data) { 10882 dest = ast_strdupa((char *)data); 10883 } else { 10884 ast_log(LOG_WARNING, "Channel requested with no data\n"); 10885 return NULL; 10886 } 10887 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 10888 /* Retrieve the group number */ 10889 char *stringp; 10890 10891 stringp = dest + 1; 10892 s = strsep(&stringp, "/"); 10893 if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 10894 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 10895 return NULL; 10896 } 10897 groupmatch = ((ast_group_t) 1 << x); 10898 if (toupper(dest[0]) == 'G') { 10899 if (dest[0] == 'G') { 10900 backwards = 1; 10901 p = ifend; 10902 } else 10903 p = iflist; 10904 } else { 10905 if (dest[0] == 'R') { 10906 backwards = 1; 10907 p = round_robin[x]?round_robin[x]->prev:ifend; 10908 if (!p) 10909 p = ifend; 10910 } else { 10911 p = round_robin[x]?round_robin[x]->next:iflist; 10912 if (!p) 10913 p = iflist; 10914 } 10915 roundrobin = 1; 10916 } 10917 } else { 10918 char *stringp; 10919 10920 stringp = dest; 10921 s = strsep(&stringp, "/"); 10922 p = iflist; 10923 if (!strcasecmp(s, "pseudo")) { 10924 /* Special case for pseudo */ 10925 x = CHAN_PSEUDO; 10926 channelmatch = x; 10927 } 10928 #ifdef HAVE_PRI 10929 else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) { 10930 if ((trunkgroup < 1) || (crv < 1)) { 10931 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 10932 return NULL; 10933 } 10934 res--; 10935 for (x = 0; x < NUM_SPANS; x++) { 10936 if (pris[x].trunkgroup == trunkgroup) { 10937 pri = pris + x; 10938 lock = &pri->lock; 10939 start = pri->crvs; 10940 end = pri->crvend; 10941 break; 10942 } 10943 } 10944 if (!pri) { 10945 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 10946 return NULL; 10947 } 10948 channelmatch = crv; 10949 p = pris[x].crvs; 10950 } 10951 #endif 10952 else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) { 10953 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 10954 return NULL; 10955 } else { 10956 channelmatch = x; 10957 } 10958 } 10959 /* Search for an unowned channel */ 10960 ast_mutex_lock(lock); 10961 exitpvt = p; 10962 while (p && !tmp) { 10963 if (roundrobin) 10964 round_robin[x] = p; 10965 #if 0 10966 ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 10967 #endif 10968 10969 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 10970 ast_debug(1, "Using channel %d\n", p->channel); 10971 if (p->inalarm) 10972 goto next; 10973 10974 callwait = (p->owner != NULL); 10975 #ifdef HAVE_PRI 10976 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 10977 if (p->sig != SIG_FXSKS) { 10978 /* Gotta find an actual channel to use for this 10979 CRV if this isn't a callwait */ 10980 bearer = pri_find_empty_chan(pri, 0); 10981 if (bearer < 0) { 10982 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 10983 p = NULL; 10984 break; 10985 } 10986 pri_assign_bearer(p, pri, pri->pvts[bearer]); 10987 } else { 10988 if (alloc_sub(p, 0)) { 10989 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 10990 p = NULL; 10991 break; 10992 } else 10993 ast_debug(1, "Allocated placeholder pseudo channel\n"); 10994 10995 p->pri = pri; 10996 } 10997 } 10998 #endif 10999 #ifdef HAVE_OPENR2 11000 if (p->mfcr2) { 11001 ast_mutex_lock(&p->lock); 11002 if (p->mfcr2call) { 11003 ast_mutex_unlock(&p->lock); 11004 ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel); 11005 goto next; 11006 } 11007 p->mfcr2call = 1; 11008 ast_mutex_unlock(&p->lock); 11009 } 11010 #endif 11011 if (p->channel == CHAN_PSEUDO) { 11012 p = duplicate_pseudo(p); 11013 if (!p) { 11014 break; 11015 } 11016 } 11017 if (p->owner) { 11018 if (alloc_sub(p, SUB_CALLWAIT)) { 11019 p = NULL; 11020 break; 11021 } 11022 } 11023 p->outgoing = 1; 11024 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 11025 if (!tmp) { 11026 p->outgoing = 0; 11027 } 11028 #ifdef HAVE_PRI 11029 if (p->bearer) { 11030 /* Log owner to bearer channel, too */ 11031 p->bearer->owner = tmp; 11032 } 11033 #endif 11034 /* Make special notes */ 11035 if (res > 1) { 11036 if (opt == 'c') { 11037 /* Confirm answer */ 11038 p->confirmanswer = 1; 11039 } else if (opt == 'r') { 11040 /* Distinctive ring */ 11041 if (res < 3) 11042 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 11043 else 11044 p->distinctivering = y; 11045 } else if (opt == 'd') { 11046 /* If this is an ISDN call, make it digital */ 11047 p->digital = 1; 11048 if (tmp) 11049 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 11050 } else { 11051 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 11052 } 11053 } 11054 /* Note if the call is a call waiting call */ 11055 if (tmp && callwait) 11056 tmp->cdrflags |= AST_CDR_CALLWAIT; 11057 break; 11058 } 11059 next: 11060 if (backwards) { 11061 p = p->prev; 11062 if (!p) 11063 p = end; 11064 } else { 11065 p = p->next; 11066 if (!p) 11067 p = start; 11068 } 11069 /* stop when you roll to the one that we started from */ 11070 if (p == exitpvt) 11071 break; 11072 } 11073 ast_mutex_unlock(lock); 11074 restart_monitor(); 11075 if (callwait) 11076 *cause = AST_CAUSE_BUSY; 11077 else if (!tmp) { 11078 if (channelmatched) { 11079 if (busy) 11080 *cause = AST_CAUSE_BUSY; 11081 } else if (groupmatched) { 11082 *cause = AST_CAUSE_CONGESTION; 11083 } 11084 } 11085 11086 return tmp; 11087 }
| static int dahdi_restart | ( | void | ) | [static] |
Definition at line 14338 of file chan_dahdi.c.
References ast_active_channels(), ast_cond_wait(), ast_debug, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verb, dahdi_close_pri_fd(), dahdi_close_ss7_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), dahdi_ss7_error(), dahdi_ss7_message(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, linksets, lock, LOG_WARNING, dahdi_ss7::master, dahdi_pri::master, master, monlock, dahdi_pvt::next, NUM_DCHANS, 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().
14339 { 14340 #if defined(HAVE_PRI) || defined(HAVE_SS7) 14341 int i, j; 14342 #endif 14343 int cancel_code; 14344 struct dahdi_pvt *p; 14345 14346 ast_mutex_lock(&restart_lock); 14347 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n"); 14348 dahdi_softhangup_all(); 14349 ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n"); 14350 #ifdef HAVE_OPENR2 14351 dahdi_r2_destroy_links(); 14352 #endif 14353 14354 #if defined(HAVE_PRI) 14355 for (i = 0; i < NUM_SPANS; i++) { 14356 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 14357 cancel_code = pthread_cancel(pris[i].master); 14358 pthread_kill(pris[i].master, SIGURG); 14359 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 14360 pthread_join(pris[i].master, NULL); 14361 ast_debug(4, "Joined thread of span %d\n", i); 14362 } 14363 } 14364 #endif 14365 14366 #if defined(HAVE_SS7) 14367 for (i = 0; i < NUM_SPANS; i++) { 14368 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) { 14369 cancel_code = pthread_cancel(linksets[i].master); 14370 pthread_kill(linksets[i].master, SIGURG); 14371 ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code); 14372 pthread_join(linksets[i].master, NULL); 14373 ast_debug(4, "Joined thread of span %d\n", i); 14374 } 14375 } 14376 #endif 14377 14378 ast_mutex_lock(&monlock); 14379 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 14380 cancel_code = pthread_cancel(monitor_thread); 14381 pthread_kill(monitor_thread, SIGURG); 14382 ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 14383 pthread_join(monitor_thread, NULL); 14384 ast_debug(4, "Joined monitor thread\n"); 14385 } 14386 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 14387 14388 ast_mutex_lock(&ss_thread_lock); 14389 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 14390 int x = DAHDI_FLASH; 14391 ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 14392 14393 for (p = iflist; p; p = p->next) { 14394 if (p->owner) 14395 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 */ 14396 } 14397 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 14398 } 14399 14400 /* ensure any created channels before monitor threads were stopped are hungup */ 14401 dahdi_softhangup_all(); 14402 ast_verb(4, "Final softhangup of all DAHDI channels complete.\n"); 14403 destroy_all_channels(); 14404 ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 14405 14406 ast_mutex_unlock(&monlock); 14407 14408 #ifdef HAVE_PRI 14409 for (i = 0; i < NUM_SPANS; i++) { 14410 for (j = 0; j < NUM_DCHANS; j++) 14411 dahdi_close_pri_fd(&(pris[i]), j); 14412 } 14413 14414 memset(pris, 0, sizeof(pris)); 14415 for (i = 0; i < NUM_SPANS; i++) { 14416 ast_mutex_init(&pris[i].lock); 14417 pris[i].offset = -1; 14418 pris[i].master = AST_PTHREADT_NULL; 14419 for (j = 0; j < NUM_DCHANS; j++) 14420 pris[i].fds[j] = -1; 14421 } 14422 pri_set_error(dahdi_pri_error); 14423 pri_set_message(dahdi_pri_message); 14424 #endif 14425 #ifdef HAVE_SS7 14426 for (i = 0; i < NUM_SPANS; i++) { 14427 for (j = 0; j < NUM_DCHANS; j++) 14428 dahdi_close_ss7_fd(&(linksets[i]), j); 14429 } 14430 14431 memset(linksets, 0, sizeof(linksets)); 14432 for (i = 0; i < NUM_SPANS; i++) { 14433 ast_mutex_init(&linksets[i].lock); 14434 linksets[i].master = AST_PTHREADT_NULL; 14435 for (j = 0; j < NUM_DCHANS; j++) 14436 linksets[i].fds[j] = -1; 14437 } 14438 ss7_set_error(dahdi_ss7_error); 14439 ss7_set_message(dahdi_ss7_message); 14440 #endif 14441 14442 if (setup_dahdi(2) != 0) { 14443 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 14444 ast_mutex_unlock(&ss_thread_lock); 14445 return 1; 14446 } 14447 ast_mutex_unlock(&ss_thread_lock); 14448 ast_mutex_unlock(&restart_lock); 14449 return 0; 14450 }
| static char* dahdi_restart_cmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14452 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.
14453 { 14454 switch (cmd) { 14455 case CLI_INIT: 14456 e->command = "dahdi restart"; 14457 e->usage = 14458 "Usage: dahdi restart\n" 14459 " Restarts the DAHDI channels: destroys them all and then\n" 14460 " re-reads them from chan_dahdi.conf.\n" 14461 " Note that this will STOP any running CALL on DAHDI channels.\n" 14462 ""; 14463 return NULL; 14464 case CLI_GENERATE: 14465 return NULL; 14466 } 14467 if (a->argc != 2) 14468 return CLI_SHOWUSAGE; 14469 14470 if (dahdi_restart() != 0) 14471 return CLI_FAILURE; 14472 return CLI_SUCCESS; 14473 }
| static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5470 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().
05471 { 05472 int x; 05473 int res; 05474 /* Make sure our transmit state is on hook */ 05475 x = 0; 05476 x = DAHDI_ONHOOK; 05477 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05478 do { 05479 x = DAHDI_RING; 05480 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 05481 if (res) { 05482 switch (errno) { 05483 case EBUSY: 05484 case EINTR: 05485 /* Wait just in case */ 05486 usleep(10000); 05487 continue; 05488 case EINPROGRESS: 05489 res = 0; 05490 break; 05491 default: 05492 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 05493 res = 0; 05494 } 05495 } 05496 } while (res); 05497 return res; 05498 }
| static int dahdi_send_keypad_facility_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 3962 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().
03963 { 03964 /* Data will be our digit string */ 03965 struct dahdi_pvt *p; 03966 char *digits = (char *) data; 03967 03968 if (ast_strlen_zero(digits)) { 03969 ast_debug(1, "No digit string sent to application!\n"); 03970 return -1; 03971 } 03972 03973 p = (struct dahdi_pvt *)chan->tech_pvt; 03974 03975 if (!p) { 03976 ast_debug(1, "Unable to find technology private\n"); 03977 return -1; 03978 } 03979 03980 ast_mutex_lock(&p->lock); 03981 03982 if (!p->pri || !p->call) { 03983 ast_debug(1, "Unable to find pri or call on channel!\n"); 03984 ast_mutex_unlock(&p->lock); 03985 return -1; 03986 } 03987 03988 if (!pri_grab(p, p->pri)) { 03989 pri_keypad_facility(p->pri->pri, p->call, digits); 03990 pri_rel(p->pri); 03991 } else { 03992 ast_debug(1, "Unable to grab pri to send keypad facility!\n"); 03993 ast_mutex_unlock(&p->lock); 03994 return -1; 03995 } 03996 03997 ast_mutex_unlock(&p->lock); 03998 03999 return 0; 04000 }
| static int dahdi_sendtext | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 17380 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.
17381 { 17382 #define END_SILENCE_LEN 400 17383 #define HEADER_MS 50 17384 #define TRAILER_MS 5 17385 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 17386 #define ASCII_BYTES_PER_CHAR 80 17387 17388 unsigned char *buf,*mybuf; 17389 struct dahdi_pvt *p = c->tech_pvt; 17390 struct pollfd fds[1]; 17391 int size,res,fd,len,x; 17392 int bytes=0; 17393 /* Initial carrier (imaginary) */ 17394 float cr = 1.0; 17395 float ci = 0.0; 17396 float scont = 0.0; 17397 int idx; 17398 17399 idx = dahdi_get_index(c, p, 0); 17400 if (idx < 0) { 17401 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 17402 return -1; 17403 } 17404 if (!text[0]) return(0); /* if nothing to send, dont */ 17405 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 17406 if (p->mate) 17407 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 17408 else 17409 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 17410 if (!buf) 17411 return -1; 17412 mybuf = buf; 17413 if (p->mate) { 17414 int codec = AST_LAW(p); 17415 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 17416 PUT_CLID_MARKMS; 17417 } 17418 /* Put actual message */ 17419 for (x = 0; text[x]; x++) { 17420 PUT_CLID(text[x]); 17421 } 17422 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 17423 PUT_CLID_MARKMS; 17424 } 17425 len = bytes; 17426 buf = mybuf; 17427 } else { 17428 len = tdd_generate(p->tdd, buf, text); 17429 if (len < 1) { 17430 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 17431 ast_free(mybuf); 17432 return -1; 17433 } 17434 } 17435 memset(buf + len, 0x7f, END_SILENCE_LEN); 17436 len += END_SILENCE_LEN; 17437 fd = p->subs[idx].dfd; 17438 while (len) { 17439 if (ast_check_hangup(c)) { 17440 ast_free(mybuf); 17441 return -1; 17442 } 17443 size = len; 17444 if (size > READ_SIZE) 17445 size = READ_SIZE; 17446 fds[0].fd = fd; 17447 fds[0].events = POLLOUT | POLLPRI; 17448 fds[0].revents = 0; 17449 res = poll(fds, 1, -1); 17450 if (!res) { 17451 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 17452 continue; 17453 } 17454 /* if got exception */ 17455 if (fds[0].revents & POLLPRI) { 17456 ast_free(mybuf); 17457 return -1; 17458 } 17459 if (!(fds[0].revents & POLLOUT)) { 17460 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 17461 continue; 17462 } 17463 res = write(fd, buf, size); 17464 if (res != size) { 17465 if (res == -1) { 17466 ast_free(mybuf); 17467 return -1; 17468 } 17469 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 17470 break; 17471 } 17472 len -= size; 17473 buf += size; 17474 } 17475 ast_free(mybuf); 17476 return(0); 17477 }
| static char* dahdi_set_dnd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15112 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.
15113 { 15114 int channel; 15115 int on; 15116 struct dahdi_pvt *dahdi_chan = NULL; 15117 15118 switch (cmd) { 15119 case CLI_INIT: 15120 e->command = "dahdi set dnd"; 15121 e->usage = 15122 "Usage: dahdi set dnd <chan#> <on|off>\n" 15123 " Sets/resets DND (Do Not Disturb) mode on a channel.\n" 15124 " Changes take effect immediately.\n" 15125 " <chan num> is the channel number\n" 15126 " <on|off> Enable or disable DND mode?\n" 15127 ; 15128 return NULL; 15129 case CLI_GENERATE: 15130 return NULL; 15131 } 15132 15133 if (a->argc != 5) 15134 return CLI_SHOWUSAGE; 15135 15136 if ((channel = atoi(a->argv[3])) <= 0) { 15137 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]); 15138 return CLI_SHOWUSAGE; 15139 } 15140 15141 if (ast_true(a->argv[4])) 15142 on = 1; 15143 else if (ast_false(a->argv[4])) 15144 on = 0; 15145 else { 15146 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]); 15147 return CLI_SHOWUSAGE; 15148 } 15149 15150 ast_mutex_lock(&iflock); 15151 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) { 15152 if (dahdi_chan->channel != channel) 15153 continue; 15154 15155 /* Found the channel. Actually set it */ 15156 dahdi_dnd(dahdi_chan, on); 15157 break; 15158 } 15159 ast_mutex_unlock(&iflock); 15160 15161 if (!dahdi_chan) { 15162 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15163 return CLI_FAILURE; 15164 } 15165 15166 return CLI_SUCCESS; 15167 }
| static int dahdi_set_hook | ( | int | fd, | |
| int | hs | |||
| ) | [inline, static] |
Definition at line 2863 of file chan_dahdi.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), mkintf(), mwi_send_process_buffer(), mwi_send_process_event(), and ss_thread().
02864 { 02865 int x, res; 02866 02867 x = hs; 02868 res = ioctl(fd, DAHDI_HOOK, &x); 02869 02870 if (res < 0) { 02871 if (errno == EINPROGRESS) 02872 return 0; 02873 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 02874 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 02875 } 02876 02877 return res; 02878 }
| static char* dahdi_set_hwgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14969 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.
14970 { 14971 int channel; 14972 int gain; 14973 int tx; 14974 struct dahdi_hwgain hwgain; 14975 struct dahdi_pvt *tmp = NULL; 14976 14977 switch (cmd) { 14978 case CLI_INIT: 14979 e->command = "dahdi set hwgain"; 14980 e->usage = 14981 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n" 14982 " Sets the hardware gain on a a given channel, overriding the\n" 14983 " value provided at module loadtime, whether the channel is in\n" 14984 " use or not. Changes take effect immediately.\n" 14985 " <rx|tx> which direction do you want to change (relative to our module)\n" 14986 " <chan num> is the channel number relative to the device\n" 14987 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 14988 return NULL; 14989 case CLI_GENERATE: 14990 return NULL; 14991 } 14992 14993 if (a->argc != 6) 14994 return CLI_SHOWUSAGE; 14995 14996 if (!strcasecmp("rx", a->argv[3])) 14997 tx = 0; /* rx */ 14998 else if (!strcasecmp("tx", a->argv[3])) 14999 tx = 1; /* tx */ 15000 else 15001 return CLI_SHOWUSAGE; 15002 15003 channel = atoi(a->argv[4]); 15004 gain = atof(a->argv[5])*10.0; 15005 15006 ast_mutex_lock(&iflock); 15007 15008 for (tmp = iflist; tmp; tmp = tmp->next) { 15009 15010 if (tmp->channel != channel) 15011 continue; 15012 15013 if (tmp->subs[SUB_REAL].dfd == -1) 15014 break; 15015 15016 hwgain.newgain = gain; 15017 hwgain.tx = tx; 15018 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) { 15019 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno)); 15020 ast_mutex_unlock(&iflock); 15021 return CLI_FAILURE; 15022 } 15023 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n", 15024 tx ? "tx" : "rx", gain, (float)gain/10.0, channel); 15025 break; 15026 } 15027 15028 ast_mutex_unlock(&iflock); 15029 15030 if (tmp) 15031 return CLI_SUCCESS; 15032 15033 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15034 return CLI_FAILURE; 15035 15036 }
| static char* dahdi_set_swgain | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15038 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.
15039 { 15040 int channel; 15041 float gain; 15042 int tx; 15043 int res; 15044 ast_mutex_t *lock; 15045 struct dahdi_pvt *tmp = NULL; 15046 15047 switch (cmd) { 15048 case CLI_INIT: 15049 e->command = "dahdi set swgain"; 15050 e->usage = 15051 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n" 15052 " Sets the software gain on a a given channel, overriding the\n" 15053 " value provided at module loadtime, whether the channel is in\n" 15054 " use or not. Changes take effect immediately.\n" 15055 " <rx|tx> which direction do you want to change (relative to our module)\n" 15056 " <chan num> is the channel number relative to the device\n" 15057 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n"; 15058 return NULL; 15059 case CLI_GENERATE: 15060 return NULL; 15061 } 15062 15063 lock = &iflock; 15064 15065 if (a->argc != 6) 15066 return CLI_SHOWUSAGE; 15067 15068 if (!strcasecmp("rx", a->argv[3])) 15069 tx = 0; /* rx */ 15070 else if (!strcasecmp("tx", a->argv[3])) 15071 tx = 1; /* tx */ 15072 else 15073 return CLI_SHOWUSAGE; 15074 15075 channel = atoi(a->argv[4]); 15076 gain = atof(a->argv[5]); 15077 15078 ast_mutex_lock(lock); 15079 for (tmp = iflist; tmp; tmp = tmp->next) { 15080 15081 if (tmp->channel != channel) 15082 continue; 15083 15084 if (tmp->subs[SUB_REAL].dfd == -1) 15085 break; 15086 15087 if (tx) 15088 res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 15089 else 15090 res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law); 15091 15092 if (res) { 15093 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel); 15094 ast_mutex_unlock(lock); 15095 return CLI_FAILURE; 15096 } 15097 15098 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n", 15099 tx ? "tx" : "rx", gain, channel); 15100 break; 15101 } 15102 ast_mutex_unlock(lock); 15103 15104 if (tmp) 15105 return CLI_SUCCESS; 15106 15107 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 15108 return CLI_FAILURE; 15109 15110 }
| static int dahdi_setlaw | ( | int | dfd, | |
| int | law | |||
| ) | [static] |
Definition at line 11090 of file chan_dahdi.c.
Referenced by pri_dchannel(), and ss7_start_call().
11091 { 11092 return ioctl(dfd, DAHDI_SETLAW, &law); 11093 }
| static int dahdi_setlinear | ( | int | dfd, | |
| int | linear | |||
| ) | [static] |
Definition at line 2165 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 4837 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_NOTICE, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::txgain, and ast_channel_tech::type.
04838 { 04839 char *cp; 04840 signed char *scp; 04841 int x; 04842 int idx; 04843 struct dahdi_pvt *p = chan->tech_pvt, *pp; 04844 struct oprmode *oprmode; 04845 04846 04847 /* all supported options require data */ 04848 if (!data || (datalen < 1)) { 04849 errno = EINVAL; 04850 return -1; 04851 } 04852 04853 switch (option) { 04854 case AST_OPTION_TXGAIN: 04855 scp = (signed char *) data; 04856 idx = dahdi_get_index(chan, p, 0); 04857 if (idx < 0) { 04858 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 04859 return -1; 04860 } 04861 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 04862 return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law); 04863 case AST_OPTION_RXGAIN: 04864 scp = (signed char *) data; 04865 idx = dahdi_get_index(chan, p, 0); 04866 if (idx < 0) { 04867 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 04868 return -1; 04869 } 04870 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 04871 return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law); 04872 case AST_OPTION_TONE_VERIFY: 04873 if (!p->dsp) 04874 break; 04875 cp = (char *) data; 04876 switch (*cp) { 04877 case 1: 04878 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 04879 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 04880 break; 04881 case 2: 04882 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 04883 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 04884 break; 04885 default: 04886 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 04887 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 04888 break; 04889 } 04890 break; 04891 case AST_OPTION_TDD: 04892 /* turn on or off TDD */ 04893 cp = (char *) data; 04894 p->mate = 0; 04895 if (!*cp) { /* turn it off */ 04896 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 04897 if (p->tdd) 04898 tdd_free(p->tdd); 04899 p->tdd = 0; 04900 break; 04901 } 04902 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n", 04903 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 04904 dahdi_disable_ec(p); 04905 /* otherwise, turn it on */ 04906 if (!p->didtdd) { /* if havent done it yet */ 04907 unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */ 04908 unsigned char *buf; 04909 int size, res, fd, len; 04910 struct pollfd fds[1]; 04911 04912 buf = mybuf; 04913 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 04914 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 04915 len = 40000; 04916 idx = dahdi_get_index(chan, p, 0); 04917 if (idx < 0) { 04918 ast_log(LOG_WARNING, "No index in TDD?\n"); 04919 return -1; 04920 } 04921 fd = p->subs[idx].dfd; 04922 while (len) { 04923 if (ast_check_hangup(chan)) 04924 return -1; 04925 size = len; 04926 if (size > READ_SIZE) 04927 size = READ_SIZE; 04928 fds[0].fd = fd; 04929 fds[0].events = POLLPRI | POLLOUT; 04930 fds[0].revents = 0; 04931 res = poll(fds, 1, -1); 04932 if (!res) { 04933 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel); 04934 continue; 04935 } 04936 /* if got exception */ 04937 if (fds[0].revents & POLLPRI) 04938 return -1; 04939 if (!(fds[0].revents & POLLOUT)) { 04940 ast_debug(1, "write fd not ready on channel %d\n", p->channel); 04941 continue; 04942 } 04943 res = write(fd, buf, size); 04944 if (res != size) { 04945 if (res == -1) return -1; 04946 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 04947 break; 04948 } 04949 len -= size; 04950 buf += size; 04951 } 04952 p->didtdd = 1; /* set to have done it now */ 04953 } 04954 if (*cp == 2) { /* Mate mode */ 04955 if (p->tdd) 04956 tdd_free(p->tdd); 04957 p->tdd = 0; 04958 p->mate = 1; 04959 break; 04960 } 04961 if (!p->tdd) { /* if we dont have one yet */ 04962 p->tdd = tdd_new(); /* allocate one */ 04963 } 04964 break; 04965 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 04966 if (!p->dsp) 04967 break; 04968 cp = (char *) data; 04969 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n", 04970 *cp ? "ON" : "OFF", (int) *cp, chan->name); 04971 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax); 04972 break; 04973 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 04974 cp = (char *) data; 04975 if (!*cp) { 04976 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 04977 x = 0; 04978 dahdi_disable_ec(p); 04979 } else { 04980 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 04981 x = 1; 04982 } 04983 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 04984 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 04985 break; 04986 case AST_OPTION_OPRMODE: /* Operator services mode */ 04987 oprmode = (struct oprmode *) data; 04988 /* We don't support operator mode across technologies */ 04989 if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) { 04990 ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n", 04991 chan->tech->type, oprmode->peer->tech->type); 04992 errno = EINVAL; 04993 return -1; 04994 } 04995 pp = oprmode->peer->tech_pvt; 04996 p->oprmode = pp->oprmode = 0; 04997 /* setup peers */ 04998 p->oprpeer = pp; 04999 pp->oprpeer = p; 05000 /* setup modes, if any */ 05001 if (oprmode->mode) 05002 { 05003 pp->oprmode = oprmode->mode; 05004 p->oprmode = -oprmode->mode; 05005 } 05006 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n", 05007 oprmode->mode, chan->name,oprmode->peer->name); 05008 break; 05009 case AST_OPTION_ECHOCAN: 05010 cp = (char *) data; 05011 if (*cp) { 05012 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name); 05013 dahdi_enable_ec(p); 05014 } else { 05015 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name); 05016 dahdi_disable_ec(p); 05017 } 05018 break; 05019 } 05020 errno = 0; 05021 05022 return 0; 05023 }
| static char* dahdi_show_channel | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14609 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_channel::name, ast_variable::name, dahdi_pvt::next, ast_variable::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::pri, dahdi_pri::pri, pris, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::resetting, S_OR, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, dahdi_pvt::ss7, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
14610 { 14611 int channel; 14612 struct dahdi_pvt *tmp = NULL; 14613 struct dahdi_confinfo ci; 14614 struct dahdi_params ps; 14615 int x; 14616 ast_mutex_t *lock; 14617 struct dahdi_pvt *start; 14618 #ifdef HAVE_PRI 14619 char *c; 14620 int trunkgroup; 14621 struct dahdi_pri *pri=NULL; 14622 #endif 14623 switch (cmd) { 14624 case CLI_INIT: 14625 e->command = "dahdi show channel"; 14626 e->usage = 14627 "Usage: dahdi show channel <chan num>\n" 14628 " Detailed information about a given channel\n"; 14629 return NULL; 14630 case CLI_GENERATE: 14631 return NULL; 14632 } 14633 14634 lock = &iflock; 14635 start = iflist; 14636 14637 if (a->argc != 4) 14638 return CLI_SHOWUSAGE; 14639 #ifdef HAVE_PRI 14640 if ((c = strchr(a->argv[3], ':'))) { 14641 if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2) 14642 return CLI_SHOWUSAGE; 14643 if ((trunkgroup < 1) || (channel < 1)) 14644 return CLI_SHOWUSAGE; 14645 for (x = 0; x < NUM_SPANS; x++) { 14646 if (pris[x].trunkgroup == trunkgroup) { 14647 pri = pris + x; 14648 break; 14649 } 14650 } 14651 if (pri) { 14652 start = pri->crvs; 14653 lock = &pri->lock; 14654 } else { 14655 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 14656 return CLI_FAILURE; 14657 } 14658 } else 14659 #endif 14660 channel = atoi(a->argv[3]); 14661 14662 ast_mutex_lock(lock); 14663 tmp = start; 14664 while (tmp) { 14665 if (tmp->channel == channel) { 14666 #ifdef HAVE_PRI 14667 if (pri) 14668 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 14669 else 14670 #endif 14671 ast_cli(a->fd, "Channel: %d\n", tmp->channel); 14672 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 14673 ast_cli(a->fd, "Span: %d\n", tmp->span); 14674 ast_cli(a->fd, "Extension: %s\n", tmp->exten); 14675 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 14676 ast_cli(a->fd, "Context: %s\n", tmp->context); 14677 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num); 14678 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton); 14679 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name); 14680 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none")); 14681 if (tmp->vars) { 14682 struct ast_variable *v; 14683 ast_cli(a->fd, "Variables:\n"); 14684 for (v = tmp->vars ; v ; v = v->next) 14685 ast_cli(a->fd, " %s = %s\n", v->name, v->value); 14686 } 14687 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy); 14688 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm); 14689 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 14690 ast_cli(a->fd, "Radio: %d\n", tmp->radio); 14691 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 14692 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)" : ""); 14693 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)" : ""); 14694 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)" : ""); 14695 ast_cli(a->fd, "Confno: %d\n", tmp->confno); 14696 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno); 14697 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference); 14698 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 14699 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no"); 14700 if (tmp->busydetect) { 14701 #if defined(BUSYDETECT_TONEONLY) 14702 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n"); 14703 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE) 14704 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n"); 14705 #endif 14706 #ifdef BUSYDETECT_DEBUG 14707 ast_cli(a->fd, " Busy Detector Debug: Enabled\n"); 14708 #endif 14709 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount); 14710 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength); 14711 } 14712 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no"); 14713 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 14714 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 14715 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 14716 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 14717 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 14718 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no"); 14719 ast_cli(a->fd, "Echo Cancellation:\n"); 14720 14721 if (tmp->echocancel.head.tap_length) { 14722 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length); 14723 for (x = 0; x < tmp->echocancel.head.param_count; x++) { 14724 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value); 14725 } 14726 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF"); 14727 } else { 14728 ast_cli(a->fd, "\tnone\n"); 14729 } 14730 ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone); 14731 if (tmp->master) 14732 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel); 14733 for (x = 0; x < MAX_SLAVES; x++) { 14734 if (tmp->slaves[x]) 14735 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 14736 } 14737 #ifdef HAVE_OPENR2 14738 if (tmp->mfcr2) { 14739 char calldir[OR2_MAX_PATH]; 14740 openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan); 14741 openr2_variant_t r2variant = openr2_context_get_variant(r2context); 14742 ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan)); 14743 ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan)); 14744 ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan)); 14745 ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan)); 14746 ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No"); 14747 ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant)); 14748 ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context)); 14749 ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context)); 14750 ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No"); 14751 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1 14752 ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No"); 14753 #endif 14754 ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No"); 14755 ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No"); 14756 ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No"); 14757 ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No"); 14758 ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No"); 14759 ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context)); 14760 ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context)); 14761 ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan)); 14762 ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan)); 14763 ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan)); 14764 ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan)); 14765 ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir))); 14766 } 14767 #endif 14768 #ifdef HAVE_SS7 14769 if (tmp->ss7) { 14770 ast_cli(a->fd, "CIC: %d\n", tmp->cic); 14771 } 14772 #endif 14773 #ifdef HAVE_PRI 14774 if (tmp->pri) { 14775 ast_cli(a->fd, "PRI Flags: "); 14776 if (tmp->resetting) 14777 ast_cli(a->fd, "Resetting "); 14778 if (tmp->call) 14779 ast_cli(a->fd, "Call "); 14780 if (tmp->bearer) 14781 ast_cli(a->fd, "Bearer "); 14782 ast_cli(a->fd, "\n"); 14783 if (tmp->logicalspan) 14784 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan); 14785 else 14786 ast_cli(a->fd, "PRI Logical Span: Implicit\n"); 14787 } 14788 #endif 14789 memset(&ci, 0, sizeof(ci)); 14790 ps.channo = tmp->channel; 14791 if (tmp->subs[SUB_REAL].dfd > -1) { 14792 memset(&ci, 0, sizeof(ci)); 14793 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 14794 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 14795 } 14796 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 14797 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 14798 } 14799 memset(&ps, 0, sizeof(ps)); 14800 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 14801 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 14802 } else { 14803 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 14804 } 14805 } 14806 ast_mutex_unlock(lock); 14807 return CLI_SUCCESS; 14808 } 14809 tmp = tmp->next; 14810 } 14811 14812 ast_cli(a->fd, "Unable to find given channel %d\n", channel); 14813 ast_mutex_unlock(lock); 14814 return CLI_FAILURE; 14815 }
| static char* dahdi_show_channels | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14485 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, dahdi_pri::pri, pris, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.
14486 { 14487 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 14488 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n" 14489 unsigned int targetnum = 0; 14490 int filtertype = 0; 14491 struct dahdi_pvt *tmp = NULL; 14492 char tmps[20] = ""; 14493 char statestr[20] = ""; 14494 char blockstr[20] = ""; 14495 ast_mutex_t *lock; 14496 struct dahdi_pvt *start; 14497 #ifdef HAVE_PRI 14498 int trunkgroup; 14499 struct dahdi_pri *pri = NULL; 14500 int x; 14501 #endif 14502 switch (cmd) { 14503 case CLI_INIT: 14504 e->command = "dahdi show channels [trunkgroup|group|context]"; 14505 e->usage = 14506 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n" 14507 " Shows a list of available channels with optional filtering\n" 14508 " <group> must be a number between 0 and 63\n"; 14509 return NULL; 14510 case CLI_GENERATE: 14511 return NULL; 14512 } 14513 14514 lock = &iflock; 14515 start = iflist; 14516 14517 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */ 14518 14519 if (!((a->argc == 3) || (a->argc == 5))) 14520 return CLI_SHOWUSAGE; 14521 14522 if (a->argc == 5) { 14523 #ifdef HAVE_PRI 14524 if (!strcasecmp(a->argv[3], "trunkgroup")) { 14525 /* this option requires no special handling, so leave filtertype to zero */ 14526 if ((trunkgroup = atoi(a->argv[4])) < 1) 14527 return CLI_SHOWUSAGE; 14528 for (x = 0; x < NUM_SPANS; x++) { 14529 if (pris[x].trunkgroup == trunkgroup) { 14530 pri = pris + x; 14531 break; 14532 } 14533 } 14534 if (pri) { 14535 start = pri->crvs; 14536 lock = &pri->lock; 14537 } else { 14538 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup); 14539 return CLI_FAILURE; 14540 } 14541 } else 14542 #endif 14543 if (!strcasecmp(a->argv[3], "group")) { 14544 targetnum = atoi(a->argv[4]); 14545 if ((targetnum < 0) || (targetnum > 63)) 14546 return CLI_SHOWUSAGE; 14547 targetnum = 1 << targetnum; 14548 filtertype = 1; 14549 } else if (!strcasecmp(a->argv[3], "context")) { 14550 filtertype = 2; 14551 } 14552 } 14553 14554 ast_mutex_lock(lock); 14555 #ifdef HAVE_PRI 14556 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 14557 #else 14558 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State"); 14559 #endif 14560 14561 tmp = start; 14562 while (tmp) { 14563 if (filtertype) { 14564 switch(filtertype) { 14565 case 1: /* dahdi show channels group <group> */ 14566 if (!(tmp->group & targetnum)) { 14567 tmp = tmp->next; 14568 continue; 14569 } 14570 break; 14571 case 2: /* dahdi show channels context <context> */ 14572 if (strcasecmp(tmp->context, a->argv[4])) { 14573 tmp = tmp->next; 14574 continue; 14575 } 14576 break; 14577 default: 14578 ; 14579 } 14580 } 14581 if (tmp->channel > 0) { 14582 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 14583 } else 14584 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 14585 14586 if (tmp->locallyblocked) 14587 blockstr[0] = 'L'; 14588 else 14589 blockstr[0] = ' '; 14590 14591 if (tmp->remotelyblocked) 14592 blockstr[1] = 'R'; 14593 else 14594 blockstr[1] = ' '; 14595 14596 blockstr[2] = '\0'; 14597 14598 snprintf(statestr, sizeof(statestr), "%s", "In Service"); 14599 14600 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr); 14601 tmp = tmp->next; 14602 } 14603 ast_mutex_unlock(lock); 14604 return CLI_SUCCESS; 14605 #undef FORMAT 14606 #undef FORMAT2 14607 }
| static char* dahdi_show_status | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14854 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.
14855 { 14856 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n" 14857 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n" 14858 int span; 14859 int res; 14860 char alarmstr[50]; 14861 14862 int ctl; 14863 struct dahdi_spaninfo s; 14864 14865 switch (cmd) { 14866 case CLI_INIT: 14867 e->command = "dahdi show status"; 14868 e->usage = 14869 "Usage: dahdi show status\n" 14870 " Shows a list of DAHDI cards with status\n"; 14871 return NULL; 14872 case CLI_GENERATE: 14873 return NULL; 14874 } 14875 ctl = open("/dev/dahdi/ctl", O_RDWR); 14876 if (ctl < 0) { 14877 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 14878 return CLI_FAILURE; 14879 } 14880 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO"); 14881 14882 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 14883 s.spanno = span; 14884 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 14885 if (res) { 14886 continue; 14887 } 14888 alarmstr[0] = '\0'; 14889 if (s.alarms > 0) { 14890 if (s.alarms & DAHDI_ALARM_BLUE) 14891 strcat(alarmstr, "BLU/"); 14892 if (s.alarms & DAHDI_ALARM_YELLOW) 14893 strcat(alarmstr, "YEL/"); 14894 if (s.alarms & DAHDI_ALARM_RED) 14895 strcat(alarmstr, "RED/"); 14896 if (s.alarms & DAHDI_ALARM_LOOPBACK) 14897 strcat(alarmstr, "LB/"); 14898 if (s.alarms & DAHDI_ALARM_RECOVER) 14899 strcat(alarmstr, "REC/"); 14900 if (s.alarms & DAHDI_ALARM_NOTOPEN) 14901 strcat(alarmstr, "NOP/"); 14902 if (!strlen(alarmstr)) 14903 strcat(alarmstr, "UUU/"); 14904 if (strlen(alarmstr)) { 14905 /* Strip trailing / */ 14906 alarmstr[strlen(alarmstr) - 1] = '\0'; 14907 } 14908 } else { 14909 if (s.numchans) 14910 strcpy(alarmstr, "OK"); 14911 else 14912 strcpy(alarmstr, "UNCONFIGURED"); 14913 } 14914 14915 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count, 14916 s.lineconfig & DAHDI_CONFIG_D4 ? "D4" : 14917 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" : 14918 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" : 14919 "CAS", 14920 s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" : 14921 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" : 14922 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" : 14923 "Unk", 14924 s.lineconfig & DAHDI_CONFIG_CRC4 ? 14925 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL", 14926 lbostr[s.lbo] 14927 ); 14928 } 14929 close(ctl); 14930 14931 return CLI_SUCCESS; 14932 #undef FORMAT 14933 #undef FORMAT2 14934 }
| static char* dahdi_show_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14936 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.
14937 { 14938 int pseudo_fd = -1; 14939 struct dahdi_versioninfo vi; 14940 14941 switch (cmd) { 14942 case CLI_INIT: 14943 e->command = "dahdi show version"; 14944 e->usage = 14945 "Usage: dahdi show version\n" 14946 " Shows the DAHDI version in use\n"; 14947 return NULL; 14948 case CLI_GENERATE: 14949 return NULL; 14950 } 14951 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) { 14952 ast_cli(a->fd, "Failed to open control file to get version.\n"); 14953 return CLI_SUCCESS; 14954 } 14955 14956 strcpy(vi.version, "Unknown"); 14957 strcpy(vi.echo_canceller, "Unknown"); 14958 14959 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi)) 14960 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno)); 14961 else 14962 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller); 14963 14964 close(pseudo_fd); 14965 14966 return CLI_SUCCESS; 14967 }
| static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 2408 of file chan_dahdi.c.
References buf, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, and SIG_SS7.
02409 { 02410 static char buf[256]; 02411 switch (sig) { 02412 case SIG_EM: 02413 return "E & M Immediate"; 02414 case SIG_EMWINK: 02415 return "E & M Wink"; 02416 case SIG_EM_E1: 02417 return "E & M E1"; 02418 case SIG_FEATD: 02419 return "Feature Group D (DTMF)"; 02420 case SIG_FEATDMF: 02421 return "Feature Group D (MF)"; 02422 case SIG_FEATDMF_TA: 02423 return "Feature Groud D (MF) Tandem Access"; 02424 case SIG_FEATB: 02425 return "Feature Group B (MF)"; 02426 case SIG_E911: 02427 return "E911 (MF)"; 02428 case SIG_FGC_CAMA: 02429 return "FGC/CAMA (Dialpulse)"; 02430 case SIG_FGC_CAMAMF: 02431 return "FGC/CAMA (MF)"; 02432 case SIG_FXSLS: 02433 return "FXS Loopstart"; 02434 case SIG_FXSGS: 02435 return "FXS Groundstart"; 02436 case SIG_FXSKS: 02437 return "FXS Kewlstart"; 02438 case SIG_FXOLS: 02439 return "FXO Loopstart"; 02440 case SIG_FXOGS: 02441 return "FXO Groundstart"; 02442 case SIG_FXOKS: 02443 return "FXO Kewlstart"; 02444 case SIG_PRI: 02445 return "ISDN PRI"; 02446 case SIG_BRI: 02447 return "ISDN BRI Point to Point"; 02448 case SIG_BRI_PTMP: 02449 return "ISDN BRI Point to MultiPoint"; 02450 case SIG_SS7: 02451 return "SS7"; 02452 case SIG_MFCR2: 02453 return "MFC/R2"; 02454 case SIG_SF: 02455 return "SF (Tone) Immediate"; 02456 case SIG_SFWINK: 02457 return "SF (Tone) Wink"; 02458 case SIG_SF_FEATD: 02459 return "SF (Tone) with Feature Group D (DTMF)"; 02460 case SIG_SF_FEATDMF: 02461 return "SF (Tone) with Feature Group D (MF)"; 02462 case SIG_SF_FEATB: 02463 return "SF (Tone) with Feature Group B (MF)"; 02464 case SIG_GR303FXOKS: 02465 return "GR-303 with FXOKS"; 02466 case SIG_GR303FXSKS: 02467 return "GR-303 with FXSKS"; 02468 case 0: 02469 return "Pseudo"; 02470 default: 02471 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 02472 return buf; 02473 } 02474 }
| static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 14309 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_verbose, iflist, iflock, dahdi_pvt::lock, ast_channel::name, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.
Referenced by dahdi_restart().
14310 { 14311 struct dahdi_pvt *p; 14312 retry: 14313 ast_mutex_lock(&iflock); 14314 for (p = iflist; p; p = p->next) { 14315 ast_mutex_lock(&p->lock); 14316 if (p->owner && !p->restartpending) { 14317 if (ast_channel_trylock(p->owner)) { 14318 if (option_debug > 2) 14319 ast_verbose("Avoiding deadlock\n"); 14320 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 14321 ast_mutex_unlock(&p->lock); 14322 ast_mutex_unlock(&iflock); 14323 goto retry; 14324 } 14325 if (option_debug > 2) 14326 ast_verbose("Softhanging up on %s\n", p->owner->name); 14327 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 14328 p->restartpending = 1; 14329 num_restart_pending++; 14330 ast_channel_unlock(p->owner); 14331 } 14332 ast_mutex_unlock(&p->lock); 14333 } 14334 ast_mutex_unlock(&iflock); 14335 }
| static void dahdi_ss7_error | ( | struct ss7 * | ss7, | |
| char * | s | |||
| ) | [static] |
Definition at line 11939 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 11922 of file chan_dahdi.c.
References ast_verbose, linksets, and NUM_SPANS.
Referenced by dahdi_restart(), and load_module().
11923 { 11924 #if 0 11925 int i; 11926 11927 for (i = 0; i < NUM_SPANS; i++) 11928 if (linksets[i].ss7 == ss7) 11929 break; 11930 11931 ast_verbose("[%d] %s", i+1, s); 11932 #else 11933 ast_verbose("%s", s); 11934 #endif 11935 }
| static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2692 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().
02693 { 02694 int x; 02695 int res; 02696 02697 if (p && p->echocanon && p->echotraining) { 02698 x = p->echotraining; 02699 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 02700 if (res) 02701 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 02702 else 02703 ast_debug(1, "Engaged echo training on channel %d\n", p->channel); 02704 } else { 02705 ast_debug(1, "No echo training requested\n"); 02706 } 02707 }
| static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
| struct dahdi_pvt * | master, | |||
| int | needlock | |||
| ) | [static] |
Definition at line 5044 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().
05045 { 05046 /* Unlink a specific slave or all slaves/masters from a given master */ 05047 int x; 05048 int hasslaves; 05049 if (!master) 05050 return; 05051 if (needlock) { 05052 ast_mutex_lock(&master->lock); 05053 if (slave) { 05054 while (ast_mutex_trylock(&slave->lock)) { 05055 DEADLOCK_AVOIDANCE(&master->lock); 05056 } 05057 } 05058 } 05059 hasslaves = 0; 05060 for (x = 0; x < MAX_SLAVES; x++) { 05061 if (master->slaves[x]) { 05062 if (!slave || (master->slaves[x] == slave)) { 05063 /* Take slave out of the conference */ 05064 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 05065 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 05066 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 05067 master->slaves[x]->master = NULL; 05068 master->slaves[x] = NULL; 05069 } else 05070 hasslaves = 1; 05071 } 05072 if (!hasslaves) 05073 master->inconference = 0; 05074 } 05075 if (!slave) { 05076 if (master->master) { 05077 /* Take master out of the conference */ 05078 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 05079 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 05080 hasslaves = 0; 05081 for (x = 0; x < MAX_SLAVES; x++) { 05082 if (master->master->slaves[x] == master) 05083 master->master->slaves[x] = NULL; 05084 else if (master->master->slaves[x]) 05085 hasslaves = 1; 05086 } 05087 if (!hasslaves) 05088 master->master->inconference = 0; 05089 } 05090 master->master = NULL; 05091 } 05092 update_conf(master); 05093 if (needlock) { 05094 if (slave) 05095 ast_mutex_unlock(&slave->lock); 05096 ast_mutex_unlock(&master->lock); 05097 } 05098 }
| static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 385 of file chan_dahdi.c.
Referenced by ss_thread().
| static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
| int | idx | |||
| ) | [static] |
Definition at line 7635 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
07636 { 07637 int j; 07638 dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK); 07639 for (;;) 07640 { 07641 /* set bits of interest */ 07642 j = DAHDI_IOMUX_SIGEVENT; 07643 /* wait for some happening */ 07644 if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 07645 /* exit loop if we have it */ 07646 if (j & DAHDI_IOMUX_SIGEVENT) break; 07647 } 07648 /* get the event info */ 07649 if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 07650 return 0; 07651 }
| static int dahdi_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | frame | |||
| ) | [static] |
Definition at line 7090 of file chan_dahdi.c.
References ast_debug, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, errno, ast_frame::frametype, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, my_dahdi_write(), ast_channel::name, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, ast_frame::ptr, PVT_TO_CHANNEL, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
07091 { 07092 struct dahdi_pvt *p = ast->tech_pvt; 07093 int res; 07094 int idx; 07095 idx = dahdi_get_index(ast, p, 0); 07096 if (idx < 0) { 07097 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 07098 return -1; 07099 } 07100 07101 #if 0 07102 #ifdef HAVE_PRI 07103 ast_mutex_lock(&p->lock); 07104 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 07105 if (p->pri->pri) { 07106 if (!pri_grab(p, p->pri)) { 07107 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 07108 pri_rel(p->pri); 07109 } else 07110 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07111 } 07112 p->proceeding=1; 07113 } 07114 ast_mutex_unlock(&p->lock); 07115 #endif 07116 #endif 07117 /* Write a frame of (presumably voice) data */ 07118 if (frame->frametype != AST_FRAME_VOICE) { 07119 if (frame->frametype != AST_FRAME_IMAGE) 07120 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 07121 return 0; 07122 } 07123 if ((frame->subclass != AST_FORMAT_SLINEAR) && 07124 (frame->subclass != AST_FORMAT_ULAW) && 07125 (frame->subclass != AST_FORMAT_ALAW)) { 07126 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 07127 return -1; 07128 } 07129 if (p->dialing) { 07130 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); 07131 return 0; 07132 } 07133 if (!p->owner) { 07134 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name); 07135 return 0; 07136 } 07137 if (p->cidspill) { 07138 ast_debug(1, "Dropping frame since I've still got a callerid spill\n"); 07139 return 0; 07140 } 07141 /* Return if it's not valid data */ 07142 if (!frame->data.ptr || !frame->datalen) 07143 return 0; 07144 07145 if (frame->subclass == AST_FORMAT_SLINEAR) { 07146 if (!p->subs[idx].linear) { 07147 p->subs[idx].linear = 1; 07148 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07149 if (res) 07150 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 07151 } 07152 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1); 07153 } else { 07154 /* x-law already */ 07155 if (p->subs[idx].linear) { 07156 p->subs[idx].linear = 0; 07157 res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 07158 if (res) 07159 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 07160 } 07161 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0); 07162 } 07163 if (res < 0) { 07164 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 07165 return -1; 07166 } 07167 return 0; 07168 }
| static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 3929 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().
03930 { 03931 int x; 03932 struct dahdi_pvt *p, *pl; 03933 03934 while (num_restart_pending) { 03935 usleep(1); 03936 } 03937 03938 ast_mutex_lock(&iflock); 03939 /* Destroy all the interfaces and free their memory */ 03940 p = iflist; 03941 while (p) { 03942 /* Free any callerid */ 03943 if (p->cidspill) 03944 ast_free(p->cidspill); 03945 pl = p; 03946 p = p->next; 03947 x = pl->channel; 03948 /* Free associated memory */ 03949 if (pl) 03950 destroy_dahdi_pvt(&pl); 03951 if (option_verbose > 2) 03952 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 03953 } 03954 iflist = NULL; 03955 ifcount = 0; 03956 ast_mutex_unlock(&iflock); 03957 }
Definition at line 3879 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().
03880 { 03881 int owned = 0; 03882 int i = 0; 03883 03884 if (!now) { 03885 if (cur->owner) { 03886 owned = 1; 03887 } 03888 03889 for (i = 0; i < 3; i++) { 03890 if (cur->subs[i].owner) { 03891 owned = 1; 03892 } 03893 } 03894 if (!owned) { 03895 if (prev) { 03896 prev->next = cur->next; 03897 if (prev->next) 03898 prev->next->prev = prev; 03899 else 03900 ifend = prev; 03901 } else { 03902 iflist = cur->next; 03903 if (iflist) 03904 iflist->prev = NULL; 03905 else 03906 ifend = NULL; 03907 } 03908 destroy_dahdi_pvt(&cur); 03909 } 03910 } else { 03911 if (prev) { 03912 prev->next = cur->next; 03913 if (prev->next) 03914 prev->next->prev = prev; 03915 else 03916 ifend = prev; 03917 } else { 03918 iflist = cur->next; 03919 if (iflist) 03920 iflist->prev = NULL; 03921 else 03922 ifend = NULL; 03923 } 03924 destroy_dahdi_pvt(&cur); 03925 } 03926 return 0; 03927 }
| static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 3856 of file chan_dahdi.c.
References ast_event_unsubscribe(), ast_mutex_destroy(), ast_smdi_interface_unref(), ast_variables_destroy(), dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::mwi_event_sub, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, dahdi_pvt::use_smdi, and dahdi_pvt::vars.
Referenced by destroy_all_channels(), destroy_channel(), duplicate_pseudo(), and mkintf().
03857 { 03858 struct dahdi_pvt *p = *pvt; 03859 /* Remove channel from the list */ 03860 if (p->prev) 03861 p->prev->next = p->next; 03862 if (p->next) 03863 p->next->prev = p->prev; 03864 if (p->use_smdi) 03865 ast_smdi_interface_unref(p->smdi_iface); 03866 if (p->mwi_event_sub) 03867 ast_event_unsubscribe(p->mwi_event_sub); 03868 if (p->vars) { 03869 ast_variables_destroy(p->vars); 03870 } 03871 ast_mutex_destroy(&p->lock); 03872 dahdi_close_sub(p, SUB_REAL); 03873 if (p->owner) 03874 p->owner->tech_pvt = NULL; 03875 free(p); 03876 *pvt = NULL; 03877 }
| static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 2399 of file chan_dahdi.c.
Referenced by dahdi_call(), and mkintf().
| static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 2229 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
02230 { 02231 if (isdigit(digit)) 02232 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 02233 else if (digit >= 'A' && digit <= 'D') 02234 return DAHDI_TONE_DTMF_A + (digit - 'A'); 02235 else if (digit >= 'a' && digit <= 'd') 02236 return DAHDI_TONE_DTMF_A + (digit - 'a'); 02237 else if (digit == '*') 02238 return DAHDI_TONE_DTMF_s; 02239 else if (digit == '#') 02240 return DAHDI_TONE_DTMF_p; 02241 else 02242 return -1; 02243 }
| static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5123 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().
05124 { 05125 int val; 05126 05127 p->ignoredtmf = 1; 05128 05129 val = 0; 05130 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 05131 05132 if (!p->hardwaredtmf && p->dsp) { 05133 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT; 05134 ast_dsp_set_features(p->dsp, p->dsp_features); 05135 } 05136 }
| static void* do_idle_thread | ( | void * | vchan | ) | [static] |
Definition at line 12162 of file chan_dahdi.c.
References ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_verb, ast_waitfor(), dahdi_pvt::channel, ast_channel::context, ast_channel::exten, ast_frame::frametype, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, LOG_WARNING, ast_channel::name, dahdi_pvt::pri, ast_channel::priority, ast_frame::subclass, and ast_channel::tech_pvt.
Referenced by pri_dchannel().
12163 { 12164 struct ast_channel *chan = vchan; 12165 struct dahdi_pvt *pvt = chan->tech_pvt; 12166 struct ast_frame *f; 12167 char ex[80]; 12168 /* Wait up to 30 seconds for an answer */ 12169 int newms, ms = 30000; 12170 ast_verb(3, "Initiating idle call on channel %s\n", chan->name); 12171 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial); 12172 if (ast_call(chan, ex, 0)) { 12173 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex); 12174 ast_hangup(chan); 12175 return NULL; 12176 } 12177 while ((newms = ast_waitfor(chan, ms)) > 0) { 12178 f = ast_read(chan); 12179 if (!f) { 12180 /* Got hangup */ 12181 break; 12182 } 12183 if (f->frametype == AST_FRAME_CONTROL) { 12184 switch (f->subclass) { 12185 case AST_CONTROL_ANSWER: 12186 /* Launch the PBX */ 12187 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten)); 12188 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context)); 12189 chan->priority = 1; 12190 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context); 12191 ast_pbx_run(chan); 12192 /* It's already hungup, return immediately */ 12193 return NULL; 12194 case AST_CONTROL_BUSY: 12195 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name); 12196 break; 12197 case AST_CONTROL_CONGESTION: 12198 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name); 12199 break; 12200 }; 12201 } 12202 ast_frfree(f); 12203 ms = newms; 12204 } 12205 /* Hangup the channel since nothing happend */ 12206 ast_hangup(chan); 12207 return NULL; 12208 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 9496 of file chan_dahdi.c.
References ast_calloc, ast_debug, ast_fdisset(), ast_free, AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, ast_strlen_zero(), mwi_thread_data::buf, buf, calc_energy(), dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_get_event(), dahdi_subchannel::dfd, errno, event2str(), dahdi_pvt::fxsoffhookstate, handle_init_event(), has_voicemail(), iflist, iflock, last, mwi_thread_data::len, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::msgstate, mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, mwi_thread_data::pvt, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
09497 { 09498 int count, res, res2, spoint, pollres=0; 09499 struct dahdi_pvt *i; 09500 struct dahdi_pvt *last = NULL; 09501 struct dahdi_pvt *doomed; 09502 time_t thispass = 0, lastpass = 0; 09503 int found; 09504 char buf[1024]; 09505 struct pollfd *pfds=NULL; 09506 int lastalloc = -1; 09507 /* This thread monitors all the frame relay interfaces which are not yet in use 09508 (and thus do not have a separate thread) indefinitely */ 09509 /* From here on out, we die whenever asked */ 09510 #if 0 09511 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 09512 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 09513 return NULL; 09514 } 09515 ast_debug(1, "Monitor starting...\n"); 09516 #endif 09517 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 09518 09519 for (;;) { 09520 /* Lock the interface list */ 09521 ast_mutex_lock(&iflock); 09522 if (!pfds || (lastalloc != ifcount)) { 09523 if (pfds) { 09524 ast_free(pfds); 09525 pfds = NULL; 09526 } 09527 if (ifcount) { 09528 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 09529 ast_mutex_unlock(&iflock); 09530 return NULL; 09531 } 09532 } 09533 lastalloc = ifcount; 09534 } 09535 /* Build the stuff we're going to poll on, that is the socket of every 09536 dahdi_pvt that does not have an associated owner channel */ 09537 count = 0; 09538 i = iflist; 09539 while (i) { 09540 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) { 09541 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) { 09542 /* This needs to be watched, as it lacks an owner */ 09543 pfds[count].fd = i->subs[SUB_REAL].dfd; 09544 pfds[count].events = POLLPRI; 09545 pfds[count].revents = 0; 09546 /* If we are monitoring for VMWI or sending CID, we need to 09547 read from the channel as well */ 09548 if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk) 09549 pfds[count].events |= POLLIN; 09550 count++; 09551 } 09552 } 09553 i = i->next; 09554 } 09555 /* Okay, now that we know what to do, release the interface lock */ 09556 ast_mutex_unlock(&iflock); 09557 09558 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 09559 pthread_testcancel(); 09560 /* Wait at least a second for something to happen */ 09561 res = poll(pfds, count, 1000); 09562 pthread_testcancel(); 09563 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 09564 09565 /* Okay, poll has finished. Let's see what happened. */ 09566 if (res < 0) { 09567 if ((errno != EAGAIN) && (errno != EINTR)) 09568 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 09569 continue; 09570 } 09571 /* Alright, lock the interface list again, and let's look and see what has 09572 happened */ 09573 ast_mutex_lock(&iflock); 09574 found = 0; 09575 spoint = 0; 09576 lastpass = thispass; 09577 thispass = time(NULL); 09578 i = iflist; 09579 doomed = NULL; 09580 for (i = iflist;; i = i->next) { 09581 if (doomed) { 09582 int res; 09583 res = dahdi_destroy_channel_bynum(doomed->channel); 09584 if (!res) { 09585 ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n"); 09586 } 09587 doomed = NULL; 09588 } 09589 if (!i) { 09590 break; 09591 } 09592 09593 if (thispass != lastpass) { 09594 if (!found && ((i == last) || ((i == iflist) && !last))) { 09595 last = i; 09596 if (last) { 09597 /* Only allow MWI to be initiated on a quiescent fxs port */ 09598 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO && 09599 !last->fxsoffhookstate && !last->owner && 09600 !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) { 09601 res = has_voicemail(last); 09602 if (last->msgstate != res) { 09603 /* Set driver resources for signalling VMWI */ 09604 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); 09605 if (res2) { 09606 /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */ 09607 ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno)); 09608 } 09609 /* If enabled for FSK spill then initiate it */ 09610 if (mwi_send_init(last)) { 09611 ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel); 09612 } 09613 last->msgstate = res; 09614 found ++; 09615 } 09616 } 09617 last = last->next; 09618 } 09619 } 09620 } 09621 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 09622 if (i->radio && !i->owner) 09623 { 09624 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 09625 if (res) 09626 { 09627 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 09628 /* Don't hold iflock while handling init events */ 09629 ast_mutex_unlock(&iflock); 09630 doomed = handle_init_event(i, res); 09631 ast_mutex_lock(&iflock); 09632 } 09633 continue; 09634 } 09635 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 09636 if (pollres & POLLIN) { 09637 if (i->owner || i->subs[SUB_REAL].owner) { 09638 #ifdef HAVE_PRI 09639 if (!i->pri) 09640 #endif 09641 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 09642 continue; 09643 } 09644 if (!i->mwimonitor_fsk && !i->mwisendactive) { 09645 ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd); 09646 continue; 09647 } 09648 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 09649 if (res > 0) { 09650 if (i->mwimonitor_fsk) { 09651 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) { 09652 pthread_attr_t attr; 09653 pthread_t threadid; 09654 struct mwi_thread_data *mtd; 09655 09656 pthread_attr_init(&attr); 09657 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 09658 09659 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel); 09660 if ((mtd = ast_calloc(1, sizeof(*mtd)))) { 09661 mtd->pvt = i; 09662 memcpy(mtd->buf, buf, res); 09663 mtd->len = res; 09664 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) { 09665 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel); 09666 ast_free(mtd); 09667 } 09668 i->mwimonitoractive = 1; 09669 } 09670 } 09671 } 09672 if (i->mwisendactive) { 09673 mwi_send_process_buffer(i, res); 09674 } 09675 } else { 09676 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 09677 } 09678 } 09679 if (pollres & POLLPRI) { 09680 if (i->owner || i->subs[SUB_REAL].owner) { 09681 #ifdef HAVE_PRI 09682 if (!i->pri) 09683 #endif 09684 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 09685 continue; 09686 } 09687 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 09688 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 09689 /* Don't hold iflock while handling init events */ 09690 ast_mutex_unlock(&iflock); 09691 if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) { 09692 doomed = handle_init_event(i, res); 09693 } 09694 ast_mutex_lock(&iflock); 09695 } 09696 } 09697 } 09698 ast_mutex_unlock(&iflock); 09699 } 09700 /* Never reached */ 09701 return NULL; 09702 09703 }
Definition at line 10771 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().
10772 { 10773 struct dahdi_pvt *p; 10774 struct dahdi_bufferinfo bi; 10775 int res; 10776 10777 if ((p = ast_malloc(sizeof(*p)))) { 10778 memcpy(p, src, sizeof(struct dahdi_pvt)); 10779 ast_mutex_init(&p->lock); 10780 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 10781 if (p->subs[SUB_REAL].dfd < 0) { 10782 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 10783 destroy_dahdi_pvt(&p); 10784 return NULL; 10785 } 10786 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 10787 if (!res) { 10788 bi.txbufpolicy = src->buf_policy; 10789 bi.rxbufpolicy = src->buf_policy; 10790 bi.numbufs = src->buf_no; 10791 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 10792 if (res < 0) { 10793 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 10794 } 10795 } else 10796 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 10797 } 10798 p->destroy = 1; 10799 p->next = iflist; 10800 p->prev = NULL; 10801 iflist = p; 10802 if (iflist->next) 10803 iflist->next->prev = p; 10804 return p; 10805 }
| static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 5138 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().
05139 { 05140 int val; 05141 05142 if (p->channel == CHAN_PSEUDO) 05143 return; 05144 05145 p->ignoredtmf = 0; 05146 05147 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 05148 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 05149 05150 if (!p->hardwaredtmf && p->dsp) { 05151 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT; 05152 ast_dsp_set_features(p->dsp, p->dsp_features); 05153 } 05154 }
| static char* event2str | ( | int | event | ) | [static] |
Definition at line 2389 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 2761 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
02762 { 02763 int j; 02764 int k; 02765 float linear_gain = pow(10.0, gain / 20.0); 02766 02767 switch (law) { 02768 case DAHDI_LAW_ALAW: 02769 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02770 if (gain) { 02771 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02772 if (k > 32767) k = 32767; 02773 if (k < -32767) k = -32767; 02774 g->rxgain[j] = AST_LIN2A(k); 02775 } else { 02776 g->rxgain[j] = j; 02777 } 02778 } 02779 break; 02780 case DAHDI_LAW_MULAW: 02781 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) { 02782 if (gain) { 02783 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02784 if (k > 32767) k = 32767; 02785 if (k < -32767) k = -32767; 02786 g->rxgain[j] = AST_LIN2MU(k); 02787 } else { 02788 g->rxgain[j] = j; 02789 } 02790 } 02791 break; 02792 } 02793 }
| static void fill_txgain | ( | struct dahdi_gains * | g, | |
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2727 of file chan_dahdi.c.
References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
02728 { 02729 int j; 02730 int k; 02731 float linear_gain = pow(10.0, gain / 20.0); 02732 02733 switch (law) { 02734 case DAHDI_LAW_ALAW: 02735 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02736 if (gain) { 02737 k = (int) (((float) AST_ALAW(j)) * linear_gain); 02738 if (k > 32767) k = 32767; 02739 if (k < -32767) k = -32767; 02740 g->txgain[j] = AST_LIN2A(k); 02741 } else { 02742 g->txgain[j] = j; 02743 } 02744 } 02745 break; 02746 case DAHDI_LAW_MULAW: 02747 for (j = 0; j < ARRAY_LEN(g->txgain); j++) { 02748 if (gain) { 02749 k = (int) (((float) AST_MULAW(j)) * linear_gain); 02750 if (k > 32767) k = 32767; 02751 if (k < -32767) k = -32767; 02752 g->txgain[j] = AST_LIN2MU(k); 02753 } else { 02754 g->txgain[j] = j; 02755 } 02756 } 02757 break; 02758 } 02759 }
| static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static, read] |
Definition at line 15201 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 5580 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().
05581 { 05582 int res; 05583 struct dahdi_spaninfo zi; 05584 struct dahdi_params params; 05585 05586 memset(&zi, 0, sizeof(zi)); 05587 zi.spanno = p->span; 05588 05589 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) { 05590 if (zi.alarms != DAHDI_ALARM_NONE) 05591 return zi.alarms; 05592 } else { 05593 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 05594 return 0; 05595 } 05596 05597 /* No alarms on the span. Check for channel alarms. */ 05598 memset(¶ms, 0, sizeof(params)); 05599 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 05600 return params.chan_alarms; 05601 05602 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 05603 05604 return DAHDI_ALARM_NONE; 05605 }
| static void handle_alarms | ( | struct dahdi_pvt * | p, | |
| int | alms | |||
| ) | [static] |
Definition at line 5688 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().
05689 { 05690 const char *alarm_str = alarm2str(alms); 05691 05692 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 05693 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 05694 "Alarm: %s\r\n" 05695 "Channel: %d\r\n", 05696 alarm_str, p->channel); 05697 }
| static char* handle_dahdi_show_cadences | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 14817 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.
14818 { 14819 int i, j; 14820 switch (cmd) { 14821 case CLI_INIT: 14822 e->command = "dahdi show cadences"; 14823 e->usage = 14824 "Usage: dahdi show cadences\n" 14825 " Shows all cadences currently defined\n"; 14826 return NULL; 14827 case CLI_GENERATE: 14828 return NULL; 14829 } 14830 for (i = 0; i < num_cadence; i++) { 14831 char output[1024]; 14832 char tmp[16], tmp2[64]; 14833 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 14834 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 14835 14836 for (j = 0; j < 16; j++) { 14837 if (cadences[i].ringcadence[j] == 0) 14838 break; 14839 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 14840 if (cidrings[i] * 2 - 1 == j) 14841 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 14842 else 14843 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 14844 if (j != 0) 14845 strncat(output, ",", sizeof(output) - strlen(output) - 1); 14846 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 14847 } 14848 ast_cli(a->fd,"%s\n",output); 14849 } 14850 return CLI_SUCCESS; 14851 }
Definition at line 9269 of file chan_dahdi.c.
References ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), dahdi_subchannel::dfd, errno, EVENT_FLAG_SYSTEM, dahdi_pvt::fxsoffhookstate, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, 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().
09270 { 09271 int res; 09272 pthread_t threadid; 09273 struct ast_channel *chan; 09274 09275 /* Handle an event on a given channel for the monitor thread. */ 09276 09277 switch (event) { 09278 case DAHDI_EVENT_NONE: 09279 case DAHDI_EVENT_BITSCHANGED: 09280 break; 09281 case DAHDI_EVENT_WINKFLASH: 09282 case DAHDI_EVENT_RINGOFFHOOK: 09283 if (i->inalarm) break; 09284 if (i->radio) break; 09285 /* Got a ring/answer. What kind of channel are we? */ 09286 switch (i->sig) { 09287 case SIG_FXOLS: 09288 case SIG_FXOGS: 09289 case SIG_FXOKS: 09290 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 09291 i->fxsoffhookstate = 1; 09292 if (res && (errno == EBUSY)) 09293 break; 09294 if (i->cidspill) { 09295 /* Cancel VMWI spill */ 09296 ast_free(i->cidspill); 09297 i->cidspill = NULL; 09298 } 09299 if (i->immediate) { 09300 dahdi_enable_ec(i); 09301 /* The channel is immediately up. Start right away */ 09302 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 09303 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 09304 if (!chan) { 09305 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 09306 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 09307 if (res < 0) 09308 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 09309 } 09310 } else { 09311 /* Check for callerid, digits, etc */ 09312 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 09313 if (chan) { 09314 if (has_voicemail(i)) 09315 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 09316 else 09317 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 09318 if (res < 0) 09319 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 09320 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 09321 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 09322 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 09323 if (res < 0) 09324 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 09325 ast_hangup(chan); 09326 } 09327 } else 09328 ast_log(LOG_WARNING, "Unable to create channel\n"); 09329 } 09330 break; 09331 case SIG_FXSLS: 09332 case SIG_FXSGS: 09333 case SIG_FXSKS: 09334 i->ringt = i->ringt_base; 09335 /* Fall through */ 09336 case SIG_EMWINK: 09337 case SIG_FEATD: 09338 case SIG_FEATDMF: 09339 case SIG_FEATDMF_TA: 09340 case SIG_E911: 09341 case SIG_FGC_CAMA: 09342 case SIG_FGC_CAMAMF: 09343 case SIG_FEATB: 09344 case SIG_EM: 09345 case SIG_EM_E1: 09346 case SIG_SFWINK: 09347 case SIG_SF_FEATD: 09348 case SIG_SF_FEATDMF: 09349 case SIG_SF_FEATB: 09350 case SIG_SF: 09351 /* Check for callerid, digits, etc */ 09352 if (i->cid_start == CID_START_POLARITY_IN) { 09353 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 09354 } else { 09355 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 09356 } 09357 09358 if (!chan) { 09359 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 09360 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 09361 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 09362 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 09363 if (res < 0) { 09364 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 09365 } 09366 ast_hangup(chan); 09367 } 09368 break; 09369 default: 09370 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 09371 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 09372 if (res < 0) 09373 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 09374 return NULL; 09375 } 09376 break; 09377 case DAHDI_EVENT_NOALARM: 09378 i->inalarm = 0; 09379 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 09380 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 09381 "Channel: %d\r\n", i->channel); 09382 break; 09383 case DAHDI_EVENT_ALARM: 09384 i->inalarm = 1; 09385 res = get_alarms(i); 09386 handle_alarms(i, res); 09387 /* fall thru intentionally */ 09388 case DAHDI_EVENT_ONHOOK: 09389 if (i->radio) 09390 break; 09391 /* Back on hook. Hang up. */ 09392 switch (i->sig) { 09393 case SIG_FXOLS: 09394 case SIG_FXOGS: 09395 case SIG_FEATD: 09396 case SIG_FEATDMF: 09397 case SIG_FEATDMF_TA: 09398 case SIG_E911: 09399 case SIG_FGC_CAMA: 09400 case SIG_FGC_CAMAMF: 09401 case SIG_FEATB: 09402 case SIG_EM: 09403 case SIG_EM_E1: 09404 case SIG_EMWINK: 09405 case SIG_SF_FEATD: 09406 case SIG_SF_FEATDMF: 09407 case SIG_SF_FEATB: 09408 case SIG_SF: 09409 case SIG_SFWINK: 09410 case SIG_FXSLS: 09411 case SIG_FXSGS: 09412 case SIG_FXSKS: 09413 case SIG_GR303FXSKS: 09414 dahdi_disable_ec(i); 09415 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 09416 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09417 break; 09418 case SIG_GR303FXOKS: 09419 case SIG_FXOKS: 09420 dahdi_disable_ec(i); 09421 /* Diddle the battery for the zhone */ 09422 #ifdef ZHONE_HACK 09423 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 09424 usleep(1); 09425 #endif 09426 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 09427 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 09428 break; 09429 case SIG_PRI: 09430 case SIG_SS7: 09431 case SIG_BRI: 09432 case SIG_BRI_PTMP: 09433 dahdi_disable_ec(i); 09434 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 09435 break; 09436 default: 09437 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 09438 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 09439 return NULL; 09440 } 09441 if (i->sig & __DAHDI_SIG_FXO) { 09442 i->fxsoffhookstate = 0; 09443 } 09444 break; 09445 case DAHDI_EVENT_POLARITY: 09446 switch (i->sig) { 09447 case SIG_FXSLS: 09448 case SIG_FXSKS: 09449 case SIG_FXSGS: 09450 /* We have already got a PR before the channel was 09451 created, but it wasn't handled. We need polarity 09452 to be REV for remote hangup detection to work. 09453 At least in Spain */ 09454 if (i->hanguponpolarityswitch) 09455 i->polarity = POLARITY_REV; 09456 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) { 09457 i->polarity = POLARITY_REV; 09458 ast_verb(2, "Starting post polarity " 09459 "CID detection on channel %d\n", 09460 i->channel); 09461 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 09462 if (!chan) { 09463 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 09464 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 09465 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 09466 } 09467 } 09468 break; 09469 default: 09470 ast_log(LOG_WARNING, "handle_init_event detected " 09471 "polarity reversal on non-FXO (SIG_FXS) " 09472 "interface %d\n", i->channel); 09473 } 09474 break; 09475 case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */ 09476 ast_log(LOG_NOTICE, 09477 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 09478 i->channel); 09479 return i; 09480 case DAHDI_EVENT_NEONMWI_ACTIVE: 09481 if (i->mwimonitor_neon) { 09482 notify_message(i->mailbox, 1); 09483 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox); 09484 } 09485 break; 09486 case DAHDI_EVENT_NEONMWI_INACTIVE: 09487 if (i->mwimonitor_neon) { 09488 notify_message(i->mailbox, 0); 09489 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox); 09490 } 09491 break; 09492 } 09493 return NULL; 09494 }
| static char* handle_pri_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13707 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, complete_span_4(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_DCHANS, NUM_SPANS, ast_cli_args::pos, pridebugfdlock, pris, ast_cli_entry::usage, and ast_cli_args::word.
13708 { 13709 int span; 13710 int x; 13711 int level = 0; 13712 switch (cmd) { 13713 case CLI_INIT: 13714 e->command = "pri set debug {on|off|0|1|2} span"; 13715 e->usage = 13716 "Usage: pri set debug {<level>|on|off} span <span>\n" 13717 " Enables debugging on a given PRI span\n"; 13718 return NULL; 13719 case CLI_GENERATE: 13720 return complete_span_4(a->line, a->word, a->pos, a->n); 13721 } 13722 if (a->argc < 6) { 13723 return CLI_SHOWUSAGE; 13724 } 13725 13726 if (!strcasecmp(a->argv[3], "on")) { 13727 level = 1; 13728 } else if (!strcasecmp(a->argv[3], "off")) { 13729 level = 0; 13730 } else { 13731 level = atoi(a->argv[3]); 13732 } 13733 span = atoi(a->argv[5]); 13734 if ((span < 1) || (span > NUM_SPANS)) { 13735 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS); 13736 return CLI_SUCCESS; 13737 } 13738 if (!pris[span-1].pri) { 13739 ast_cli(a->fd, "No PRI running on span %d\n", span); 13740 return CLI_SUCCESS; 13741 } 13742 for (x = 0; x < NUM_DCHANS; x++) { 13743 if (pris[span-1].dchans[x]) { 13744 if (level == 1) { 13745 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 13746 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 13747 PRI_DEBUG_Q921_STATE); 13748 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 13749 } else if (level == 0) { 13750 pri_set_debug(pris[span-1].dchans[x], 0); 13751 //close the file if it's set 13752 ast_mutex_lock(&pridebugfdlock); 13753 close(pridebugfd); 13754 pridebugfd = -1; 13755 ast_cli(a->fd, "PRI debug output to file disabled\n"); 13756 ast_mutex_unlock(&pridebugfdlock); 13757 } else { 13758 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU | 13759 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | 13760 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE); 13761 ast_cli(a->fd, "Enabled debugging on span %d\n", span); 13762 } 13763 } 13764 } 13765 return CLI_SUCCESS; 13766 }
| static char* handle_pri_set_debug_file | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13669 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(), 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.
13670 { 13671 int myfd; 13672 switch (cmd) { 13673 case CLI_INIT: 13674 e->command = "pri set debug file"; 13675 e->usage = "Usage: pri set debug file [output-file]\n" 13676 " Sends PRI debug output to the specified output file\n"; 13677 return NULL; 13678 case CLI_GENERATE: 13679 return NULL; 13680 } 13681 if (a->argc < 5) 13682 return CLI_SHOWUSAGE; 13683 13684 if (ast_strlen_zero(a->argv[4])) 13685 return CLI_SHOWUSAGE; 13686 13687 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE); 13688 if (myfd < 0) { 13689 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]); 13690 return CLI_SUCCESS; 13691 } 13692 13693 ast_mutex_lock(&pridebugfdlock); 13694 13695 if (pridebugfd >= 0) 13696 close(pridebugfd); 13697 13698 pridebugfd = myfd; 13699 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename)); 13700 ast_mutex_unlock(&pridebugfdlock); 13701 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]); 13702 return CLI_SUCCESS; 13703 }
| static char* handle_pri_show_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13880 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_DCHANS, NUM_SPANS, pridebugfdlock, pris, and ast_cli_entry::usage.
13881 { 13882 int x; 13883 int span; 13884 int count=0; 13885 int debug=0; 13886 13887 switch (cmd) { 13888 case CLI_INIT: 13889 e->command = "pri show debug"; 13890 e->usage = 13891 "Usage: pri show debug\n" 13892 " Show the debug state of pri spans\n"; 13893 return NULL; 13894 case CLI_GENERATE: 13895 return NULL; 13896 } 13897 13898 for (span = 0; span < NUM_SPANS; span++) { 13899 if (pris[span].pri) { 13900 for (x = 0; x < NUM_DCHANS; x++) { 13901 debug = 0; 13902 if (pris[span].dchans[x]) { 13903 debug = pri_get_debug(pris[span].dchans[x]); 13904 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" ); 13905 count++; 13906 } 13907 } 13908 } 13909 13910 } 13911 ast_mutex_lock(&pridebugfdlock); 13912 if (pridebugfd >= 0) 13913 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename); 13914 ast_mutex_unlock(&pridebugfdlock); 13915 13916 if (!count) 13917 ast_cli(a->fd, "No debug set or no PRI running\n"); 13918 return CLI_SUCCESS; 13919 }
| static char* handle_pri_show_span | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13828 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_DCHANS, NUM_SPANS, dahdi_pri::overlapdial, ast_cli_args::pos, pri_order(), pris, status, ast_cli_entry::usage, and ast_cli_args::word.
13829 { 13830 int span; 13831 int x; 13832 char status[256]; 13833 switch (cmd) { 13834 case CLI_INIT: 13835 e->command = "pri show span"; 13836 e->usage = 13837 "Usage: pri show span <span>\n" 13838 " Displays PRI Information on a given PRI span\n"; 13839 return NULL; 13840 case CLI_GENERATE: 13841 return complete_span_4(a->line, a->word, a->pos, a->n); 13842 } 13843 13844 if (a->argc < 4) 13845 return CLI_SHOWUSAGE; 13846 span = atoi(a->argv[3]); 13847 if ((span < 1) || (span > NUM_SPANS)) { 13848 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS); 13849 return CLI_SUCCESS; 13850 } 13851 if (!pris[span-1].pri) { 13852 ast_cli(a->fd, "No PRI running on span %d\n", span); 13853 return CLI_SUCCESS; 13854 } 13855 for (x = 0; x < NUM_DCHANS; x++) { 13856 if (pris[span-1].dchannels[x]) { 13857 #ifdef PRI_DUMP_INFO_STR 13858 char *info_str = NULL; 13859 #endif 13860 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]); 13861 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri); 13862 ast_cli(a->fd, "Status: %s\n", status); 13863 #ifdef PRI_DUMP_INFO_STR 13864 info_str = pri_dump_info_str(pris[span-1].pri); 13865 if (info_str) { 13866 ast_cli(a->fd, "%s", info_str); 13867 ast_free(info_str); 13868 } 13869 #else 13870 pri_dump_info(pris[span-1].pri); 13871 #endif 13872 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No"); 13873 } 13874 } 13875 return CLI_SUCCESS; 13876 }
| static char* handle_pri_show_spans | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13793 of file chan_dahdi.c.
References ast_cli_args::argc, ast_cli(), build_status(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NUM_DCHANS, NUM_SPANS, pris, status, and ast_cli_entry::usage.
13794 { 13795 int span; 13796 int x; 13797 char status[256]; 13798 13799 switch (cmd) { 13800 case CLI_INIT: 13801 e->command = "pri show spans"; 13802 e->usage = 13803 "Usage: pri show spans\n" 13804 " Displays PRI Information\n"; 13805 return NULL; 13806 case CLI_GENERATE: 13807 return NULL; 13808 } 13809 13810 if (a->argc != 3) 13811 return CLI_SHOWUSAGE; 13812 13813 for (span = 0; span < NUM_SPANS; span++) { 13814 if (pris[span].pri) { 13815 for (x = 0; x < NUM_DCHANS; x++) { 13816 if (pris[span].dchannels[x]) { 13817 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri); 13818 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status); 13819 } 13820 } 13821 } 13822 } 13823 return CLI_SUCCESS; 13824 }
| static char* handle_pri_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 13923 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.
13924 { 13925 switch (cmd) { 13926 case CLI_INIT: 13927 e->command = "pri show version"; 13928 e->usage = 13929 "Usage: pri show version\n" 13930 "Show libpri version information\n"; 13931 return NULL; 13932 case CLI_GENERATE: 13933 return NULL; 13934 } 13935 13936 ast_cli(a->fd, "libpri version: %s\n", pri_get_version()); 13937 13938 return CLI_SUCCESS; 13939 }
| static char* handle_ss7_block_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15569 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.
15570 { 15571 int linkset, cic; 15572 int blocked = -1, i; 15573 switch (cmd) { 15574 case CLI_INIT: 15575 e->command = "ss7 block cic"; 15576 e->usage = 15577 "Usage: ss7 block cic <linkset> <CIC>\n" 15578 " Sends a remote blocking request for the given CIC on the specified linkset\n"; 15579 return NULL; 15580 case CLI_GENERATE: 15581 return NULL; 15582 } 15583 if (a->argc == 5) 15584 linkset = atoi(a->argv[3]); 15585 else 15586 return CLI_SHOWUSAGE; 15587 15588 if ((linkset < 1) || (linkset > NUM_SPANS)) { 15589 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 15590 return CLI_SUCCESS; 15591 } 15592 15593 if (!linksets[linkset-1].ss7) { 15594 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 15595 return CLI_SUCCESS; 15596 } 15597 15598 cic = atoi(a->argv[4]); 15599 15600 if (cic < 1) { 15601 ast_cli(a->fd, "Invalid CIC specified!\n"); 15602 return CLI_SUCCESS; 15603 } 15604 15605 for (i = 0; i < linksets[linkset-1].numchans; i++) { 15606 if (linksets[linkset-1].pvts[i]->cic == cic) { 15607 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 15608 if (!blocked) { 15609 ast_mutex_lock(&linksets[linkset-1].lock); 15610 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 15611 ast_mutex_unlock(&linksets[linkset-1].lock); 15612 } 15613 } 15614 } 15615 15616 if (blocked < 0) { 15617 ast_cli(a->fd, "Invalid CIC specified!\n"); 15618 return CLI_SUCCESS; 15619 } 15620 15621 if (!blocked) 15622 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic); 15623 else 15624 ast_cli(a->fd, "CIC %d already locally blocked\n", cic); 15625 15626 /* Break poll on the linkset so it sends our messages */ 15627 pthread_kill(linksets[linkset-1].master, SIGURG); 15628 15629 return CLI_SUCCESS; 15630 }
| static char* handle_ss7_block_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15634 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.
15635 { 15636 int linkset; 15637 int i; 15638 switch (cmd) { 15639 case CLI_INIT: 15640 e->command = "ss7 block linkset"; 15641 e->usage = 15642 "Usage: ss7 block linkset <linkset number>\n" 15643 " Sends a remote blocking request for all CICs on the given linkset\n"; 15644 return NULL; 15645 case CLI_GENERATE: 15646 return NULL; 15647 } 15648 if (a->argc == 4) 15649 linkset = atoi(a->argv[3]); 15650 else 15651 return CLI_SHOWUSAGE; 15652 15653 if ((linkset < 1) || (linkset > NUM_SPANS)) { 15654 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 15655 return CLI_SUCCESS; 15656 } 15657 15658 if (!linksets[linkset-1].ss7) { 15659 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 15660 return CLI_SUCCESS; 15661 } 15662 15663 for (i = 0; i < linksets[linkset-1].numchans; i++) { 15664 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 15665 ast_mutex_lock(&linksets[linkset-1].lock); 15666 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 15667 ast_mutex_unlock(&linksets[linkset-1].lock); 15668 } 15669 15670 /* Break poll on the linkset so it sends our messages */ 15671 pthread_kill(linksets[linkset-1].master, SIGURG); 15672 15673 return CLI_SUCCESS; 15674 }
| static char* handle_ss7_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15530 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.
15531 { 15532 int span; 15533 switch (cmd) { 15534 case CLI_INIT: 15535 e->command = "ss7 set debug {on|off} linkset"; 15536 e->usage = 15537 "Usage: ss7 set debug {on|off} linkset <linkset>\n" 15538 " Enables debugging on a given SS7 linkset\n"; 15539 return NULL; 15540 case CLI_GENERATE: 15541 return NULL; 15542 } 15543 if (a->argc < 6) 15544 return CLI_SHOWUSAGE; 15545 span = atoi(a->argv[5]); 15546 if ((span < 1) || (span > NUM_SPANS)) { 15547 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS); 15548 return CLI_SUCCESS; 15549 } 15550 if (!linksets[span-1].ss7) { 15551 ast_cli(a->fd, "No SS7 running on linkset %d\n", span); 15552 return CLI_SUCCESS; 15553 } 15554 if (linksets[span-1].ss7) { 15555 if (strcasecmp(a->argv[3], "on")) { 15556 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP); 15557 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span); 15558 } else { 15559 ss7_set_debug(linksets[span-1].ss7, 0); 15560 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span); 15561 } 15562 } 15563 15564 return CLI_SUCCESS; 15565 }
| static char* handle_ss7_show_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15782 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.
15783 { 15784 int linkset; 15785 struct dahdi_ss7 *ss7; 15786 switch (cmd) { 15787 case CLI_INIT: 15788 e->command = "ss7 show linkset"; 15789 e->usage = 15790 "Usage: ss7 show linkset <span>\n" 15791 " Shows the status of an SS7 linkset.\n"; 15792 return NULL; 15793 case CLI_GENERATE: 15794 return NULL; 15795 } 15796 15797 if (a->argc < 4) 15798 return CLI_SHOWUSAGE; 15799 linkset = atoi(a->argv[3]); 15800 if ((linkset < 1) || (linkset > NUM_SPANS)) { 15801 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 15802 return CLI_SUCCESS; 15803 } 15804 if (!linksets[linkset-1].ss7) { 15805 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 15806 return CLI_SUCCESS; 15807 } 15808 if (linksets[linkset-1].ss7) 15809 ss7 = &linksets[linkset-1]; 15810 15811 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down"); 15812 15813 return CLI_SUCCESS; 15814 }
| static char* handle_ss7_unblock_cic | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15678 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.
15679 { 15680 int linkset, cic; 15681 int i, blocked = -1; 15682 switch (cmd) { 15683 case CLI_INIT: 15684 e->command = "ss7 unblock cic"; 15685 e->usage = 15686 "Usage: ss7 unblock cic <linkset> <CIC>\n" 15687 " Sends a remote unblocking request for the given CIC on the specified linkset\n"; 15688 return NULL; 15689 case CLI_GENERATE: 15690 return NULL; 15691 } 15692 15693 if (a->argc == 5) 15694 linkset = atoi(a->argv[3]); 15695 else 15696 return CLI_SHOWUSAGE; 15697 15698 if ((linkset < 1) || (linkset > NUM_SPANS)) { 15699 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 15700 return CLI_SUCCESS; 15701 } 15702 15703 if (!linksets[linkset-1].ss7) { 15704 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 15705 return CLI_SUCCESS; 15706 } 15707 15708 cic = atoi(a->argv[4]); 15709 15710 if (cic < 1) { 15711 ast_cli(a->fd, "Invalid CIC specified!\n"); 15712 return CLI_SUCCESS; 15713 } 15714 15715 for (i = 0; i < linksets[linkset-1].numchans; i++) { 15716 if (linksets[linkset-1].pvts[i]->cic == cic) { 15717 blocked = linksets[linkset-1].pvts[i]->locallyblocked; 15718 if (blocked) { 15719 ast_mutex_lock(&linksets[linkset-1].lock); 15720 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc); 15721 ast_mutex_unlock(&linksets[linkset-1].lock); 15722 } 15723 } 15724 } 15725 15726 if (blocked > 0) 15727 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic); 15728 15729 /* Break poll on the linkset so it sends our messages */ 15730 pthread_kill(linksets[linkset-1].master, SIGURG); 15731 15732 return CLI_SUCCESS; 15733 }
| static char* handle_ss7_unblock_linkset | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15737 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.
15738 { 15739 int linkset; 15740 int i; 15741 switch (cmd) { 15742 case CLI_INIT: 15743 e->command = "ss7 unblock linkset"; 15744 e->usage = 15745 "Usage: ss7 unblock linkset <linkset number>\n" 15746 " Sends a remote unblocking request for all CICs on the specified linkset\n"; 15747 return NULL; 15748 case CLI_GENERATE: 15749 return NULL; 15750 } 15751 15752 if (a->argc == 4) 15753 linkset = atoi(a->argv[3]); 15754 else 15755 return CLI_SHOWUSAGE; 15756 15757 if ((linkset < 1) || (linkset > NUM_SPANS)) { 15758 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS); 15759 return CLI_SUCCESS; 15760 } 15761 15762 if (!linksets[linkset-1].ss7) { 15763 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset); 15764 return CLI_SUCCESS; 15765 } 15766 15767 for (i = 0; i < linksets[linkset-1].numchans; i++) { 15768 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic); 15769 ast_mutex_lock(&linksets[linkset-1].lock); 15770 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc); 15771 ast_mutex_unlock(&linksets[linkset-1].lock); 15772 } 15773 15774 /* Break poll on the linkset so it sends our messages */ 15775 pthread_kill(linksets[linkset-1].master, SIGURG); 15776 15777 return CLI_SUCCESS; 15778 }
| static char* handle_ss7_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 15818 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.
15819 { 15820 switch (cmd) { 15821 case CLI_INIT: 15822 e->command = "ss7 show version"; 15823 e->usage = 15824 "Usage: ss7 show version\n" 15825 " Show the libss7 version\n"; 15826 return NULL; 15827 case CLI_GENERATE: 15828 return NULL; 15829 } 15830 15831 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version()); 15832 15833 return CLI_SUCCESS; 15834 }
| static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3001 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_strlen_zero(), context, dahdi_pvt::mailbox, and mailbox.
Referenced by dahdi_handle_event(), do_monitor(), handle_init_event(), and mwi_send_init().
03002 { 03003 int new_msgs; 03004 struct ast_event *event; 03005 char *mailbox, *context; 03006 03007 mailbox = context = ast_strdupa(p->mailbox); 03008 strsep(&context, "@"); 03009 if (ast_strlen_zero(context)) 03010 context = "default"; 03011 03012 event = ast_event_get_cached(AST_EVENT_MWI, 03013 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 03014 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 03015 AST_EVENT_IE_END); 03016 03017 if (event) { 03018 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); 03019 ast_event_destroy(event); 03020 } else 03021 new_msgs = ast_app_has_voicemail(p->mailbox, NULL); 03022 03023 return new_msgs; 03024 }
| static int isourconf | ( | struct dahdi_pvt * | p, | |
| struct dahdi_subchannel * | c | |||
| ) | [static] |
Definition at line 2516 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
02517 { 02518 /* If they're listening to our channel, they're ours */ 02519 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 02520 return 1; 02521 /* If they're a talker on our (allocated) conference, they're ours */ 02522 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 02523 return 1; 02524 return 0; 02525 }
Definition at line 2546 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().
02547 { 02548 int x; 02549 int useslavenative; 02550 struct dahdi_pvt *slave = NULL; 02551 /* Start out optimistic */ 02552 useslavenative = 1; 02553 /* Update conference state in a stateless fashion */ 02554 for (x = 0; x < 3; x++) { 02555 /* Any three-way calling makes slave native mode *definitely* out 02556 of the question */ 02557 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 02558 useslavenative = 0; 02559 } 02560 /* If we don't have any 3-way calls, check to see if we have 02561 precisely one slave */ 02562 if (useslavenative) { 02563 for (x = 0; x < MAX_SLAVES; x++) { 02564 if (p->slaves[x]) { 02565 if (slave) { 02566 /* Whoops already have a slave! No 02567 slave native and stop right away */ 02568 slave = NULL; 02569 useslavenative = 0; 02570 break; 02571 } else { 02572 /* We have one slave so far */ 02573 slave = p->slaves[x]; 02574 } 02575 } 02576 } 02577 } 02578 /* If no slave, slave native definitely out */ 02579 if (!slave) 02580 useslavenative = 0; 02581 else if (slave->law != p->law) { 02582 useslavenative = 0; 02583 slave = NULL; 02584 } 02585 if (out) 02586 *out = slave; 02587 return useslavenative; 02588 }
| static int linkset_addsigchan | ( | int | sigchan | ) | [static] |
Definition at line 15407 of file chan_dahdi.c.
References ast_log(), dahdi_close_ss7_fd(), errno, LINKSTATE_DOWN, LINKSTATE_INALARM, LOG_ERROR, NUM_DCHANS, NUM_SPANS, and ss7_resolve_linkset().
Referenced by process_dahdi().
15408 { 15409 struct dahdi_ss7 *link; 15410 int res; 15411 int curfd; 15412 struct dahdi_params p; 15413 struct dahdi_bufferinfo bi; 15414 struct dahdi_spaninfo si; 15415 15416 15417 link = ss7_resolve_linkset(cur_linkset); 15418 if (!link) { 15419 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 15420 return -1; 15421 } 15422 15423 if (cur_ss7type < 0) { 15424 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n"); 15425 return -1; 15426 } 15427 15428 if (!link->ss7) 15429 link->ss7 = ss7_new(cur_ss7type); 15430 15431 if (!link->ss7) { 15432 ast_log(LOG_ERROR, "Can't create new SS7!\n"); 15433 return -1; 15434 } 15435 15436 link->type = cur_ss7type; 15437 15438 if (cur_pointcode < 0) { 15439 ast_log(LOG_ERROR, "Unspecified pointcode!\n"); 15440 return -1; 15441 } else 15442 ss7_set_pc(link->ss7, cur_pointcode); 15443 15444 if (sigchan < 0) { 15445 ast_log(LOG_ERROR, "Invalid sigchan!\n"); 15446 return -1; 15447 } else { 15448 if (link->numsigchans >= NUM_DCHANS) { 15449 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset); 15450 return -1; 15451 } 15452 curfd = link->numsigchans; 15453 15454 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600); 15455 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) { 15456 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno)); 15457 return -1; 15458 } 15459 memset(&p, 0, sizeof(p)); 15460 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p); 15461 if (res) { 15462 dahdi_close_ss7_fd(link, curfd); 15463 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno)); 15464 return -1; 15465 } 15466 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) { 15467 dahdi_close_ss7_fd(link, curfd); 15468 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan); 15469 return -1; 15470 } 15471 15472 memset(&bi, 0, sizeof(bi)); 15473 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 15474 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 15475 bi.numbufs = 32; 15476 bi.bufsize = 512; 15477 15478 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) { 15479 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno)); 15480 dahdi_close_ss7_fd(link, curfd); 15481 return -1; 15482 } 15483 15484 if (p.sigtype == DAHDI_SIG_MTP2) 15485 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]); 15486 else 15487 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]); 15488 15489 link->numsigchans++; 15490 15491 memset(&si, 0, sizeof(si)); 15492 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si); 15493 if (res) { 15494 dahdi_close_ss7_fd(link, curfd); 15495 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno)); 15496 } 15497 15498 if (!si.alarms) { 15499 link->linkstate[curfd] = LINKSTATE_DOWN; 15500 ss7_link_noalarm(link->ss7, link->fds[curfd]); 15501 } else { 15502 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM; 15503 ss7_link_alarm(link->ss7, link->fds[curfd]); 15504 } 15505 } 15506 15507 if (cur_adjpointcode < 0) { 15508 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n"); 15509 return -1; 15510 } else { 15511 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode); 15512 } 15513 15514 if (cur_defaultdpc < 0) { 15515 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n"); 15516 return -1; 15517 } 15518 15519 if (cur_networkindicator < 0) { 15520 ast_log(LOG_ERROR, "Invalid networkindicator!\n"); 15521 return -1; 15522 } else 15523 ss7_set_network_ind(link->ss7, cur_networkindicator); 15524 15525 return 0; 15526 }
| static int load_module | ( | void | ) | [static] |
Definition at line 17308 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_xml, ast_string_field_init, ast_string_field_set, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_ss7_error(), dahdi_ss7_message(), inuse, linksets, lock, LOG_ERROR, dahdi_ss7::master, dahdi_pri::master, name, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, and setup_dahdi().
17309 { 17310 int res; 17311 #if defined(HAVE_PRI) || defined(HAVE_SS7) 17312 int y, i; 17313 #endif 17314 17315 #ifdef HAVE_PRI 17316 memset(pris, 0, sizeof(pris)); 17317 for (y = 0; y < NUM_SPANS; y++) { 17318 ast_mutex_init(&pris[y].lock); 17319 pris[y].offset = -1; 17320 pris[y].master = AST_PTHREADT_NULL; 17321 for (i = 0; i < NUM_DCHANS; i++) 17322 pris[y].fds[i] = -1; 17323 } 17324 pri_set_error(dahdi_pri_error); 17325 pri_set_message(dahdi_pri_message); 17326 ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec); 17327 #ifdef HAVE_PRI_PROG_W_CAUSE 17328 ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec); 17329 #endif 17330 #endif 17331 #ifdef HAVE_SS7 17332 memset(linksets, 0, sizeof(linksets)); 17333 for (y = 0; y < NUM_SPANS; y++) { 17334 ast_mutex_init(&linksets[y].lock); 17335 linksets[y].master = AST_PTHREADT_NULL; 17336 for (i = 0; i < NUM_DCHANS; i++) 17337 linksets[y].fds[i] = -1; 17338 } 17339 ss7_set_error(dahdi_ss7_error); 17340 ss7_set_message(dahdi_ss7_message); 17341 #endif /* HAVE_SS7 */ 17342 res = setup_dahdi(0); 17343 /* Make sure we can register our DAHDI channel type */ 17344 if (res) 17345 return AST_MODULE_LOAD_DECLINE; 17346 if (ast_channel_register(&dahdi_tech)) { 17347 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n"); 17348 __unload_module(); 17349 return AST_MODULE_LOAD_FAILURE; 17350 } 17351 #ifdef HAVE_PRI 17352 ast_string_field_init(&inuse, 16); 17353 ast_string_field_set(&inuse, name, "GR-303InUse"); 17354 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli)); 17355 #endif 17356 #ifdef HAVE_SS7 17357 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli)); 17358 #endif 17359 #ifdef HAVE_OPENR2 17360 ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0])); 17361 ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec); 17362 #endif 17363 17364 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli)); 17365 17366 memset(round_robin, 0, sizeof(round_robin)); 17367 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" ); 17368 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" ); 17369 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" ); 17370 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" ); 17371 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" ); 17372 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels"); 17373 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)"); 17374 17375 ast_cond_init(&ss_thread_complete, NULL); 17376 17377 return res; 17378 }
| static struct dahdi_pvt* mkintf | ( | int | channel, | |
| const struct dahdi_chan_conf * | conf, | |||
| struct dahdi_pri * | pri, | |||
| int | reloading | |||
| ) | [static, read] |
Definition at line 9990 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_strlen_zero(), ast_variable_new(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call, dahdi_ss7::called_nai, dahdi_pvt::callgroup, dahdi_ss7::calling_nai, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_SMDI, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, dahdi_pvt::cid_ton, dahdi_pvt::confno, context, dahdi_pvt::context, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), dahdi_set_hook(), dahdi_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pri::dialplan, dialplan2str(), dahdi_pri::discardremoteholdretrieval, dahdi_pvt::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, ast_variable::file, dahdi_pvt::firstradio, free, dahdi_pvt::fxsoffhookstate, get_alarms(), dahdi_pvt::group, handle_alarms(), dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::head, dahdi_pvt::hidecallerid, dahdi_pri::idledial, dahdi_pri::idleext, iflist, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pri::inbanddisconnect, dahdi_pvt::inservice, dahdi_pri::internationalprefix, dahdi_ss7::internationalprefix, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::locallyblocked, dahdi_pri::localprefix, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, mailbox, dahdi_pvt::mailbox, MAX_CHANNELS, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, mwi_event_cb(), dahdi_pvt::mwi_event_sub, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, ast_variable::next, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, NUM_SPANS, dahdi_pri::numchans, dahdi_ss7::numchans, dahdi_pvt::onhooktime, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::parkinglot, dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_chan_conf::pri, pri_is_up(), pri_resolve_span(), dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::privateprefix, dahdi_pvt::propconfno, dahdi_pvt::pulse, dahdi_pri::pvts, dahdi_ss7::pvts, dahdi_pri::qsigchannelmapping, dahdi_pvt::radio, distRingData::range, dahdi_pvt::remotelyblocked, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, dahdi_distRings::ringnum, dahdi_pvt::ringt_base, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pri::sig, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sigtype_to_signalling(), dahdi_pvt::smdi_iface, dahdi_chan_conf::smdi_port, dahdi_pvt::span, dahdi_chan_conf::ss7, dahdi_pvt::ss7, dahdi_ss7::ss7, ss7_resolve_linkset(), dahdi_pvt::ss7call, dahdi_pvt::stripmsd, SUB_REAL, dahdi_pvt::subs, dahdi_ss7::subscriberprefix, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_ss7::unknownprefix, update_conf(), dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
Referenced by build_channels(), and process_dahdi().
09991 { 09992 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 09993 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 09994 char fn[80]; 09995 struct dahdi_bufferinfo bi; 09996 09997 int res; 09998 int span = 0; 09999 int here = 0; 10000 int x; 10001 struct dahdi_pvt **wlist; 10002 struct dahdi_pvt **wend; 10003 struct dahdi_params p; 10004 10005 wlist = &iflist; 10006 wend = &ifend; 10007 10008 #ifdef HAVE_PRI 10009 if (pri) { 10010 wlist = &pri->crvs; 10011 wend = &pri->crvend; 10012 } 10013 #endif 10014 10015 tmp2 = *wlist; 10016 prev = NULL; 10017 10018 while (tmp2) { 10019 if (!tmp2->destroy) { 10020 if (tmp2->channel == channel) { 10021 tmp = tmp2; 10022 here = 1; 10023 break; 10024 } 10025 if (tmp2->channel > channel) { 10026 break; 10027 } 10028 } 10029 prev = tmp2; 10030 tmp2 = tmp2->next; 10031 } 10032 10033 if (!here && reloading != 1) { 10034 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 10035 if (tmp) 10036 free(tmp); 10037 return NULL; 10038 } 10039 ast_mutex_init(&tmp->lock); 10040 ifcount++; 10041 for (x = 0; x < 3; x++) 10042 tmp->subs[x].dfd = -1; 10043 tmp->channel = channel; 10044 tmp->priindication_oob = conf->chan.priindication_oob; 10045 } 10046 10047 if (tmp) { 10048 int chan_sig = conf->chan.sig; 10049 if (!here) { 10050 if ((channel != CHAN_PSEUDO) && !pri) { 10051 int count = 0; 10052 snprintf(fn, sizeof(fn), "%d", channel); 10053 /* Open non-blocking */ 10054 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 10055 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 */ 10056 usleep(1); 10057 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 10058 count++; 10059 } 10060 /* Allocate a DAHDI structure */ 10061 if (tmp->subs[SUB_REAL].dfd < 0) { 10062 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); 10063 destroy_dahdi_pvt(&tmp); 10064 return NULL; 10065 } 10066 memset(&p, 0, sizeof(p)); 10067 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 10068 if (res < 0) { 10069 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 10070 destroy_dahdi_pvt(&tmp); 10071 return NULL; 10072 } 10073 if (conf->is_sig_auto) 10074 chan_sig = sigtype_to_signalling(p.sigtype); 10075 if (p.sigtype != (chan_sig & 0x3ffff)) { 10076 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)); 10077 destroy_dahdi_pvt(&tmp); 10078 return NULL; 10079 } 10080 tmp->law = p.curlaw; 10081 tmp->span = p.spanno; 10082 span = p.spanno - 1; 10083 } else { 10084 if (channel == CHAN_PSEUDO) 10085 chan_sig = 0; 10086 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 10087 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 10088 return NULL; 10089 } 10090 } 10091 #ifdef HAVE_SS7 10092 if (chan_sig == SIG_SS7) { 10093 struct dahdi_ss7 *ss7; 10094 int clear = 0; 10095 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) { 10096 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 10097 destroy_dahdi_pvt(&tmp); 10098 return NULL; 10099 } 10100 10101 ss7 = ss7_resolve_linkset(cur_linkset); 10102 if (!ss7) { 10103 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset); 10104 destroy_dahdi_pvt(&tmp); 10105 return NULL; 10106 } 10107 if (cur_cicbeginswith < 0) { 10108 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n"); 10109 destroy_dahdi_pvt(&tmp); 10110 return NULL; 10111 } 10112 10113 tmp->cic = cur_cicbeginswith++; 10114 10115 /* DB: Add CIC's DPC information */ 10116 tmp->dpc = cur_defaultdpc; 10117 10118 tmp->ss7 = ss7; 10119 tmp->ss7call = NULL; 10120 ss7->pvts[ss7->numchans++] = tmp; 10121 10122 ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix)); 10123 ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix)); 10124 ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix)); 10125 ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix)); 10126 10127 ss7->called_nai = conf->ss7.called_nai; 10128 ss7->calling_nai = conf->ss7.calling_nai; 10129 } 10130 #endif 10131 #ifdef HAVE_OPENR2 10132 if (chan_sig == SIG_MFCR2 && reloading != 1) { 10133 struct dahdi_mfcr2 *r2_link; 10134 r2_link = dahdi_r2_get_link(); 10135 if (!r2_link) { 10136 ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n"); 10137 destroy_dahdi_pvt(&tmp); 10138 return NULL; 10139 } 10140 if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) { 10141 ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n"); 10142 destroy_dahdi_pvt(&tmp); 10143 return NULL; 10144 } 10145 if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) { 10146 ast_log(LOG_ERROR, "Cannot add more channels to this link!\n"); 10147 destroy_dahdi_pvt(&tmp); 10148 return NULL; 10149 } 10150 r2_link->pvts[r2_link->numchans++] = tmp; 10151 tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context, 10152 tmp->subs[SUB_REAL].dfd, 10153 NULL, NULL); 10154 if (!tmp->r2chan) { 10155 openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context); 10156 ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err)); 10157 destroy_dahdi_pvt(&tmp); 10158 return NULL; 10159 } 10160 tmp->mfcr2 = r2_link; 10161 if (conf->mfcr2.call_files) { 10162 openr2_chan_enable_call_files(tmp->r2chan); 10163 } 10164 openr2_chan_set_client_data(tmp->r2chan, tmp); 10165 /* cast seems to be needed to get rid of the annoying warning regarding format attribute */ 10166 openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log); 10167 openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel); 10168 tmp->mfcr2_category = conf->mfcr2.category; 10169 tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls; 10170 tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls; 10171 tmp->mfcr2_forced_release = conf->mfcr2.forced_release; 10172 tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer; 10173 tmp->mfcr2call = 0; 10174 tmp->mfcr2_dnis_index = 0; 10175 tmp->mfcr2_ani_index = 0; 10176 r2_link->monitored_count++; 10177 } 10178 #endif 10179 #ifdef HAVE_PRI 10180 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 10181 int offset; 10182 int myswitchtype; 10183 int matchesdchan; 10184 int x,y; 10185 offset = 0; 10186 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 10187 && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 10188 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 10189 destroy_dahdi_pvt(&tmp); 10190 return NULL; 10191 } 10192 if (span >= NUM_SPANS) { 10193 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 10194 destroy_dahdi_pvt(&tmp); 10195 return NULL; 10196 } else { 10197 struct dahdi_spaninfo si; 10198 si.spanno = 0; 10199 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 10200 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 10201 destroy_dahdi_pvt(&tmp); 10202 return NULL; 10203 } 10204 /* Store the logical span first based upon the real span */ 10205 tmp->logicalspan = pris[span].prilogicalspan; 10206 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 10207 if (span < 0) { 10208 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 10209 destroy_dahdi_pvt(&tmp); 10210 return NULL; 10211 } 10212 if ((chan_sig == SIG_PRI) || 10213 (chan_sig == SIG_BRI) || 10214 (chan_sig == SIG_BRI_PTMP)) 10215 myswitchtype = conf->pri.switchtype; 10216 else 10217 myswitchtype = PRI_SWITCH_GR303_TMC; 10218 /* Make sure this isn't a d-channel */ 10219 matchesdchan=0; 10220 for (x = 0; x < NUM_SPANS; x++) { 10221 for (y = 0; y < NUM_DCHANS; y++) { 10222 if (pris[x].dchannels[y] == tmp->channel) { 10223 matchesdchan = 1; 10224 break; 10225 } 10226 } 10227 } 10228 offset = p.chanpos; 10229 if (!matchesdchan) { 10230 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 10231 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 10232 destroy_dahdi_pvt(&tmp); 10233 return NULL; 10234 } 10235 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 10236 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 10237 destroy_dahdi_pvt(&tmp); 10238 return NULL; 10239 } 10240 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 10241 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 10242 destroy_dahdi_pvt(&tmp); 10243 return NULL; 10244 } 10245 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 10246 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 10247 destroy_dahdi_pvt(&tmp); 10248 return NULL; 10249 } 10250 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 10251 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 10252 destroy_dahdi_pvt(&tmp); 10253 return NULL; 10254 } 10255 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 10256 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 10257 destroy_dahdi_pvt(&tmp); 10258 return NULL; 10259 } 10260 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 10261 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 10262 destroy_dahdi_pvt(&tmp); 10263 return NULL; 10264 } 10265 if (pris[span].numchans >= MAX_CHANNELS) { 10266 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 10267 pris[span].trunkgroup); 10268 destroy_dahdi_pvt(&tmp); 10269 return NULL; 10270 } 10271 10272 pris[span].sig = chan_sig; 10273 pris[span].nodetype = conf->pri.nodetype; 10274 pris[span].switchtype = myswitchtype; 10275 pris[span].nsf = conf->pri.nsf; 10276 pris[span].dialplan = conf->pri.dialplan; 10277 pris[span].localdialplan = conf->pri.localdialplan; 10278 pris[span].pvts[pris[span].numchans++] = tmp; 10279 pris[span].minunused = conf->pri.minunused; 10280 pris[span].minidle = conf->pri.minidle; 10281 pris[span].overlapdial = conf->pri.overlapdial; 10282 pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping; 10283 pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval; 10284 #ifdef HAVE_PRI_INBANDDISCONNECT 10285 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 10286 #endif 10287 pris[span].facilityenable = conf->pri.facilityenable; 10288 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 10289 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 10290 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 10291 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 10292 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 10293 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 10294 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 10295 pris[span].resetinterval = conf->pri.resetinterval; 10296 10297 tmp->pri = &pris[span]; 10298 tmp->prioffset = offset; 10299 tmp->call = NULL; 10300 } else { 10301 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 10302 destroy_dahdi_pvt(&tmp); 10303 return NULL; 10304 } 10305 } 10306 } else { 10307 tmp->prioffset = 0; 10308 } 10309 #endif 10310 } else { 10311 chan_sig = tmp->sig; 10312 if (tmp->subs[SUB_REAL].dfd > -1) { 10313 memset(&p, 0, sizeof(p)); 10314 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 10315 } 10316 } 10317 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 10318 switch (chan_sig) { 10319 case SIG_FXSKS: 10320 case SIG_FXSLS: 10321 case SIG_EM: 10322 case SIG_EM_E1: 10323 case SIG_EMWINK: 10324 case SIG_FEATD: 10325 case SIG_FEATDMF: 10326 case SIG_FEATDMF_TA: 10327 case SIG_FEATB: 10328 case SIG_E911: 10329 case SIG_SF: 10330 case SIG_SFWINK: 10331 case SIG_FGC_CAMA: 10332 case SIG_FGC_CAMAMF: 10333 case SIG_SF_FEATD: 10334 case SIG_SF_FEATDMF: 10335 case SIG_SF_FEATB: 10336 p.starttime = 250; 10337 break; 10338 } 10339 10340 if (tmp->radio) { 10341 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 10342 p.channo = channel; 10343 p.rxwinktime = 1; 10344 p.rxflashtime = 1; 10345 p.starttime = 1; 10346 p.debouncetime = 5; 10347 } 10348 if (!tmp->radio) { 10349 p.channo = channel; 10350 /* Override timing settings based on config file */ 10351 if (conf->timing.prewinktime >= 0) 10352 p.prewinktime = conf->timing.prewinktime; 10353 if (conf->timing.preflashtime >= 0) 10354 p.preflashtime = conf->timing.preflashtime; 10355 if (conf->timing.winktime >= 0) 10356 p.winktime = conf->timing.winktime; 10357 if (conf->timing.flashtime >= 0) 10358 p.flashtime = conf->timing.flashtime; 10359 if (conf->timing.starttime >= 0) 10360 p.starttime = conf->timing.starttime; 10361 if (conf->timing.rxwinktime >= 0) 10362 p.rxwinktime = conf->timing.rxwinktime; 10363 if (conf->timing.rxflashtime >= 0) 10364 p.rxflashtime = conf->timing.rxflashtime; 10365 if (conf->timing.debouncetime >= 0) 10366 p.debouncetime = conf->timing.debouncetime; 10367 } 10368 10369 /* dont set parms on a pseudo-channel (or CRV) */ 10370 if (tmp->subs[SUB_REAL].dfd >= 0) 10371 { 10372 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 10373 if (res < 0) { 10374 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 10375 destroy_dahdi_pvt(&tmp); 10376 return NULL; 10377 } 10378 } 10379 #if 1 10380 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 10381 memset(&bi, 0, sizeof(bi)); 10382 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 10383 if (!res) { 10384 bi.txbufpolicy = conf->chan.buf_policy; 10385 bi.rxbufpolicy = conf->chan.buf_policy; 10386 bi.numbufs = conf->chan.buf_no; 10387 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 10388 if (res < 0) { 10389 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 10390 } 10391 } else { 10392 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 10393 } 10394 tmp->buf_policy = conf->chan.buf_policy; 10395 tmp->buf_no = conf->chan.buf_no; 10396 tmp->usefaxbuffers = conf->chan.usefaxbuffers; 10397 tmp->faxbuf_policy = conf->chan.faxbuf_policy; 10398 tmp->faxbuf_no = conf->chan.faxbuf_no; 10399 /* This is not as gnarly as it may first appear. If the ioctl above failed, we'd be setting 10400 * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail. 10401 * The reason the ioctl call above failed should to be determined before worrying about the 10402 * faxbuffer-related ioctl calls */ 10403 tmp->bufsize = bi.bufsize; 10404 } 10405 #endif 10406 tmp->immediate = conf->chan.immediate; 10407 tmp->transfertobusy = conf->chan.transfertobusy; 10408 if (chan_sig & __DAHDI_SIG_FXS) { 10409 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk; 10410 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon; 10411 tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas; 10412 } 10413 tmp->sig = chan_sig; 10414 tmp->outsigmod = conf->chan.outsigmod; 10415 tmp->ringt_base = ringt_base; 10416 tmp->firstradio = 0; 10417 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 10418 tmp->permcallwaiting = conf->chan.callwaiting; 10419 else 10420 tmp->permcallwaiting = 0; 10421 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 10422 tmp->destroy = 0; 10423 tmp->drings = conf->chan.drings; 10424 10425 /* 10 is a nice default. */ 10426 if (tmp->drings.ringnum[0].range == 0) 10427 tmp->drings.ringnum[0].range = 10; 10428 if (tmp->drings.ringnum[1].range == 0) 10429 tmp->drings.ringnum[1].range = 10; 10430 if (tmp->drings.ringnum[2].range == 0) 10431 tmp->drings.ringnum[2].range = 10; 10432 10433 tmp->usedistinctiveringdetection = usedistinctiveringdetection; 10434 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 10435 tmp->threewaycalling = conf->chan.threewaycalling; 10436 tmp->adsi = conf->chan.adsi; 10437 tmp->use_smdi = conf->chan.use_smdi; 10438 tmp->permhidecallerid = conf->chan.hidecallerid; 10439 tmp->callreturn = conf->chan.callreturn; 10440 tmp->echocancel = conf->chan.echocancel; 10441 tmp->echotraining = conf->chan.echotraining; 10442 tmp->pulse = conf->chan.pulse; 10443 if (tmp->echocancel.head.tap_length) { 10444 tmp->echocanbridged = conf->chan.echocanbridged; 10445 } else { 10446 if (conf->chan.echocanbridged) 10447 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 10448 tmp->echocanbridged = 0; 10449 } 10450 tmp->busydetect = conf->chan.busydetect; 10451 tmp->busycount = conf->chan.busycount; 10452 tmp->busy_tonelength = conf->chan.busy_tonelength; 10453 tmp->busy_quietlength = conf->chan.busy_quietlength; 10454 tmp->callprogress = conf->chan.callprogress; 10455 tmp->waitfordialtone = conf->chan.waitfordialtone; 10456 tmp->cancallforward = conf->chan.cancallforward; 10457 tmp->dtmfrelax = conf->chan.dtmfrelax; 10458 tmp->callwaiting = tmp->permcallwaiting; 10459 tmp->hidecallerid = tmp->permhidecallerid; 10460 tmp->channel = channel; 10461 tmp->stripmsd = conf->chan.stripmsd; 10462 tmp->use_callerid = conf->chan.use_callerid; 10463 tmp->cid_signalling = conf->chan.cid_signalling; 10464 tmp->cid_start = conf->chan.cid_start; 10465 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 10466 tmp->restrictcid = conf->chan.restrictcid; 10467 tmp->use_callingpres = conf->chan.use_callingpres; 10468 tmp->priexclusive = conf->chan.priexclusive; 10469 if (tmp->usedistinctiveringdetection) { 10470 if (!tmp->use_callerid) { 10471 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 10472 tmp->use_callerid = 1; 10473 } 10474 } 10475 10476 if (tmp->cid_signalling == CID_SIG_SMDI) { 10477 if (!tmp->use_smdi) { 10478 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 10479 tmp->use_smdi = 1; 10480 } 10481 } 10482 if (tmp->use_smdi) { 10483 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 10484 if (!(tmp->smdi_iface)) { 10485 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 10486 tmp->use_smdi = 0; 10487 } 10488 } 10489 10490 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 10491 tmp->amaflags = conf->chan.amaflags; 10492 if (!here) { 10493 tmp->confno = -1; 10494 tmp->propconfno = -1; 10495 } 10496 tmp->canpark = conf->chan.canpark; 10497 tmp->transfer = conf->chan.transfer; 10498 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 10499 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 10500 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 10501 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 10502 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 10503 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot)); 10504 tmp->cid_ton = 0; 10505 if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP) || (tmp->sig != SIG_MFCR2)) { 10506 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 10507 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 10508 } else { 10509 tmp->cid_num[0] = '\0'; 10510 tmp->cid_name[0] = '\0'; 10511 } 10512 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 10513 if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) { 10514 char *mailbox, *context; 10515 mailbox = context = ast_strdupa(tmp->mailbox); 10516 strsep(&context, "@"); 10517 if (ast_strlen_zero(context)) 10518 context = "default"; 10519 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL, 10520 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 10521 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 10522 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, 10523 AST_EVENT_IE_END); 10524 } 10525 tmp->msgstate = -1; 10526 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 10527 tmp->mwisend_setting = conf->chan.mwisend_setting; 10528 tmp->mwisend_fsk = conf->chan.mwisend_fsk; 10529 tmp->mwisend_rpas = conf->chan.mwisend_rpas; 10530 #endif 10531 if (chan_sig & __DAHDI_SIG_FXO) { 10532 memset(&p, 0, sizeof(p)); 10533 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 10534 if (!res) { 10535 tmp->fxsoffhookstate = p.rxisoffhook; 10536 } 10537 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 10538 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); 10539 #endif 10540 } 10541 tmp->onhooktime = time(NULL); 10542 tmp->group = conf->chan.group; 10543 tmp->callgroup = conf->chan.callgroup; 10544 tmp->pickupgroup= conf->chan.pickupgroup; 10545 if (conf->chan.vars) { 10546 struct ast_variable *v, *tmpvar; 10547 for (v = conf->chan.vars ; v ; v = v->next) { 10548 if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { 10549 tmpvar->next = tmp->vars; 10550 tmp->vars = tmpvar; 10551 } 10552 } 10553 } 10554 tmp->cid_rxgain = conf->chan.cid_rxgain; 10555 tmp->rxgain = conf->chan.rxgain; 10556 tmp->txgain = conf->chan.txgain; 10557 tmp->tonezone = conf->chan.tonezone; 10558 if (tmp->subs[SUB_REAL].dfd > -1) { 10559 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 10560 if (tmp->dsp) 10561 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 10562 update_conf(tmp); 10563 if (!here) { 10564 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) 10565 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2)) 10566 /* Hang it up to be sure it's good */ 10567 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 10568 } 10569 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 10570 #ifdef HAVE_PRI 10571 /* the dchannel is down so put the channel in alarm */ 10572 if (tmp->pri && !pri_is_up(tmp->pri)) 10573 tmp->inalarm = 1; 10574 #endif 10575 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 10576 tmp->inalarm = 1; 10577 handle_alarms(tmp, res); 10578 } 10579 } 10580 10581 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 10582 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 10583 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 10584 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 10585 if (!here) { 10586 tmp->locallyblocked = tmp->remotelyblocked = 0; 10587 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) 10588 tmp->inservice = 0; 10589 else /* We default to in service on protocols that don't have a reset */ 10590 tmp->inservice = 1; 10591 } 10592 } 10593 if (tmp && !here) { 10594 /* nothing on the iflist */ 10595 if (!*wlist) { 10596 *wlist = tmp; 10597 tmp->prev = NULL; 10598 tmp->next = NULL; 10599 *wend = tmp; 10600 } else { 10601 /* at least one member on the iflist */ 10602 struct dahdi_pvt *working = *wlist; 10603 10604 /* check if we maybe have to put it on the begining */ 10605 if (working->channel > tmp->channel) { 10606 tmp->next = *wlist; 10607 tmp->prev = NULL; 10608 (*wlist)->prev = tmp; 10609 *wlist = tmp; 10610 } else { 10611 /* go through all the members and put the member in the right place */ 10612 while (working) { 10613 /* in the middle */ 10614 if (working->next) { 10615 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 10616 tmp->next = working->next; 10617 tmp->prev = working; 10618 working->next->prev = tmp; 10619 working->next = tmp; 10620 break; 10621 } 10622 } else { 10623 /* the last */ 10624 if (working->channel < tmp->channel) { 10625 working->next = tmp; 10626 tmp->next = NULL; 10627 tmp->prev = working; 10628 *wend = tmp; 10629 break; 10630 } 10631 } 10632 working = working->next; 10633 } 10634 } 10635 } 10636 } 10637 return tmp; 10638 }
| static void mwi_event_cb | ( | const struct ast_event * | event, | |
| void * | userdata | |||
| ) | [static] |
Definition at line 367 of file chan_dahdi.c.
Referenced by mkintf().
00368 { 00369 /* This module does not handle MWI in an event-based manner. However, it 00370 * subscribes to MWI for each mailbox that is configured so that the core 00371 * knows that we care about it. Then, chan_dahdi will get the MWI from the 00372 * event cache instead of checking the mailbox directly. */ 00373 }
| static int mwi_send_init | ( | struct dahdi_pvt * | pvt | ) | [static] |
Definition at line 9063 of file chan_dahdi.c.
References ast_calloc, ast_free, AST_LAW, ast_log(), CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_subchannel::dfd, has_voicemail(), LOG_WARNING, MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, SUB_REAL, dahdi_pvt::subs, and vmwi_generate().
Referenced by do_monitor().
09064 { 09065 int x, res; 09066 09067 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 09068 /* Determine how this spill is to be sent */ 09069 if (pvt->mwisend_rpas) { 09070 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 09071 pvt->mwisendactive = 1; 09072 } else if (pvt->mwisend_fsk) { 09073 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 09074 pvt->mwisendactive = 1; 09075 } else { 09076 pvt->mwisendactive = 0; 09077 return 0; 09078 } 09079 #else 09080 if (mwisend_rpas) { 09081 pvt->mwisend_data.mwisend_current = MWI_SEND_SA; 09082 } else { 09083 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 09084 } 09085 pvt->mwisendactive = 1; 09086 #endif 09087 09088 if (pvt->cidspill) { 09089 ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n"); 09090 ast_free(pvt->cidspill); 09091 pvt->cidspill = NULL; 09092 pvt->cidpos = 0; 09093 pvt->cidlen = 0; 09094 } 09095 pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE); 09096 if (!pvt->cidspill) { 09097 pvt->mwisendactive = 0; 09098 return -1; 09099 } 09100 x = DAHDI_FLUSH_BOTH; 09101 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 09102 x = 3000; 09103 ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 09104 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 09105 if (pvt->mwisend_fsk) { 09106 #endif 09107 pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL, 09108 AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0); 09109 pvt->cidpos = 0; 09110 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 09111 } 09112 #endif 09113 return 0; 09114 }
| static int mwi_send_process_buffer | ( | struct dahdi_pvt * | pvt, | |
| int | num_read | |||
| ) | [static] |
Definition at line 9116 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_CLEANUP, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, quit, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
09117 { 09118 struct timeval now; 09119 int res; 09120 09121 /* sanity check to catch if this had been interrupted previously 09122 * i.e. state says there is more to do but there is no spill allocated 09123 */ 09124 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) { 09125 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 09126 } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 09127 /* Normal processing -- Perform mwi send action */ 09128 switch ( pvt->mwisend_data.mwisend_current) { 09129 case MWI_SEND_SA: 09130 /* Send the Ring Pulse Signal Alert */ 09131 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence); 09132 if (res) { 09133 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno)); 09134 goto quit; 09135 } 09136 res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING); 09137 pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT; 09138 break; 09139 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */ 09140 break; 09141 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/ 09142 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 09143 if (pvt->mwisend_fsk) { 09144 #endif 09145 gettimeofday(&now, NULL); 09146 if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) { 09147 pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; 09148 } 09149 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI 09150 } else { /* support for mwisendtype=nofsk */ 09151 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 09152 } 09153 #endif 09154 break; 09155 case MWI_SEND_SPILL: 09156 /* We read some number of bytes. Write an equal amount of data */ 09157 if(0 < num_read) { 09158 if (num_read > pvt->cidlen - pvt->cidpos) 09159 num_read = pvt->cidlen - pvt->cidpos; 09160 res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read); 09161 if (res > 0) { 09162 pvt->cidpos += res; 09163 if (pvt->cidpos >= pvt->cidlen) { 09164 pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP; 09165 } 09166 } else { 09167 ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno)); 09168 goto quit; 09169 } 09170 } 09171 break; 09172 case MWI_SEND_CLEANUP: 09173 /* For now, do nothing */ 09174 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 09175 break; 09176 default: 09177 /* Should not get here, punt*/ 09178 goto quit; 09179 } 09180 } 09181 09182 if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) { 09183 if (pvt->cidspill) { 09184 ast_free(pvt->cidspill); 09185 pvt->cidspill = NULL; 09186 pvt->cidpos = 0; 09187 pvt->cidlen = 0; 09188 } 09189 pvt->mwisendactive = 0; 09190 } 09191 return 0; 09192 quit: 09193 if (pvt->cidspill) { 09194 ast_free(pvt->cidspill); 09195 pvt->cidspill = NULL; 09196 pvt->cidpos = 0; 09197 pvt->cidlen = 0; 09198 } 09199 pvt->mwisendactive = 0; 09200 return -1; 09201 }
| static int mwi_send_process_event | ( | struct dahdi_pvt * | pvt, | |
| int | event | |||
| ) | [static] |
Definition at line 9203 of file chan_dahdi.c.
References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA_WAIT, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
09204 { 09205 int handled = 0; 09206 09207 if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) { 09208 switch (event) { 09209 case DAHDI_EVENT_RINGEROFF: 09210 if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) { 09211 handled = 1; 09212 09213 if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) { 09214 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno)); 09215 if(pvt->cidspill) { 09216 ast_free(pvt->cidspill); 09217 pvt->cidspill = NULL; 09218 } 09219 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 09220 pvt->mwisendactive = 0; 09221 } else { 09222 pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE; 09223 gettimeofday(&pvt->mwisend_data.pause, NULL); 09224 } 09225 } 09226 break; 09227 /* Going off hook, I need to punt this spill */ 09228 case DAHDI_EVENT_RINGOFFHOOK: 09229 if (pvt->cidspill) { 09230 ast_free(pvt->cidspill); 09231 pvt->cidspill = NULL; 09232 pvt->cidpos = 0; 09233 pvt->cidlen = 0; 09234 } 09235 pvt->mwisend_data.mwisend_current = MWI_SEND_DONE; 09236 pvt->mwisendactive = 0; 09237 break; 09238 case DAHDI_EVENT_RINGERON: 09239 case DAHDI_EVENT_HOOKCOMPLETE: 09240 break; 09241 default: 09242 break; 09243 } 09244 } 09245 return handled; 09246 }
| static void* mwi_thread | ( | void * | data | ) | [static] |
Definition at line 8925 of file chan_dahdi.c.
References ast_free, ast_hangup(), AST_LAW, ast_log(), ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_get(), callerid_new(), dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), dahdi_subchannel::dfd, errno, event2str(), EVENT_FLAG_SYSTEM, callerid_state::flags, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitoractive, name, notify_message(), mwi_thread_data::pvt, quit, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, ss_thread(), SUB_REAL, and dahdi_pvt::subs.
Referenced by do_monitor().
08926 { 08927 struct mwi_thread_data *mtd = data; 08928 struct callerid_state *cs; 08929 pthread_t threadid; 08930 int samples = 0; 08931 char *name, *number; 08932 int flags; 08933 int i, res; 08934 unsigned int spill_done = 0; 08935 int spill_result = -1; 08936 08937 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) { 08938 mtd->pvt->mwimonitoractive = 0; 08939 08940 return NULL; 08941 } 08942 08943 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt)); 08944 08945 bump_gains(mtd->pvt); 08946 08947 for (;;) { 08948 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08949 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) { 08950 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08951 goto quit; 08952 } 08953 08954 if (i & DAHDI_IOMUX_SIGEVENT) { 08955 struct ast_channel *chan; 08956 08957 /* If we get an event, screen out events that we do not act on. 08958 * Otherwise, cancel and go to the simple switch to let it deal with it. 08959 */ 08960 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd); 08961 08962 switch (res) { 08963 case DAHDI_EVENT_NEONMWI_ACTIVE: 08964 case DAHDI_EVENT_NEONMWI_INACTIVE: 08965 case DAHDI_EVENT_NONE: 08966 case DAHDI_EVENT_BITSCHANGED: 08967 break; 08968 case DAHDI_EVENT_NOALARM: 08969 mtd->pvt->inalarm = 0; 08970 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel); 08971 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 08972 "Channel: %d\r\n", mtd->pvt->channel); 08973 break; 08974 case DAHDI_EVENT_ALARM: 08975 mtd->pvt->inalarm = 1; 08976 res = get_alarms(mtd->pvt); 08977 handle_alarms(mtd->pvt, res); 08978 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */ 08979 default: 08980 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res)); 08981 callerid_free(cs); 08982 08983 restore_gains(mtd->pvt); 08984 mtd->pvt->ringt = mtd->pvt->ringt_base; 08985 08986 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) { 08987 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) { 08988 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel); 08989 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 08990 if (res < 0) 08991 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel); 08992 ast_hangup(chan); 08993 goto quit; 08994 } 08995 goto quit_no_clean; 08996 08997 } else { 08998 ast_log(LOG_WARNING, "Could not create channel to handle call\n"); 08999 } 09000 } 09001 } else if (i & DAHDI_IOMUX_READ) { 09002 if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) { 09003 if (errno != ELAST) { 09004 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 09005 goto quit; 09006 } 09007 break; 09008 } 09009 samples += res; 09010 if (!spill_done) { 09011 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) { 09012 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 09013 break; 09014 } else if (spill_result) { 09015 spill_done = 1; 09016 } 09017 } else { 09018 /* keep reading data until the energy level drops below the threshold 09019 so we don't get another 'trigger' on the remaining carrier signal 09020 */ 09021 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel) 09022 break; 09023 } 09024 if (samples > (8000 * 4)) /*Termination case - time to give up*/ 09025 break; 09026 } 09027 } 09028 09029 if (spill_result == 1) { 09030 callerid_get(cs, &name, &number, &flags); 09031 if (flags & CID_MSGWAITING) { 09032 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel); 09033 notify_message(mtd->pvt->mailbox, 1); 09034 } else if (flags & CID_NOMSGWAITING) { 09035 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel); 09036 notify_message(mtd->pvt->mailbox, 0); 09037 } else { 09038 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel); 09039 } 09040 } 09041 09042 09043 quit: 09044 callerid_free(cs); 09045 09046 restore_gains(mtd->pvt); 09047 09048 quit_no_clean: 09049 mtd->pvt->mwimonitoractive = 0; 09050 09051 ast_free(mtd); 09052 09053 return NULL; 09054 }
| static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
| unsigned char * | buf, | |||
| int | len, | |||
| int | idx, | |||
| int | linear | |||
| ) | [static] |
Definition at line 7068 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().
07069 { 07070 int sent=0; 07071 int size; 07072 int res; 07073 int fd; 07074 fd = p->subs[idx].dfd; 07075 while (len) { 07076 size = len; 07077 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 07078 size = (linear ? READ_SIZE * 2 : READ_SIZE); 07079 res = write(fd, buf, size); 07080 if (res != size) { 07081 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 07082 return sent; 07083 } 07084 len -= size; 07085 buf += size; 07086 } 07087 return sent; 07088 }
| static int my_getsigstr | ( | struct ast_channel * | chan, | |
| char * | str, | |||
| const char * | term, | |||
| int | ms | |||
| ) | [static] |
Definition at line 7616 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
07617 { 07618 char c; 07619 07620 *str = 0; /* start with empty output buffer */ 07621 for (;;) 07622 { 07623 /* Wait for the first digit (up to specified ms). */ 07624 c = ast_waitfordigit(chan, ms); 07625 /* if timeout, hangup or error, return as such */ 07626 if (c < 1) 07627 return c; 07628 *str++ = c; 07629 *str = 0; 07630 if (strchr(term, c)) 07631 return 1; 07632 } 07633 }
| 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 2940 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_strlen_zero(), context, mailbox, and s.
Referenced by handle_init_event(), mwi_thread(), and ss_thread().
02941 { 02942 char s[sizeof(mwimonitornotify) + 80]; 02943 struct ast_event *event; 02944 char *mailbox, *context; 02945 02946 /* Strip off @default */ 02947 context = mailbox = ast_strdupa(mailbox_full); 02948 strsep(&context, "@"); 02949 if (ast_strlen_zero(context)) 02950 context = "default"; 02951 02952 if (!(event = ast_event_new(AST_EVENT_MWI, 02953 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, 02954 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, 02955 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02956 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot, 02957 AST_EVENT_IE_END))) { 02958 return; 02959 } 02960 02961 ast_event_queue_and_cache(event); 02962 02963 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) { 02964 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot); 02965 ast_safe_system(s); 02966 } 02967 }
| static unsigned int parse_pointcode | ( | const char * | pcstring | ) | [static] |
Definition at line 9858 of file chan_dahdi.c.
Referenced by process_dahdi().
| static int pri_active_dchan_fd | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 4126 of file chan_dahdi.c.
References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, and dahdi_pri::pri.
Referenced by pri_find_principle().
04127 { 04128 int x = -1; 04129 04130 for (x = 0; x < NUM_DCHANS; x++) { 04131 if ((pri->dchans[x] == pri->pri)) 04132 break; 04133 } 04134 04135 return pri->fds[x]; 04136 }
| static int pri_assign_bearer | ( | struct dahdi_pvt * | crv, | |
| struct dahdi_pri * | pri, | |||
| struct dahdi_pvt * | bearer | |||
| ) | [static] |
Definition at line 4092 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().
04093 { 04094 bearer->owner = &inuse; 04095 bearer->realcall = crv; 04096 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd; 04097 if (crv->subs[SUB_REAL].owner) 04098 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd); 04099 crv->bearer = bearer; 04100 crv->call = bearer->call; 04101 crv->pri = pri; 04102 return 0; 04103 }
| static int pri_check_restart | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 12297 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().
12298 { 12299 do { 12300 pri->resetpos++; 12301 } while ((pri->resetpos < pri->numchans) && 12302 (!pri->pvts[pri->resetpos] || 12303 pri->pvts[pri->resetpos]->call || 12304 pri->pvts[pri->resetpos]->resetting)); 12305 if (pri->resetpos < pri->numchans) { 12306 /* Mark the channel as resetting and restart it */ 12307 pri->pvts[pri->resetpos]->resetting = 1; 12308 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos])); 12309 } else { 12310 pri->resetting = 0; 12311 time(&pri->lastreset); 12312 } 12313 return 0; 12314 }
| static int pri_create_spanmap | ( | int | span, | |
| int | trunkgroup, | |||
| int | logicalspan | |||
| ) | [static] |
Definition at line 9845 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.
Referenced by setup_dahdi().
09846 { 09847 if (pris[span].mastertrunkgroup) { 09848 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); 09849 return -1; 09850 } 09851 pris[span].mastertrunkgroup = trunkgroup; 09852 pris[span].prilogicalspan = logicalspan; 09853 return 0; 09854 }
| static int pri_create_trunkgroup | ( | int | trunkgroup, | |
| int * | channels | |||
| ) | [static] |
Definition at line 9780 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().
09781 { 09782 struct dahdi_spaninfo si; 09783 struct dahdi_params p; 09784 int fd; 09785 int span; 09786 int ospan=0; 09787 int x,y; 09788 for (x = 0; x < NUM_SPANS; x++) { 09789 if (pris[x].trunkgroup == trunkgroup) { 09790 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]); 09791 return -1; 09792 } 09793 } 09794 for (y = 0; y < NUM_DCHANS; y++) { 09795 if (!channels[y]) 09796 break; 09797 memset(&si, 0, sizeof(si)); 09798 memset(&p, 0, sizeof(p)); 09799 fd = open("/dev/dahdi/channel", O_RDWR); 09800 if (fd < 0) { 09801 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno)); 09802 return -1; 09803 } 09804 x = channels[y]; 09805 if (ioctl(fd, DAHDI_SPECIFY, &x)) { 09806 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno)); 09807 close(fd); 09808 return -1; 09809 } 09810 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) { 09811 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno)); 09812 return -1; 09813 } 09814 if (ioctl(fd, DAHDI_SPANSTAT, &si)) { 09815 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno)); 09816 close(fd); 09817 return -1; 09818 } 09819 span = p.spanno - 1; 09820 if (pris[span].trunkgroup) { 09821 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup); 09822 close(fd); 09823 return -1; 09824 } 09825 if (pris[span].pvts[0]) { 09826 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1); 09827 close(fd); 09828 return -1; 09829 } 09830 if (!y) { 09831 pris[span].trunkgroup = trunkgroup; 09832 pris[span].offset = channels[y] - p.chanpos; 09833 ospan = span; 09834 } 09835 pris[ospan].dchannels[y] = channels[y]; 09836 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED; 09837 pris[span].span = span + 1; 09838 close(fd); 09839 } 09840 return 0; 09841 }
| static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 12398 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_pri::discardremoteholdretrieval, dahdi_pvt::dnid, do_idle_thread(), dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::dsp_features, DSP_PROGRESS_RINGING, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_pvt::exten, dahdi_pri::fds, ast_channel::hangupcause, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::inservice, inuse, dahdi_pvt::isidlecall, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pri::lastreset, dahdi_pvt::lock, dahdi_pri::lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, manager_event, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needringing, dahdi_pri::numchans, dahdi_pri::overlapdial, dahdi_pvt::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), PRI_CHANNEL, pri_check_restart(), pri_find_crv(), pri_find_dchan(), pri_find_empty_chan(), pri_find_principle(), pri_fixup_principle(), pri_hangup_all(), pri_is_up(), pri_order(), PRI_SPAN, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pvt::rdnis, dahdi_pvt::realcall, redirectingreason2str(), dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, dahdi_pvt::rxgain, S_OR, set_actual_gain(), dahdi_pvt::setup_ack, dahdi_pvt::sig, dahdi_pri::sig, SIG_BRI_PTMP, SIG_FXSKS, dahdi_pri::span, ss_thread(), SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pri::switchtype, dahdi_pri::trunkgroup, dahdi_pvt::txgain, and dahdi_pvt::use_callerid.
Referenced by start_pri().
12399 { 12400 struct dahdi_pri *pri = vpri; 12401 pri_event *e; 12402 struct pollfd fds[NUM_DCHANS]; 12403 int res; 12404 int chanpos = 0; 12405 int x; 12406 int haveidles; 12407 int activeidles; 12408 int nextidle = -1; 12409 struct ast_channel *c; 12410 struct timeval tv, lowest, *next; 12411 struct timeval lastidle = ast_tvnow(); 12412 int doidling=0; 12413 char *cc; 12414 char idlen[80]; 12415 struct ast_channel *idle; 12416 pthread_t p; 12417 time_t t; 12418 int i, which=-1; 12419 int numdchans; 12420 int cause=0; 12421 struct dahdi_pvt *crv; 12422 pthread_t threadid; 12423 char ani2str[6]; 12424 char plancallingnum[256]; 12425 char plancallingani[256]; 12426 char calledtonstr[10]; 12427 12428 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 12429 12430 gettimeofday(&lastidle, NULL); 12431 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) { 12432 /* Need to do idle dialing, check to be sure though */ 12433 cc = strchr(pri->idleext, '@'); 12434 if (cc) { 12435 *cc = '\0'; 12436 cc++; 12437 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext)); 12438 #if 0 12439 /* Extensions may not be loaded yet */ 12440 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL)) 12441 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext); 12442 else 12443 #endif 12444 doidling = 1; 12445 } else 12446 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext); 12447 } 12448 for (;;) { 12449 for (i = 0; i < NUM_DCHANS; i++) { 12450 if (!pri->dchannels[i]) 12451 break; 12452 fds[i].fd = pri->fds[i]; 12453 fds[i].events = POLLIN | POLLPRI; 12454 fds[i].revents = 0; 12455 } 12456 numdchans = i; 12457 time(&t); 12458 ast_mutex_lock(&pri->lock); 12459 if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) { 12460 if (pri->resetting && pri_is_up(pri)) { 12461 if (pri->resetpos < 0) 12462 pri_check_restart(pri); 12463 } else { 12464 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) { 12465 pri->resetting = 1; 12466 pri->resetpos = -1; 12467 } 12468 } 12469 } 12470 /* Look for any idle channels if appropriate */ 12471 if (doidling && pri_is_up(pri)) { 12472 nextidle = -1; 12473 haveidles = 0; 12474 activeidles = 0; 12475 for (x = pri->numchans; x >= 0; x--) { 12476 if (pri->pvts[x] && !pri->pvts[x]->owner && 12477 !pri->pvts[x]->call) { 12478 if (haveidles < pri->minunused) { 12479 haveidles++; 12480 } else if (!pri->pvts[x]->resetting) { 12481 nextidle = x; 12482 break; 12483 } 12484 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) 12485 activeidles++; 12486 } 12487 if (nextidle > -1) { 12488 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) { 12489 /* Don't create a new idle call more than once per second */ 12490 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial); 12491 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause); 12492 if (idle) { 12493 pri->pvts[nextidle]->isidlecall = 1; 12494 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) { 12495 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name); 12496 dahdi_hangup(idle); 12497 } 12498 } else 12499 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen); 12500 lastidle = ast_tvnow(); 12501 } 12502 } else if ((haveidles < pri->minunused) && 12503 (activeidles > pri->minidle)) { 12504 /* Mark something for hangup if there is something 12505 that can be hungup */ 12506 for (x = pri->numchans; x >= 0; x--) { 12507 /* find a candidate channel */ 12508 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) { 12509 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12510 haveidles++; 12511 /* Stop if we have enough idle channels or 12512 can't spare any more active idle ones */ 12513 if ((haveidles >= pri->minunused) || 12514 (activeidles <= pri->minidle)) 12515 break; 12516 } 12517 } 12518 } 12519 } 12520 /* Start with reasonable max */ 12521 lowest = ast_tv(60, 0); 12522 for (i = 0; i < NUM_DCHANS; i++) { 12523 /* Find lowest available d-channel */ 12524 if (!pri->dchannels[i]) 12525 break; 12526 if ((next = pri_schedule_next(pri->dchans[i]))) { 12527 /* We need relative time here */ 12528 tv = ast_tvsub(*next, ast_tvnow()); 12529 if (tv.tv_sec < 0) { 12530 tv = ast_tv(0,0); 12531 } 12532 if (doidling || pri->resetting) { 12533 if (tv.tv_sec > 1) { 12534 tv = ast_tv(1, 0); 12535 } 12536 } else { 12537 if (tv.tv_sec > 60) { 12538 tv = ast_tv(60, 0); 12539 } 12540 } 12541 } else if (doidling || pri->resetting) { 12542 /* Make sure we stop at least once per second if we're 12543 monitoring idle channels */ 12544 tv = ast_tv(1,0); 12545 } else { 12546 /* Don't poll for more than 60 seconds */ 12547 tv = ast_tv(60, 0); 12548 } 12549 if (!i || ast_tvcmp(tv, lowest) < 0) { 12550 lowest = tv; 12551 } 12552 } 12553 ast_mutex_unlock(&pri->lock); 12554 12555 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 12556 pthread_testcancel(); 12557 e = NULL; 12558 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000); 12559 pthread_testcancel(); 12560 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 12561 12562 ast_mutex_lock(&pri->lock); 12563 if (!res) { 12564 for (which = 0; which < NUM_DCHANS; which++) { 12565 if (!pri->dchans[which]) 12566 break; 12567 /* Just a timeout, run the scheduler */ 12568 e = pri_schedule_run(pri->dchans[which]); 12569 if (e) 12570 break; 12571 } 12572 } else if (res > -1) { 12573 for (which = 0; which < NUM_DCHANS; which++) { 12574 if (!pri->dchans[which]) 12575 break; 12576 if (fds[which].revents & POLLPRI) { 12577 /* Check for an event */ 12578 x = 0; 12579 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x); 12580 if (x) { 12581 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); 12582 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent", 12583 "PRIEvent: %s\r\n" 12584 "PRIEventCode: %d\r\n" 12585 "D-channel: %s\r\n" 12586 "Span: %d\r\n", 12587 event2str(x), 12588 x, 12589 pri_order(which), 12590 pri->span 12591 ); 12592 } 12593 /* Keep track of alarm state */ 12594 if (x == DAHDI_EVENT_ALARM) { 12595 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP); 12596 pri_find_dchan(pri); 12597 } else if (x == DAHDI_EVENT_NOALARM) { 12598 pri->dchanavail[which] |= DCHAN_NOTINALARM; 12599 pri_restart(pri->dchans[which]); 12600 } 12601 12602 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span); 12603 } else if (fds[which].revents & POLLIN) { 12604 e = pri_check_event(pri->dchans[which]); 12605 } 12606 if (e) 12607 break; 12608 } 12609 } else if (errno != EINTR) 12610 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno)); 12611 12612 if (e) { 12613 if (pri->debug) 12614 pri_dump_event(pri->dchans[which], e); 12615 12616 if (e->e != PRI_EVENT_DCHAN_DOWN) { 12617 if (!(pri->dchanavail[which] & DCHAN_UP)) { 12618 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span); 12619 } 12620 pri->dchanavail[which] |= DCHAN_UP; 12621 } else if (pri->sig != SIG_BRI_PTMP) { 12622 if (pri->dchanavail[which] & DCHAN_UP) { 12623 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span); 12624 } 12625 pri->dchanavail[which] &= ~DCHAN_UP; 12626 } 12627 12628 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which])) 12629 /* Must be an NFAS group that has the secondary dchan active */ 12630 pri->pri = pri->dchans[which]; 12631 12632 switch (e->e) { 12633 case PRI_EVENT_DCHAN_UP: 12634 if (!pri->pri) pri_find_dchan(pri); 12635 12636 /* Note presense of D-channel */ 12637 time(&pri->lastreset); 12638 12639 /* Restart in 5 seconds */ 12640 if (pri->resetinterval > -1) { 12641 pri->lastreset -= pri->resetinterval; 12642 pri->lastreset += 5; 12643 } 12644 pri->resetting = 0; 12645 /* Take the channels from inalarm condition */ 12646 for (i = 0; i < pri->numchans; i++) 12647 if (pri->pvts[i]) { 12648 pri->pvts[i]->inalarm = 0; 12649 } 12650 break; 12651 case PRI_EVENT_DCHAN_DOWN: 12652 pri_find_dchan(pri); 12653 if (!pri_is_up(pri)) { 12654 pri->resetting = 0; 12655 /* Hangup active channels and put them in alarm mode */ 12656 for (i = 0; i < pri->numchans; i++) { 12657 struct dahdi_pvt *p = pri->pvts[i]; 12658 if (p) { 12659 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 12660 /* T309 is not enabled : hangup calls when alarm occurs */ 12661 if (p->call) { 12662 if (p->pri && p->pri->pri) { 12663 pri_hangup(p->pri->pri, p->call, -1); 12664 pri_destroycall(p->pri->pri, p->call); 12665 p->call = NULL; 12666 } else 12667 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n"); 12668 } 12669 if (p->realcall) { 12670 pri_hangup_all(p->realcall, pri); 12671 } else if (p->owner) 12672 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12673 } 12674 /* For PTMP connections with non persistent layer 2 we want 12675 * to *not* declare inalarm unless there actually is an alarm */ 12676 if (p->sig != SIG_BRI_PTMP) { 12677 p->inalarm = 1; 12678 } 12679 } 12680 } 12681 } 12682 break; 12683 case PRI_EVENT_RESTART: 12684 if (e->restart.channel > -1) { 12685 chanpos = pri_find_principle(pri, e->restart.channel); 12686 if (chanpos < 0) 12687 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 12688 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 12689 else { 12690 ast_verb(3, "B-channel %d/%d restarted on span %d\n", 12691 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span); 12692 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12693 if (pri->pvts[chanpos]->call) { 12694 pri_destroycall(pri->pri, pri->pvts[chanpos]->call); 12695 pri->pvts[chanpos]->call = NULL; 12696 } 12697 /* Force soft hangup if appropriate */ 12698 if (pri->pvts[chanpos]->realcall) 12699 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 12700 else if (pri->pvts[chanpos]->owner) 12701 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12702 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12703 } 12704 } else { 12705 ast_verb(3, "Restart on requested on entire span %d\n", pri->span); 12706 for (x = 0; x < pri->numchans; x++) 12707 if (pri->pvts[x]) { 12708 ast_mutex_lock(&pri->pvts[x]->lock); 12709 if (pri->pvts[x]->call) { 12710 pri_destroycall(pri->pri, pri->pvts[x]->call); 12711 pri->pvts[x]->call = NULL; 12712 } 12713 if (pri->pvts[x]->realcall) 12714 pri_hangup_all(pri->pvts[x]->realcall, pri); 12715 else if (pri->pvts[x]->owner) 12716 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12717 ast_mutex_unlock(&pri->pvts[x]->lock); 12718 } 12719 } 12720 break; 12721 case PRI_EVENT_KEYPAD_DIGIT: 12722 chanpos = pri_find_principle(pri, e->digit.channel); 12723 if (chanpos < 0) { 12724 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 12725 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span); 12726 } else { 12727 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call); 12728 if (chanpos > -1) { 12729 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12730 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */ 12731 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) { 12732 /* how to do that */ 12733 int digitlen = strlen(e->digit.digits); 12734 char digit; 12735 int i; 12736 for (i = 0; i < digitlen; i++) { 12737 digit = e->digit.digits[i]; 12738 { 12739 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 12740 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12741 } 12742 } 12743 } 12744 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12745 } 12746 } 12747 break; 12748 12749 case PRI_EVENT_INFO_RECEIVED: 12750 chanpos = pri_find_principle(pri, e->ring.channel); 12751 if (chanpos < 0) { 12752 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 12753 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 12754 } else { 12755 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call); 12756 if (chanpos > -1) { 12757 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12758 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ 12759 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) { 12760 /* how to do that */ 12761 int digitlen = strlen(e->ring.callednum); 12762 char digit; 12763 int i; 12764 for (i = 0; i < digitlen; i++) { 12765 digit = e->ring.callednum[i]; 12766 { 12767 struct ast_frame f = { AST_FRAME_DTMF, digit, }; 12768 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 12769 } 12770 } 12771 } 12772 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12773 } 12774 } 12775 break; 12776 case PRI_EVENT_RING: 12777 crv = NULL; 12778 if (e->ring.channel == -1) 12779 chanpos = pri_find_empty_chan(pri, 1); 12780 else 12781 chanpos = pri_find_principle(pri, e->ring.channel); 12782 /* if no channel specified find one empty */ 12783 if (chanpos < 0) { 12784 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 12785 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 12786 } else { 12787 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12788 if (pri->pvts[chanpos]->owner) { 12789 if (pri->pvts[chanpos]->call == e->ring.call) { 12790 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 12791 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 12792 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12793 break; 12794 } else { 12795 /* This is where we handle initial glare */ 12796 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n", 12797 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span); 12798 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12799 chanpos = -1; 12800 } 12801 } 12802 if (chanpos > -1) 12803 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12804 } 12805 if ((chanpos < 0) && (e->ring.flexible)) 12806 chanpos = pri_find_empty_chan(pri, 1); 12807 if (chanpos > -1) { 12808 ast_mutex_lock(&pri->pvts[chanpos]->lock); 12809 if (pri->switchtype == PRI_SWITCH_GR303_TMC) { 12810 /* Should be safe to lock CRV AFAIK while bearer is still locked */ 12811 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL)); 12812 if (crv) 12813 ast_mutex_lock(&crv->lock); 12814 if (!crv || crv->owner) { 12815 pri->pvts[chanpos]->call = NULL; 12816 if (crv) { 12817 if (crv->owner) 12818 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV; 12819 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); 12820 } else 12821 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); 12822 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE); 12823 if (crv) 12824 ast_mutex_unlock(&crv->lock); 12825 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 12826 break; 12827 } 12828 } 12829 pri->pvts[chanpos]->call = e->ring.call; 12830 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan); 12831 if (pri->pvts[chanpos]->use_callerid) { 12832 ast_shrink_phone_number(plancallingnum); 12833 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)); 12834 #ifdef PRI_ANI 12835 if (!ast_strlen_zero(e->ring.callingani)) { 12836 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani); 12837 ast_shrink_phone_number(plancallingani); 12838 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani)); 12839 } else { 12840 pri->pvts[chanpos]->cid_ani[0] = '\0'; 12841 } 12842 #endif 12843 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)); 12844 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */ 12845 } else { 12846 pri->pvts[chanpos]->cid_num[0] = '\0'; 12847 pri->pvts[chanpos]->cid_ani[0] = '\0'; 12848 pri->pvts[chanpos]->cid_name[0] = '\0'; 12849 pri->pvts[chanpos]->cid_ton = 0; 12850 } 12851 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri, 12852 e->ring.redirectingnum, e->ring.callingplanrdnis); 12853 /* If immediate=yes go to s|1 */ 12854 if (pri->pvts[chanpos]->immediate) { 12855 ast_verb(3, "Going to extension s|1 because of immediate=yes\n"); 12856 pri->pvts[chanpos]->exten[0] = 's'; 12857 pri->pvts[chanpos]->exten[1] = '\0'; 12858 } 12859 /* Get called number */ 12860 else if (!ast_strlen_zero(e->ring.callednum)) { 12861 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten)); 12862 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 12863 } else if (pri->overlapdial) 12864 pri->pvts[chanpos]->exten[0] = '\0'; 12865 else { 12866 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */ 12867 pri->pvts[chanpos]->exten[0] = 's'; 12868 pri->pvts[chanpos]->exten[1] = '\0'; 12869 } 12870 /* Set DNID on all incoming calls -- even immediate */ 12871 if (!ast_strlen_zero(e->ring.callednum)) 12872 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid)); 12873 /* No number yet, but received "sending complete"? */ 12874 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) { 12875 ast_verb(3, "Going to extension s|1 because of Complete received\n"); 12876 pri->pvts[chanpos]->exten[0] = 's'; 12877 pri->pvts[chanpos]->exten[1] = '\0'; 12878 } 12879 12880 /* Make sure extension exists (or in overlap dial mode, can exist) */ 12881 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) || 12882 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 12883 /* Setup law */ 12884 int law; 12885 if (pri->switchtype != PRI_SWITCH_GR303_TMC) { 12886 /* Set to audio mode at this point */ 12887 law = 1; 12888 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 12889 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno)); 12890 } 12891 if (e->ring.layer1 == PRI_LAYER_1_ALAW) 12892 law = DAHDI_LAW_ALAW; 12893 else 12894 law = DAHDI_LAW_MULAW; 12895 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law); 12896 if (res < 0) 12897 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel); 12898 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law); 12899 if (res < 0) 12900 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel); 12901 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) { 12902 /* Just announce proceeding */ 12903 pri->pvts[chanpos]->proceeding = 1; 12904 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0); 12905 } else { 12906 if (pri->switchtype != PRI_SWITCH_GR303_TMC) 12907 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 12908 else 12909 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1); 12910 } 12911 /* Get the use_callingpres state */ 12912 pri->pvts[chanpos]->callingpres = e->ring.callingpres; 12913 12914 /* Start PBX */ 12915 if (!e->ring.complete 12916 && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) 12917 && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { 12918 /* 12919 * Release the PRI lock while we create the channel 12920 * so other threads can send D channel messages. 12921 */ 12922 ast_mutex_unlock(&pri->lock); 12923 if (crv) { 12924 /* Set bearer and such */ 12925 pri_assign_bearer(crv, pri, pri->pvts[chanpos]); 12926 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 12927 pri->pvts[chanpos]->owner = &inuse; 12928 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel); 12929 } else { 12930 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype); 12931 } 12932 ast_mutex_lock(&pri->lock); 12933 if (c) { 12934 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 12935 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 12936 } 12937 if (e->ring.ani2 >= 0) { 12938 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 12939 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 12940 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 12941 } 12942 12943 #ifdef SUPPORT_USERUSER 12944 if (!ast_strlen_zero(e->ring.useruserinfo)) { 12945 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 12946 } 12947 #endif 12948 12949 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 12950 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 12951 if (e->ring.redirectingreason >= 0) 12952 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 12953 } 12954 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) { 12955 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", 12956 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"), 12957 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 12958 } else { 12959 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 12960 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 12961 if (c) 12962 ast_hangup(c); 12963 else { 12964 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 12965 pri->pvts[chanpos]->call = NULL; 12966 } 12967 } 12968 } else { 12969 /* 12970 * Release the PRI lock while we create the channel 12971 * so other threads can send D channel messages. 12972 */ 12973 ast_mutex_unlock(&pri->lock); 12974 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); 12975 ast_mutex_lock(&pri->lock); 12976 if (c) { 12977 /* 12978 * It is reasonably safe to set the following 12979 * channel variables while the PRI and DAHDI private 12980 * structures are locked. The PBX has not been 12981 * started yet and it is unlikely that any other task 12982 * will do anything with the channel we have just 12983 * created. 12984 */ 12985 if (!ast_strlen_zero(e->ring.callingsubaddr)) { 12986 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr); 12987 } 12988 if (e->ring.ani2 >= 0) { 12989 snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2); 12990 pbx_builtin_setvar_helper(c, "ANI2", ani2str); 12991 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2; 12992 } 12993 12994 #ifdef SUPPORT_USERUSER 12995 if (!ast_strlen_zero(e->ring.useruserinfo)) { 12996 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo); 12997 } 12998 #endif 12999 13000 if (e->ring.redirectingreason >= 0) 13001 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason)); 13002 13003 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan); 13004 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr); 13005 } 13006 if (c && !ast_pbx_start(c)) { 13007 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", 13008 plancallingnum, pri->pvts[chanpos]->exten, 13009 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 13010 13011 dahdi_enable_ec(pri->pvts[chanpos]); 13012 } else { 13013 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 13014 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); 13015 if (c) { 13016 ast_hangup(c); 13017 } else { 13018 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); 13019 pri->pvts[chanpos]->call = NULL; 13020 } 13021 } 13022 } 13023 } else { 13024 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n", 13025 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 13026 pri->pvts[chanpos]->prioffset, pri->span); 13027 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); 13028 pri->pvts[chanpos]->call = NULL; 13029 pri->pvts[chanpos]->exten[0] = '\0'; 13030 } 13031 if (crv) 13032 ast_mutex_unlock(&crv->lock); 13033 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13034 } else { 13035 if (e->ring.flexible) 13036 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION); 13037 else 13038 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL); 13039 } 13040 break; 13041 case PRI_EVENT_RINGING: 13042 chanpos = pri_find_principle(pri, e->ringing.channel); 13043 if (chanpos < 0) { 13044 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 13045 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 13046 } else { 13047 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call); 13048 if (chanpos < 0) { 13049 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 13050 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span); 13051 } else { 13052 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13053 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 13054 dahdi_enable_ec(pri->pvts[chanpos]); 13055 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1; 13056 pri->pvts[chanpos]->alerting = 1; 13057 } else 13058 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n"); 13059 13060 if ( 13061 #ifdef PRI_PROGRESS_MASK 13062 e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE 13063 #else 13064 e->ringing.progress == 8 13065 #endif 13066 ) { 13067 /* Now we can do call progress detection */ 13068 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 13069 /* RINGING detection isn't required because we got ALERTING signal */ 13070 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING); 13071 pri->pvts[chanpos]->dsp_features = 0; 13072 } 13073 } 13074 13075 #ifdef SUPPORT_USERUSER 13076 if (!ast_strlen_zero(e->ringing.useruserinfo)) { 13077 struct ast_channel *owner = pri->pvts[chanpos]->owner; 13078 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13079 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo); 13080 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13081 } 13082 #endif 13083 13084 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13085 } 13086 } 13087 break; 13088 case PRI_EVENT_PROGRESS: 13089 /* Get chan value if e->e is not PRI_EVNT_RINGING */ 13090 chanpos = pri_find_principle(pri, e->proceeding.channel); 13091 if (chanpos > -1) { 13092 if ((!pri->pvts[chanpos]->progress) 13093 #ifdef PRI_PROGRESS_MASK 13094 || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) 13095 #else 13096 || (e->proceeding.progress == 8) 13097 #endif 13098 ) { 13099 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 13100 13101 if (e->proceeding.cause > -1) { 13102 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause); 13103 13104 /* Work around broken, out of spec USER_BUSY cause in a progress message */ 13105 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) { 13106 if (pri->pvts[chanpos]->owner) { 13107 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n"); 13108 13109 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause; 13110 f.subclass = AST_CONTROL_BUSY; 13111 } 13112 } 13113 } 13114 13115 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13116 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n", 13117 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 13118 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 13119 if ( 13120 #ifdef PRI_PROGRESS_MASK 13121 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE 13122 #else 13123 e->proceeding.progress == 8 13124 #endif 13125 ) { 13126 /* Now we can do call progress detection */ 13127 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 13128 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 13129 pri->pvts[chanpos]->dsp_features = 0; 13130 } 13131 /* Bring voice path up */ 13132 f.subclass = AST_CONTROL_PROGRESS; 13133 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 13134 } 13135 pri->pvts[chanpos]->progress = 1; 13136 pri->pvts[chanpos]->dialing = 0; 13137 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13138 } 13139 } 13140 break; 13141 case PRI_EVENT_PROCEEDING: 13142 chanpos = pri_find_principle(pri, e->proceeding.channel); 13143 if (chanpos > -1) { 13144 if (!pri->pvts[chanpos]->proceeding) { 13145 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 13146 13147 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13148 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n", 13149 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span); 13150 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 13151 if ( 13152 #ifdef PRI_PROGRESS_MASK 13153 e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE 13154 #else 13155 e->proceeding.progress == 8 13156 #endif 13157 ) { 13158 /* Now we can do call progress detection */ 13159 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 13160 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 13161 pri->pvts[chanpos]->dsp_features = 0; 13162 } 13163 /* Bring voice path up */ 13164 f.subclass = AST_CONTROL_PROGRESS; 13165 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 13166 } 13167 pri->pvts[chanpos]->proceeding = 1; 13168 pri->pvts[chanpos]->dialing = 0; 13169 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13170 } 13171 } 13172 break; 13173 case PRI_EVENT_FACNAME: 13174 chanpos = pri_find_principle(pri, e->facname.channel); 13175 if (chanpos < 0) { 13176 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 13177 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 13178 } else { 13179 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call); 13180 if (chanpos < 0) { 13181 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 13182 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span); 13183 } else { 13184 /* Re-use *69 field for PRI */ 13185 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13186 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num)); 13187 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name)); 13188 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1; 13189 dahdi_enable_ec(pri->pvts[chanpos]); 13190 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13191 } 13192 } 13193 break; 13194 case PRI_EVENT_ANSWER: 13195 chanpos = pri_find_principle(pri, e->answer.channel); 13196 if (chanpos < 0) { 13197 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 13198 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 13199 } else { 13200 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call); 13201 if (chanpos < 0) { 13202 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 13203 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span); 13204 } else { 13205 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13206 /* Now we can do call progress detection */ 13207 13208 /* We changed this so it turns on the DSP no matter what... progress or no progress. 13209 * By this time, we need DTMF detection and other features that were previously disabled 13210 * -- Matt F */ 13211 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) { 13212 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features); 13213 pri->pvts[chanpos]->dsp_features = 0; 13214 } 13215 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) { 13216 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n"); 13217 x = DAHDI_START; 13218 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 13219 if (res < 0) { 13220 if (errno != EINPROGRESS) { 13221 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 13222 } 13223 } 13224 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) { 13225 pri->pvts[chanpos]->dialing = 1; 13226 /* Send any "w" waited stuff */ 13227 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop); 13228 if (res < 0) { 13229 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno)); 13230 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 13231 } else 13232 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr); 13233 13234 pri->pvts[chanpos]->dop.dialstr[0] = '\0'; 13235 } else if (pri->pvts[chanpos]->confirmanswer) { 13236 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel); 13237 } else { 13238 pri->pvts[chanpos]->dialing = 0; 13239 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1; 13240 /* Enable echo cancellation if it's not on already */ 13241 dahdi_enable_ec(pri->pvts[chanpos]); 13242 } 13243 13244 #ifdef SUPPORT_USERUSER 13245 if (!ast_strlen_zero(e->answer.useruserinfo)) { 13246 struct ast_channel *owner = pri->pvts[chanpos]->owner; 13247 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13248 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo); 13249 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13250 } 13251 #endif 13252 13253 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13254 } 13255 } 13256 break; 13257 case PRI_EVENT_HANGUP: 13258 chanpos = pri_find_principle(pri, e->hangup.channel); 13259 if (chanpos < 0) { 13260 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 13261 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 13262 } else { 13263 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 13264 if (chanpos > -1) { 13265 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13266 if (!pri->pvts[chanpos]->alreadyhungup) { 13267 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */ 13268 pri->pvts[chanpos]->alreadyhungup = 1; 13269 if (pri->pvts[chanpos]->realcall) 13270 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 13271 else if (pri->pvts[chanpos]->owner) { 13272 /* Queue a BUSY instead of a hangup if our cause is appropriate */ 13273 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 13274 switch (pri->pvts[chanpos]->owner->_state) { 13275 case AST_STATE_BUSY: 13276 case AST_STATE_UP: 13277 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 13278 break; 13279 default: 13280 switch (e->hangup.cause) { 13281 case PRI_CAUSE_USER_BUSY: 13282 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 13283 break; 13284 case PRI_CAUSE_CALL_REJECTED: 13285 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 13286 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 13287 case PRI_CAUSE_SWITCH_CONGESTION: 13288 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 13289 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 13290 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 13291 break; 13292 default: 13293 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 13294 } 13295 break; 13296 } 13297 } 13298 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n", 13299 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause); 13300 } else { 13301 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 13302 pri->pvts[chanpos]->call = NULL; 13303 } 13304 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 13305 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 13306 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 13307 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 13308 pri->pvts[chanpos]->resetting = 1; 13309 } 13310 if (e->hangup.aoc_units > -1) 13311 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 13312 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 13313 13314 #ifdef SUPPORT_USERUSER 13315 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) { 13316 struct ast_channel *owner = pri->pvts[chanpos]->owner; 13317 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13318 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 13319 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13320 } 13321 #endif 13322 13323 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13324 } else { 13325 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 13326 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 13327 } 13328 } 13329 break; 13330 #ifndef PRI_EVENT_HANGUP_REQ 13331 #error please update libpri 13332 #endif 13333 case PRI_EVENT_HANGUP_REQ: 13334 chanpos = pri_find_principle(pri, e->hangup.channel); 13335 if (chanpos < 0) { 13336 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 13337 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 13338 } else { 13339 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 13340 if (chanpos > -1) { 13341 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13342 if (pri->pvts[chanpos]->realcall) 13343 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 13344 else if (pri->pvts[chanpos]->owner) { 13345 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause; 13346 switch (pri->pvts[chanpos]->owner->_state) { 13347 case AST_STATE_BUSY: 13348 case AST_STATE_UP: 13349 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 13350 break; 13351 default: 13352 switch (e->hangup.cause) { 13353 case PRI_CAUSE_USER_BUSY: 13354 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1; 13355 break; 13356 case PRI_CAUSE_CALL_REJECTED: 13357 case PRI_CAUSE_NETWORK_OUT_OF_ORDER: 13358 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION: 13359 case PRI_CAUSE_SWITCH_CONGESTION: 13360 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER: 13361 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE: 13362 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1; 13363 break; 13364 default: 13365 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 13366 break; 13367 } 13368 break; 13369 } 13370 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); 13371 if (e->hangup.aoc_units > -1) 13372 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", 13373 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); 13374 } else { 13375 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); 13376 pri->pvts[chanpos]->call = NULL; 13377 } 13378 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) { 13379 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n", 13380 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 13381 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); 13382 pri->pvts[chanpos]->resetting = 1; 13383 } 13384 13385 #ifdef SUPPORT_USERUSER 13386 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 13387 struct ast_channel *owner = pri->pvts[chanpos]->owner; 13388 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13389 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 13390 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13391 } 13392 #endif 13393 13394 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13395 } else { 13396 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); 13397 } 13398 } 13399 break; 13400 case PRI_EVENT_HANGUP_ACK: 13401 chanpos = pri_find_principle(pri, e->hangup.channel); 13402 if (chanpos < 0) { 13403 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 13404 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 13405 } else { 13406 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call); 13407 if (chanpos > -1) { 13408 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13409 pri->pvts[chanpos]->call = NULL; 13410 pri->pvts[chanpos]->resetting = 0; 13411 if (pri->pvts[chanpos]->owner) { 13412 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span); 13413 } 13414 13415 #ifdef SUPPORT_USERUSER 13416 if (!ast_strlen_zero(e->hangup.useruserinfo)) { 13417 struct ast_channel *owner = pri->pvts[chanpos]->owner; 13418 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13419 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo); 13420 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13421 } 13422 #endif 13423 13424 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13425 } 13426 } 13427 break; 13428 case PRI_EVENT_CONFIG_ERR: 13429 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err); 13430 break; 13431 case PRI_EVENT_RESTART_ACK: 13432 chanpos = pri_find_principle(pri, e->restartack.channel); 13433 if (chanpos < 0) { 13434 /* Sometime switches (e.g. I421 / British Telecom) don't give us the 13435 channel number, so we have to figure it out... This must be why 13436 everybody resets exactly a channel at a time. */ 13437 for (x = 0; x < pri->numchans; x++) { 13438 if (pri->pvts[x] && pri->pvts[x]->resetting) { 13439 chanpos = x; 13440 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13441 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 13442 pri->pvts[chanpos]->prioffset, pri->span); 13443 if (pri->pvts[chanpos]->realcall) 13444 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 13445 else if (pri->pvts[chanpos]->owner) { 13446 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 13447 pri->pvts[chanpos]->prioffset, pri->span); 13448 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 13449 } 13450 pri->pvts[chanpos]->resetting = 0; 13451 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 13452 pri->pvts[chanpos]->prioffset, pri->span); 13453 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13454 if (pri->resetting) 13455 pri_check_restart(pri); 13456 break; 13457 } 13458 } 13459 if (chanpos < 0) { 13460 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 13461 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 13462 } 13463 } else { 13464 if (pri->pvts[chanpos]) { 13465 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13466 if (pri->pvts[chanpos]->realcall) 13467 pri_hangup_all(pri->pvts[chanpos]->realcall, pri); 13468 else if (pri->pvts[chanpos]->owner) { 13469 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n", 13470 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span); 13471 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 13472 } 13473 pri->pvts[chanpos]->resetting = 0; 13474 pri->pvts[chanpos]->inservice = 1; 13475 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 13476 pri->pvts[chanpos]->prioffset, pri->span); 13477 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13478 if (pri->resetting) 13479 pri_check_restart(pri); 13480 } 13481 } 13482 break; 13483 case PRI_EVENT_SETUP_ACK: 13484 chanpos = pri_find_principle(pri, e->setup_ack.channel); 13485 if (chanpos < 0) { 13486 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 13487 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span); 13488 } else { 13489 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call); 13490 if (chanpos > -1) { 13491 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13492 pri->pvts[chanpos]->setup_ack = 1; 13493 /* Send any queued digits */ 13494 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) { 13495 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]); 13496 pri_information(pri->pri, pri->pvts[chanpos]->call, 13497 pri->pvts[chanpos]->dialdest[x]); 13498 } 13499 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13500 } else 13501 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel); 13502 } 13503 break; 13504 case PRI_EVENT_NOTIFY: 13505 chanpos = pri_find_principle(pri, e->notify.channel); 13506 if (chanpos < 0) { 13507 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n", 13508 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span); 13509 } else if (!pri->discardremoteholdretrieval) { 13510 struct ast_frame f = { AST_FRAME_CONTROL, }; 13511 ast_mutex_lock(&pri->pvts[chanpos]->lock); 13512 switch (e->notify.info) { 13513 case PRI_NOTIFY_REMOTE_HOLD: 13514 f.subclass = AST_CONTROL_HOLD; 13515 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 13516 break; 13517 case PRI_NOTIFY_REMOTE_RETRIEVAL: 13518 f.subclass = AST_CONTROL_UNHOLD; 13519 dahdi_queue_frame(pri->pvts[chanpos], &f, pri); 13520 break; 13521 } 13522 ast_mutex_unlock(&pri->pvts[chanpos]->lock); 13523 } 13524 break; 13525 default: 13526 ast_debug(1, "Event: %d\n", e->e); 13527 } 13528 } 13529 ast_mutex_unlock(&pri->lock); 13530 } 13531 /* Never reached */ 13532 return NULL; 13533 }
Definition at line 12033 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 4140 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, dahdi_pri::pri, dahdi_pri::sig, and SIG_BRI_PTMP.
Referenced by pri_dchannel().
04141 { 04142 int oldslot = -1; 04143 struct pri *old; 04144 int newslot = -1; 04145 int x; 04146 old = pri->pri; 04147 for (x = 0; x < NUM_DCHANS; x++) { 04148 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0)) 04149 newslot = x; 04150 if (pri->dchans[x] == old) { 04151 oldslot = x; 04152 } 04153 } 04154 if (newslot < 0) { 04155 newslot = 0; 04156 /* This is annoying to see on non persistent layer 2 connections. Let's not complain in that case */ 04157 if (pri->sig != SIG_BRI_PTMP) { 04158 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n", 04159 pri->dchannels[newslot]); 04160 } 04161 } 04162 if (old && (oldslot != newslot)) 04163 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n", 04164 pri->dchannels[oldslot], pri->dchannels[newslot]); 04165 pri->pri = pri->dchans[newslot]; 04166 return 0; 04167 }
| static int pri_find_empty_chan | ( | struct dahdi_pri * | pri, | |
| int | backwards | |||
| ) | [static] |
Definition at line 10808 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().
10809 { 10810 int x; 10811 if (backwards) 10812 x = pri->numchans; 10813 else 10814 x = 0; 10815 for (;;) { 10816 if (backwards && (x < 0)) 10817 break; 10818 if (!backwards && (x >= pri->numchans)) 10819 break; 10820 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) { 10821 ast_debug(1, "Found empty available channel %d/%d\n", 10822 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset); 10823 return x; 10824 } 10825 if (backwards) 10826 x--; 10827 else 10828 x++; 10829 } 10830 return -1; 10831 }
| static int pri_find_principle | ( | struct dahdi_pri * | pri, | |
| int | channel | |||
| ) | [static] |
Definition at line 12047 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().
12048 { 12049 int x; 12050 int span = PRI_SPAN(channel); 12051 int spanfd; 12052 struct dahdi_params param; 12053 int principle = -1; 12054 int explicit = PRI_EXPLICIT(channel); 12055 channel = PRI_CHANNEL(channel); 12056 12057 if (!explicit) { 12058 spanfd = pri_active_dchan_fd(pri); 12059 memset(¶m, 0, sizeof(param)); 12060 if (ioctl(spanfd, DAHDI_GET_PARAMS, ¶m)) 12061 return -1; 12062 span = pris[param.spanno - 1].prilogicalspan; 12063 } 12064 12065 for (x = 0; x < pri->numchans; x++) { 12066 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) { 12067 principle = x; 12068 break; 12069 } 12070 } 12071 12072 return principle; 12073 }
| static int pri_fixup_principle | ( | struct dahdi_pri * | pri, | |
| int | principle, | |||
| q931_call * | c | |||
| ) | [static] |
Definition at line 12077 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().
12078 { 12079 int x; 12080 struct dahdi_pvt *crv; 12081 if (!c) { 12082 if (principle < 0) 12083 return -1; 12084 return principle; 12085 } 12086 if ((principle > -1) && 12087 (principle < pri->numchans) && 12088 (pri->pvts[principle]) && 12089 (pri->pvts[principle]->call == c)) 12090 return principle; 12091 /* First, check for other bearers */ 12092 for (x = 0; x < pri->numchans; x++) { 12093 if (!pri->pvts[x]) 12094 continue; 12095 if (pri->pvts[x]->call == c) { 12096 /* Found our call */ 12097 if (principle != x) { 12098 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x]; 12099 12100 ast_verb(3, "Moving call from channel %d to channel %d\n", 12101 old->channel, new->channel); 12102 if (new->owner) { 12103 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n", 12104 old->channel, new->channel, new->channel); 12105 return -1; 12106 } 12107 /* Fix it all up now */ 12108 new->owner = old->owner; 12109 old->owner = NULL; 12110 if (new->owner) { 12111 ast_string_field_build(new->owner, name, 12112 "DAHDI/%d:%d-%d", pri->trunkgroup, 12113 new->channel, 1); 12114 new->owner->tech_pvt = new; 12115 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd); 12116 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner; 12117 old->subs[SUB_REAL].owner = NULL; 12118 } else 12119 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); 12120 new->call = old->call; 12121 old->call = NULL; 12122 12123 /* Copy any DSP that may be present */ 12124 new->dsp = old->dsp; 12125 new->dsp_features = old->dsp_features; 12126 old->dsp = NULL; 12127 old->dsp_features = 0; 12128 } 12129 return principle; 12130 } 12131 } 12132 /* Now check for a CRV with no bearer */ 12133 crv = pri->crvs; 12134 while (crv) { 12135 if (crv->call == c) { 12136 /* This is our match... Perform some basic checks */ 12137 if (crv->bearer) 12138 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n"); 12139 else if (pri->pvts[principle]->owner) 12140 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n"); 12141 else { 12142 /* Looks good. Drop the pseudo channel now, clear up the assignment, and 12143 wakeup the potential sleeper */ 12144 dahdi_close_sub(crv, SUB_REAL); 12145 pri->pvts[principle]->call = crv->call; 12146 pri_assign_bearer(crv, pri, pri->pvts[principle]); 12147 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n", 12148 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset, 12149 pri->trunkgroup, crv->channel); 12150 wakeup_sub(crv, SUB_REAL, pri); 12151 } 12152 return principle; 12153 } 12154 crv = crv->next; 12155 } 12156 ast_log(LOG_WARNING, "Call specified, but not found?\n"); 12157 return -1; 12158 }
Definition at line 1431 of file chan_dahdi.c.
References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, and dahdi_pri::master.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_send_keypad_facility_exec(), dahdi_write(), and ss_thread().
01432 { 01433 int res; 01434 /* Grab the lock first */ 01435 do { 01436 res = ast_mutex_trylock(&pri->lock); 01437 if (res) { 01438 DEADLOCK_AVOIDANCE(&pvt->lock); 01439 } 01440 } while (res); 01441 /* Then break the poll */ 01442 if (pri->master != AST_PTHREADT_NULL) 01443 pthread_kill(pri->master, SIGURG); 01444 return 0; 01445 }
Definition at line 12318 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().
12319 { 12320 int x; 12321 int redo; 12322 ast_mutex_unlock(&pri->lock); 12323 ast_mutex_lock(&p->lock); 12324 do { 12325 redo = 0; 12326 for (x = 0; x < 3; x++) { 12327 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) { 12328 redo++; 12329 DEADLOCK_AVOIDANCE(&p->lock); 12330 } 12331 if (p->subs[x].owner) { 12332 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED); 12333 ast_channel_unlock(p->subs[x].owner); 12334 } 12335 } 12336 } while (redo); 12337 ast_mutex_unlock(&p->lock); 12338 ast_mutex_lock(&pri->lock); 12339 return 0; 12340 }
| static int pri_is_up | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 4080 of file chan_dahdi.c.
References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.
Referenced by mkintf(), and pri_dchannel().
04081 { 04082 int x; 04083 for (x = 0; x < NUM_DCHANS; x++) { 04084 if (pri->dchanavail[x] == DCHAN_AVAILABLE) 04085 return 1; 04086 } 04087 return 0; 04088 }
| static char* pri_order | ( | int | level | ) | [static] |
Definition at line 4107 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 569 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_pri::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_send_keypad_facility_exec(), dahdi_write(), and ss_thread().
00570 { 00571 ast_mutex_unlock(&pri->lock); 00572 }
| static int pri_resolve_span | ( | int * | span, | |
| int | channel, | |||
| int | offset, | |||
| struct dahdi_spaninfo * | si | |||
| ) | [static] |
Definition at line 9732 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().
09733 { 09734 int x; 09735 int trunkgroup; 09736 /* Get appropriate trunk group if there is one */ 09737 trunkgroup = pris[*span].mastertrunkgroup; 09738 if (trunkgroup) { 09739 /* Select a specific trunk group */ 09740 for (x = 0; x < NUM_SPANS; x++) { 09741 if (pris[x].trunkgroup == trunkgroup) { 09742 *span = x; 09743 return 0; 09744 } 09745 } 09746 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup); 09747 *span = -1; 09748 } else { 09749 if (pris[*span].trunkgroup) { 09750 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup); 09751 *span = -1; 09752 } else if (pris[*span].mastertrunkgroup) { 09753 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup); 09754 *span = -1; 09755 } else { 09756 if (si->totalchans == 31) { 09757 /* E1 */ 09758 pris[*span].dchannels[0] = 16 + offset; 09759 } else if (si->totalchans == 24) { 09760 /* T1 or J1 */ 09761 pris[*span].dchannels[0] = 24 + offset; 09762 } else if (si->totalchans == 3) { 09763 /* BRI */ 09764 pris[*span].dchannels[0] = 3 + offset; 09765 } else { 09766 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); 09767 *span = -1; 09768 return 0; 09769 } 09770 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED; 09771 pris[*span].offset = offset; 09772 pris[*span].span = *span + 1; 09773 } 09774 } 09775 return 0; 09776 }
| static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
| const char * | cat, | |||
| struct ast_variable * | v, | |||
| int | reload, | |||
| int | options | |||
| ) | [static] |
Definition at line 16096 of file chan_dahdi.c.
References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), AST_MAX_EXTENSION, ast_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_CHAN_MAPPING_LOGICAL, DAHDI_CHAN_MAPPING_PHYSICAL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, dahdi_pri::discardremoteholdretrieval, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_ss7::flags, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_ss7::internationalprefix, dahdi_pri::internationalprefix, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, ast_variable::lineno, linkset_addsigchan(), 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_pri::qsigchannelmapping, dahdi_pvt::radio, distRingData::range, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, SIG_SS7, dahdi_chan_conf::smdi_port, dahdi_chan_conf::ss7, SS7_NAI_DYNAMIC, ss7_resolve_linkset(), dahdi_pvt::stripmsd, dahdi_ss7::subscriberprefix, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, timer, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_ss7::unknownprefix, dahdi_pri::unknownprefix, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.
Referenced by setup_dahdi().
16097 { 16098 struct dahdi_pvt *tmp; 16099 int y; 16100 int found_pseudo = 0; 16101 char dahdichan[MAX_CHANLIST_LEN] = {}; 16102 16103 for (; v; v = v->next) { 16104 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 16105 continue; 16106 16107 /* must have parkinglot in confp before build_channels is called */ 16108 if (!strcasecmp(v->name, "parkinglot")) { 16109 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot)); 16110 } 16111 16112 /* Create the interface list */ 16113 if (!strcasecmp(v->name, "channel") 16114 #ifdef HAVE_PRI 16115 || !strcasecmp(v->name, "crv") 16116 #endif 16117 ) { 16118 int iscrv; 16119 if (options & PROC_DAHDI_OPT_NOCHAN) { 16120 ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value); 16121 continue; 16122 } 16123 iscrv = !strcasecmp(v->name, "crv"); 16124 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 16125 return -1; 16126 ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value); 16127 } else if (!strcasecmp(v->name, "buffers")) { 16128 int res; 16129 char policy[21] = ""; 16130 16131 res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy); 16132 if (res != 2) { 16133 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 16134 confp->chan.buf_no = numbufs; 16135 continue; 16136 } 16137 if (confp->chan.buf_no < 0) 16138 confp->chan.buf_no = numbufs; 16139 if (!strcasecmp(policy, "full")) { 16140 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 16141 } else if (!strcasecmp(policy, "immediate")) { 16142 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 16143 #ifdef HAVE_DAHDI_HALF_FULL 16144 } else if (!strcasecmp(policy, "half_full")) { 16145 confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL; 16146 #endif 16147 } else { 16148 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 16149 } 16150 } else if (!strcasecmp(v->name, "faxbuffers")) { 16151 int res; 16152 char policy[21] = ""; 16153 16154 res = sscanf(v->value, "%30d,%20s", &confp->chan.faxbuf_no, policy); 16155 if (res != 2) { 16156 ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n"); 16157 confp->chan.faxbuf_no = numbufs; 16158 continue; 16159 } 16160 confp->chan.usefaxbuffers = 1; 16161 if (confp->chan.faxbuf_no < 0) 16162 confp->chan.faxbuf_no = numbufs; 16163 if (!strcasecmp(policy, "full")) { 16164 confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL; 16165 } else if (!strcasecmp(policy, "immediate")) { 16166 confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE; 16167 } else { 16168 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 16169 confp->chan.usefaxbuffers = 0; 16170 } 16171 } else if (!strcasecmp(v->name, "dahdichan")) { 16172 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 16173 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 16174 usedistinctiveringdetection = ast_true(v->value); 16175 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 16176 distinctiveringaftercid = ast_true(v->value); 16177 } else if (!strcasecmp(v->name, "dring1context")) { 16178 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData)); 16179 } else if (!strcasecmp(v->name, "dring2context")) { 16180 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData)); 16181 } else if (!strcasecmp(v->name, "dring3context")) { 16182 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData)); 16183 } else if (!strcasecmp(v->name, "dring1range")) { 16184 confp->chan.drings.ringnum[0].range = atoi(v->value); 16185 } else if (!strcasecmp(v->name, "dring2range")) { 16186 confp->chan.drings.ringnum[1].range = atoi(v->value); 16187 } else if (!strcasecmp(v->name, "dring3range")) { 16188 confp->chan.drings.ringnum[2].range = atoi(v->value); 16189 } else if (!strcasecmp(v->name, "dring1")) { 16190 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]); 16191 } else if (!strcasecmp(v->name, "dring2")) { 16192 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]); 16193 } else if (!strcasecmp(v->name, "dring3")) { 16194 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]); 16195 } else if (!strcasecmp(v->name, "usecallerid")) { 16196 confp->chan.use_callerid = ast_true(v->value); 16197 } else if (!strcasecmp(v->name, "cidsignalling")) { 16198 if (!strcasecmp(v->value, "bell")) 16199 confp->chan.cid_signalling = CID_SIG_BELL; 16200 else if (!strcasecmp(v->value, "v23")) 16201 confp->chan.cid_signalling = CID_SIG_V23; 16202 else if (!strcasecmp(v->value, "dtmf")) 16203 confp->chan.cid_signalling = CID_SIG_DTMF; 16204 else if (!strcasecmp(v->value, "smdi")) 16205 confp->chan.cid_signalling = CID_SIG_SMDI; 16206 else if (!strcasecmp(v->value, "v23_jp")) 16207 confp->chan.cid_signalling = CID_SIG_V23_JP; 16208 else if (ast_true(v->value)) 16209 confp->chan.cid_signalling = CID_SIG_BELL; 16210 } else if (!strcasecmp(v->name, "cidstart")) { 16211 if (!strcasecmp(v->value, "ring")) 16212 confp->chan.cid_start = CID_START_RING; 16213 else if (!strcasecmp(v->value, "polarity_in")) 16214 confp->chan.cid_start = CID_START_POLARITY_IN; 16215 else if (!strcasecmp(v->value, "polarity")) 16216 confp->chan.cid_start = CID_START_POLARITY; 16217 else if (ast_true(v->value)) 16218 confp->chan.cid_start = CID_START_RING; 16219 } else if (!strcasecmp(v->name, "threewaycalling")) { 16220 confp->chan.threewaycalling = ast_true(v->value); 16221 } else if (!strcasecmp(v->name, "cancallforward")) { 16222 confp->chan.cancallforward = ast_true(v->value); 16223 } else if (!strcasecmp(v->name, "relaxdtmf")) { 16224 if (ast_true(v->value)) 16225 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 16226 else 16227 confp->chan.dtmfrelax = 0; 16228 } else if (!strcasecmp(v->name, "mailbox")) { 16229 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 16230 } else if (!strcasecmp(v->name, "hasvoicemail")) { 16231 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 16232 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 16233 } 16234 } else if (!strcasecmp(v->name, "adsi")) { 16235 confp->chan.adsi = ast_true(v->value); 16236 } else if (!strcasecmp(v->name, "usesmdi")) { 16237 confp->chan.use_smdi = ast_true(v->value); 16238 } else if (!strcasecmp(v->name, "smdiport")) { 16239 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 16240 } else if (!strcasecmp(v->name, "transfer")) { 16241 confp->chan.transfer = ast_true(v->value); 16242 } else if (!strcasecmp(v->name, "canpark")) { 16243 confp->chan.canpark = ast_true(v->value); 16244 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 16245 confp->chan.echocanbridged = ast_true(v->value); 16246 } else if (!strcasecmp(v->name, "busydetect")) { 16247 confp->chan.busydetect = ast_true(v->value); 16248 } else if (!strcasecmp(v->name, "busycount")) { 16249 confp->chan.busycount = atoi(v->value); 16250 } else if (!strcasecmp(v->name, "busypattern")) { 16251 if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) { 16252 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno); 16253 } 16254 } else if (!strcasecmp(v->name, "callprogress")) { 16255 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS; 16256 if (ast_true(v->value)) 16257 confp->chan.callprogress |= CALLPROGRESS_PROGRESS; 16258 } else if (!strcasecmp(v->name, "waitfordialtone")) { 16259 confp->chan.waitfordialtone = atoi(v->value); 16260 } else if (!strcasecmp(v->name, "faxdetect")) { 16261 confp->chan.callprogress &= ~CALLPROGRESS_FAX; 16262 if (!strcasecmp(v->value, "incoming")) { 16263 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING; 16264 } else if (!strcasecmp(v->value, "outgoing")) { 16265 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING; 16266 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 16267 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING; 16268 } else if (!strcasecmp(v->name, "echocancel")) { 16269 process_echocancel(confp, v->value, v->lineno); 16270 } else if (!strcasecmp(v->name, "echotraining")) { 16271 if (sscanf(v->value, "%30d", &y) == 1) { 16272 if ((y < 10) || (y > 4000)) { 16273 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno); 16274 } else { 16275 confp->chan.echotraining = y; 16276 } 16277 } else if (ast_true(v->value)) { 16278 confp->chan.echotraining = 400; 16279 } else 16280 confp->chan.echotraining = 0; 16281 } else if (!strcasecmp(v->name, "hidecallerid")) { 16282 confp->chan.hidecallerid = ast_true(v->value); 16283 } else if (!strcasecmp(v->name, "hidecalleridname")) { 16284 confp->chan.hidecalleridname = ast_true(v->value); 16285 } else if (!strcasecmp(v->name, "pulsedial")) { 16286 confp->chan.pulse = ast_true(v->value); 16287 } else if (!strcasecmp(v->name, "callreturn")) { 16288 confp->chan.callreturn = ast_true(v->value); 16289 } else if (!strcasecmp(v->name, "callwaiting")) { 16290 confp->chan.callwaiting = ast_true(v->value); 16291 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 16292 confp->chan.callwaitingcallerid = ast_true(v->value); 16293 } else if (!strcasecmp(v->name, "context")) { 16294 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 16295 } else if (!strcasecmp(v->name, "language")) { 16296 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 16297 } else if (!strcasecmp(v->name, "progzone")) { 16298 ast_copy_string(progzone, v->value, sizeof(progzone)); 16299 } else if (!strcasecmp(v->name, "mohinterpret") 16300 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 16301 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 16302 } else if (!strcasecmp(v->name, "mohsuggest")) { 16303 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 16304 } else if (!strcasecmp(v->name, "parkinglot")) { 16305 ast_copy_string(parkinglot, v->value, sizeof(parkinglot)); 16306 } else if (!strcasecmp(v->name, "stripmsd")) { 16307 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name); 16308 confp->chan.stripmsd = atoi(v->value); 16309 } else if (!strcasecmp(v->name, "jitterbuffers")) { 16310 numbufs = atoi(v->value); 16311 } else if (!strcasecmp(v->name, "group")) { 16312 confp->chan.group = ast_get_group(v->value); 16313 } else if (!strcasecmp(v->name, "callgroup")) { 16314 if (!strcasecmp(v->value, "none")) 16315 confp->chan.callgroup = 0; 16316 else 16317 confp->chan.callgroup = ast_get_group(v->value); 16318 } else if (!strcasecmp(v->name, "pickupgroup")) { 16319 if (!strcasecmp(v->value, "none")) 16320 confp->chan.pickupgroup = 0; 16321 else 16322 confp->chan.pickupgroup = ast_get_group(v->value); 16323 } else if (!strcasecmp(v->name, "setvar")) { 16324 char *varname = ast_strdupa(v->value), *varval = NULL; 16325 struct ast_variable *tmpvar; 16326 if (varname && (varval = strchr(varname, '='))) { 16327 *varval++ = '\0'; 16328 if ((tmpvar = ast_variable_new(varname, varval, ""))) { 16329 tmpvar->next = confp->chan.vars; 16330 confp->chan.vars = tmpvar; 16331 } 16332 } 16333 } else if (!strcasecmp(v->name, "immediate")) { 16334 confp->chan.immediate = ast_true(v->value); 16335 } else if (!strcasecmp(v->name, "transfertobusy")) { 16336 confp->chan.transfertobusy = ast_true(v->value); 16337 } else if (!strcasecmp(v->name, "mwimonitor")) { 16338 confp->chan.mwimonitor_neon = 0; 16339 confp->chan.mwimonitor_fsk = 0; 16340 confp->chan.mwimonitor_rpas = 0; 16341 if (strcasestr(v->value, "fsk")) { 16342 confp->chan.mwimonitor_fsk = 1; 16343 } 16344 if (strcasestr(v->value, "rpas")) { 16345 confp->chan.mwimonitor_rpas = 1; 16346 } 16347 if (strcasestr(v->value, "neon")) { 16348 confp->chan.mwimonitor_neon = 1; 16349 } 16350 /* If set to true or yes, assume that simple fsk is desired */ 16351 if (ast_true(v->value)) { 16352 confp->chan.mwimonitor_fsk = 1; 16353 } 16354 } else if (!strcasecmp(v->name, "cid_rxgain")) { 16355 if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) { 16356 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno); 16357 } 16358 } else if (!strcasecmp(v->name, "rxgain")) { 16359 if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) { 16360 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno); 16361 } 16362 } else if (!strcasecmp(v->name, "txgain")) { 16363 if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) { 16364 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno); 16365 } 16366 } else if (!strcasecmp(v->name, "tonezone")) { 16367 if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) { 16368 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno); 16369 } 16370 } else if (!strcasecmp(v->name, "callerid")) { 16371 if (!strcasecmp(v->value, "asreceived")) { 16372 confp->chan.cid_num[0] = '\0'; 16373 confp->chan.cid_name[0] = '\0'; 16374 } else { 16375 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 16376 } 16377 } else if (!strcasecmp(v->name, "fullname")) { 16378 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 16379 } else if (!strcasecmp(v->name, "cid_number")) { 16380 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 16381 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) { 16382 confp->chan.dahditrcallerid = ast_true(v->value); 16383 } else if (!strcasecmp(v->name, "restrictcid")) { 16384 confp->chan.restrictcid = ast_true(v->value); 16385 } else if (!strcasecmp(v->name, "usecallingpres")) { 16386 confp->chan.use_callingpres = ast_true(v->value); 16387 } else if (!strcasecmp(v->name, "accountcode")) { 16388 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 16389 } else if (!strcasecmp(v->name, "amaflags")) { 16390 y = ast_cdr_amaflags2int(v->value); 16391 if (y < 0) 16392 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno); 16393 else 16394 confp->chan.amaflags = y; 16395 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 16396 confp->chan.polarityonanswerdelay = atoi(v->value); 16397 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 16398 confp->chan.answeronpolarityswitch = ast_true(v->value); 16399 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 16400 confp->chan.hanguponpolarityswitch = ast_true(v->value); 16401 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 16402 confp->chan.sendcalleridafter = atoi(v->value); 16403 } else if (!strcasecmp(v->name, "mwimonitornotify")) { 16404 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify)); 16405 } else if (!strcasecmp(v->name, "mwisendtype")) { 16406 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI /* backward compatibility for older dahdi VMWI implementation */ 16407 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */ 16408 mwisend_rpas = 1; 16409 } else { 16410 mwisend_rpas = 0; 16411 } 16412 #else 16413 /* Default is fsk, to turn it off you must specify nofsk */ 16414 memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting)); 16415 if (strcasestr(v->value, "nofsk")) { /* NoFSK */ 16416 confp->chan.mwisend_fsk = 0; 16417 } else { /* Default FSK */ 16418 confp->chan.mwisend_fsk = 1; 16419 } 16420 if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */ 16421 confp->chan.mwisend_rpas = 1; 16422 } else { 16423 confp->chan.mwisend_rpas = 0; 16424 } 16425 if (strcasestr(v->value, "lrev")) { /* Line Reversal */ 16426 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV; 16427 } 16428 if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */ 16429 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC; 16430 } 16431 if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */ 16432 confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC; 16433 } 16434 #endif 16435 } else if (reload != 1) { 16436 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) { 16437 int orig_radio = confp->chan.radio; 16438 int orig_outsigmod = confp->chan.outsigmod; 16439 int orig_auto = confp->is_sig_auto; 16440 16441 confp->chan.radio = 0; 16442 confp->chan.outsigmod = -1; 16443 confp->is_sig_auto = 0; 16444 if (!strcasecmp(v->value, "em")) { 16445 confp->chan.sig = SIG_EM; 16446 } else if (!strcasecmp(v->value, "em_e1")) { 16447 confp->chan.sig = SIG_EM_E1; 16448 } else if (!strcasecmp(v->value, "em_w")) { 16449 confp->chan.sig = SIG_EMWINK; 16450 } else if (!strcasecmp(v->value, "fxs_ls")) { 16451 confp->chan.sig = SIG_FXSLS; 16452 } else if (!strcasecmp(v->value, "fxs_gs")) { 16453 confp->chan.sig = SIG_FXSGS; 16454 } else if (!strcasecmp(v->value, "fxs_ks")) { 16455 confp->chan.sig = SIG_FXSKS; 16456 } else if (!strcasecmp(v->value, "fxo_ls")) { 16457 confp->chan.sig = SIG_FXOLS; 16458 } else if (!strcasecmp(v->value, "fxo_gs")) { 16459 confp->chan.sig = SIG_FXOGS; 16460 } else if (!strcasecmp(v->value, "fxo_ks")) { 16461 confp->chan.sig = SIG_FXOKS; 16462 } else if (!strcasecmp(v->value, "fxs_rx")) { 16463 confp->chan.sig = SIG_FXSKS; 16464 confp->chan.radio = 1; 16465 } else if (!strcasecmp(v->value, "fxo_rx")) { 16466 confp->chan.sig = SIG_FXOLS; 16467 confp->chan.radio = 1; 16468 } else if (!strcasecmp(v->value, "fxs_tx")) { 16469 confp->chan.sig = SIG_FXSLS; 16470 confp->chan.radio = 1; 16471 } else if (!strcasecmp(v->value, "fxo_tx")) { 16472 confp->chan.sig = SIG_FXOGS; 16473 confp->chan.radio = 1; 16474 } else if (!strcasecmp(v->value, "em_rx")) { 16475 confp->chan.sig = SIG_EM; 16476 confp->chan.radio = 1; 16477 } else if (!strcasecmp(v->value, "em_tx")) { 16478 confp->chan.sig = SIG_EM; 16479 confp->chan.radio = 1; 16480 } else if (!strcasecmp(v->value, "em_rxtx")) { 16481 confp->chan.sig = SIG_EM; 16482 confp->chan.radio = 2; 16483 } else if (!strcasecmp(v->value, "em_txrx")) { 16484 confp->chan.sig = SIG_EM; 16485 confp->chan.radio = 2; 16486 } else if (!strcasecmp(v->value, "sf")) { 16487 confp->chan.sig = SIG_SF; 16488 } else if (!strcasecmp(v->value, "sf_w")) { 16489 confp->chan.sig = SIG_SFWINK; 16490 } else if (!strcasecmp(v->value, "sf_featd")) { 16491 confp->chan.sig = SIG_FEATD; 16492 } else if (!strcasecmp(v->value, "sf_featdmf")) { 16493 confp->chan.sig = SIG_FEATDMF; 16494 } else if (!strcasecmp(v->value, "sf_featb")) { 16495 confp->chan.sig = SIG_SF_FEATB; 16496 } else if (!strcasecmp(v->value, "sf")) { 16497 confp->chan.sig = SIG_SF; 16498 } else if (!strcasecmp(v->value, "sf_rx")) { 16499 confp->chan.sig = SIG_SF; 16500 confp->chan.radio = 1; 16501 } else if (!strcasecmp(v->value, "sf_tx")) { 16502 confp->chan.sig = SIG_SF; 16503 confp->chan.radio = 1; 16504 } else if (!strcasecmp(v->value, "sf_rxtx")) { 16505 confp->chan.sig = SIG_SF; 16506 confp->chan.radio = 2; 16507 } else if (!strcasecmp(v->value, "sf_txrx")) { 16508 confp->chan.sig = SIG_SF; 16509 confp->chan.radio = 2; 16510 } else if (!strcasecmp(v->value, "featd")) { 16511 confp->chan.sig = SIG_FEATD; 16512 } else if (!strcasecmp(v->value, "featdmf")) { 16513 confp->chan.sig = SIG_FEATDMF; 16514 } else if (!strcasecmp(v->value, "featdmf_ta")) { 16515 confp->chan.sig = SIG_FEATDMF_TA; 16516 } else if (!strcasecmp(v->value, "e911")) { 16517 confp->chan.sig = SIG_E911; 16518 } else if (!strcasecmp(v->value, "fgccama")) { 16519 confp->chan.sig = SIG_FGC_CAMA; 16520 } else if (!strcasecmp(v->value, "fgccamamf")) { 16521 confp->chan.sig = SIG_FGC_CAMAMF; 16522 } else if (!strcasecmp(v->value, "featb")) { 16523 confp->chan.sig = SIG_FEATB; 16524 #ifdef HAVE_PRI 16525 } else if (!strcasecmp(v->value, "pri_net")) { 16526 confp->chan.sig = SIG_PRI; 16527 confp->pri.nodetype = PRI_NETWORK; 16528 } else if (!strcasecmp(v->value, "pri_cpe")) { 16529 confp->chan.sig = SIG_PRI; 16530 confp->pri.nodetype = PRI_CPE; 16531 } else if (!strcasecmp(v->value, "bri_cpe")) { 16532 confp->chan.sig = SIG_BRI; 16533 confp->pri.nodetype = PRI_CPE; 16534 } else if (!strcasecmp(v->value, "bri_net")) { 16535 confp->chan.sig = SIG_BRI; 16536 confp->pri.nodetype = PRI_NETWORK; 16537 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) { 16538 confp->chan.sig = SIG_BRI_PTMP; 16539 confp->pri.nodetype = PRI_CPE; 16540 } else if (!strcasecmp(v->value, "bri_net_ptmp")) { 16541 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno); 16542 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 16543 confp->chan.sig = SIG_GR303FXOKS; 16544 confp->pri.nodetype = PRI_NETWORK; 16545 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 16546 confp->chan.sig = SIG_GR303FXSKS; 16547 confp->pri.nodetype = PRI_CPE; 16548 #endif 16549 #ifdef HAVE_SS7 16550 } else if (!strcasecmp(v->value, "ss7")) { 16551 confp->chan.sig = SIG_SS7; 16552 #endif 16553 #ifdef HAVE_OPENR2 16554 } else if (!strcasecmp(v->value, "mfcr2")) { 16555 confp->chan.sig = SIG_MFCR2; 16556 #endif 16557 } else if (!strcasecmp(v->value, "auto")) { 16558 confp->is_sig_auto = 1; 16559 } else { 16560 confp->chan.outsigmod = orig_outsigmod; 16561 confp->chan.radio = orig_radio; 16562 confp->is_sig_auto = orig_auto; 16563 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 16564 } 16565 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) { 16566 if (!strcasecmp(v->value, "em")) { 16567 confp->chan.outsigmod = SIG_EM; 16568 } else if (!strcasecmp(v->value, "em_e1")) { 16569 confp->chan.outsigmod = SIG_EM_E1; 16570 } else if (!strcasecmp(v->value, "em_w")) { 16571 confp->chan.outsigmod = SIG_EMWINK; 16572 } else if (!strcasecmp(v->value, "sf")) { 16573 confp->chan.outsigmod = SIG_SF; 16574 } else if (!strcasecmp(v->value, "sf_w")) { 16575 confp->chan.outsigmod = SIG_SFWINK; 16576 } else if (!strcasecmp(v->value, "sf_featd")) { 16577 confp->chan.outsigmod = SIG_FEATD; 16578 } else if (!strcasecmp(v->value, "sf_featdmf")) { 16579 confp->chan.outsigmod = SIG_FEATDMF; 16580 } else if (!strcasecmp(v->value, "sf_featb")) { 16581 confp->chan.outsigmod = SIG_SF_FEATB; 16582 } else if (!strcasecmp(v->value, "sf")) { 16583 confp->chan.outsigmod = SIG_SF; 16584 } else if (!strcasecmp(v->value, "featd")) { 16585 confp->chan.outsigmod = SIG_FEATD; 16586 } else if (!strcasecmp(v->value, "featdmf")) { 16587 confp->chan.outsigmod = SIG_FEATDMF; 16588 } else if (!strcasecmp(v->value, "featdmf_ta")) { 16589 confp->chan.outsigmod = SIG_FEATDMF_TA; 16590 } else if (!strcasecmp(v->value, "e911")) { 16591 confp->chan.outsigmod = SIG_E911; 16592 } else if (!strcasecmp(v->value, "fgccama")) { 16593 confp->chan.outsigmod = SIG_FGC_CAMA; 16594 } else if (!strcasecmp(v->value, "fgccamamf")) { 16595 confp->chan.outsigmod = SIG_FGC_CAMAMF; 16596 } else if (!strcasecmp(v->value, "featb")) { 16597 confp->chan.outsigmod = SIG_FEATB; 16598 } else { 16599 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno); 16600 } 16601 #ifdef HAVE_PRI 16602 } else if (!strcasecmp(v->name, "pridialplan")) { 16603 if (!strcasecmp(v->value, "national")) { 16604 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 16605 } else if (!strcasecmp(v->value, "unknown")) { 16606 confp->pri.dialplan = PRI_UNKNOWN + 1; 16607 } else if (!strcasecmp(v->value, "private")) { 16608 confp->pri.dialplan = PRI_PRIVATE + 1; 16609 } else if (!strcasecmp(v->value, "international")) { 16610 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 16611 } else if (!strcasecmp(v->value, "local")) { 16612 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 16613 } else if (!strcasecmp(v->value, "dynamic")) { 16614 confp->pri.dialplan = -1; 16615 } else if (!strcasecmp(v->value, "redundant")) { 16616 confp->pri.dialplan = -2; 16617 } else { 16618 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 16619 } 16620 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 16621 if (!strcasecmp(v->value, "national")) { 16622 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 16623 } else if (!strcasecmp(v->value, "unknown")) { 16624 confp->pri.localdialplan = PRI_UNKNOWN + 1; 16625 } else if (!strcasecmp(v->value, "private")) { 16626 confp->pri.localdialplan = PRI_PRIVATE + 1; 16627 } else if (!strcasecmp(v->value, "international")) { 16628 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 16629 } else if (!strcasecmp(v->value, "local")) { 16630 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 16631 } else if (!strcasecmp(v->value, "dynamic")) { 16632 confp->pri.localdialplan = -1; 16633 } else if (!strcasecmp(v->value, "redundant")) { 16634 confp->pri.localdialplan = -2; 16635 } else { 16636 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno); 16637 } 16638 } else if (!strcasecmp(v->name, "switchtype")) { 16639 if (!strcasecmp(v->value, "national")) 16640 confp->pri.switchtype = PRI_SWITCH_NI2; 16641 else if (!strcasecmp(v->value, "ni1")) 16642 confp->pri.switchtype = PRI_SWITCH_NI1; 16643 else if (!strcasecmp(v->value, "dms100")) 16644 confp->pri.switchtype = PRI_SWITCH_DMS100; 16645 else if (!strcasecmp(v->value, "4ess")) 16646 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 16647 else if (!strcasecmp(v->value, "5ess")) 16648 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 16649 else if (!strcasecmp(v->value, "euroisdn")) 16650 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 16651 else if (!strcasecmp(v->value, "qsig")) 16652 confp->pri.switchtype = PRI_SWITCH_QSIG; 16653 else { 16654 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno); 16655 return -1; 16656 } 16657 } else if (!strcasecmp(v->name, "nsf")) { 16658 if (!strcasecmp(v->value, "sdn")) 16659 confp->pri.nsf = PRI_NSF_SDN; 16660 else if (!strcasecmp(v->value, "megacom")) 16661 confp->pri.nsf = PRI_NSF_MEGACOM; 16662 else if (!strcasecmp(v->value, "tollfreemegacom")) 16663 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 16664 else if (!strcasecmp(v->value, "accunet")) 16665 confp->pri.nsf = PRI_NSF_ACCUNET; 16666 else if (!strcasecmp(v->value, "none")) 16667 confp->pri.nsf = PRI_NSF_NONE; 16668 else { 16669 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno); 16670 confp->pri.nsf = PRI_NSF_NONE; 16671 } 16672 } else if (!strcasecmp(v->name, "priindication")) { 16673 if (!strcasecmp(v->value, "outofband")) 16674 confp->chan.priindication_oob = 1; 16675 else if (!strcasecmp(v->value, "inband")) 16676 confp->chan.priindication_oob = 0; 16677 else 16678 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n", 16679 v->value, v->lineno); 16680 } else if (!strcasecmp(v->name, "priexclusive")) { 16681 confp->chan.priexclusive = ast_true(v->value); 16682 } else if (!strcasecmp(v->name, "internationalprefix")) { 16683 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 16684 } else if (!strcasecmp(v->name, "nationalprefix")) { 16685 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 16686 } else if (!strcasecmp(v->name, "localprefix")) { 16687 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 16688 } else if (!strcasecmp(v->name, "privateprefix")) { 16689 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 16690 } else if (!strcasecmp(v->name, "unknownprefix")) { 16691 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 16692 } else if (!strcasecmp(v->name, "resetinterval")) { 16693 if (!strcasecmp(v->value, "never")) 16694 confp->pri.resetinterval = -1; 16695 else if (atoi(v->value) >= 60) 16696 confp->pri.resetinterval = atoi(v->value); 16697 else 16698 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", 16699 v->value, v->lineno); 16700 } else if (!strcasecmp(v->name, "minunused")) { 16701 confp->pri.minunused = atoi(v->value); 16702 } else if (!strcasecmp(v->name, "minidle")) { 16703 confp->pri.minidle = atoi(v->value); 16704 } else if (!strcasecmp(v->name, "idleext")) { 16705 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 16706 } else if (!strcasecmp(v->name, "idledial")) { 16707 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 16708 } else if (!strcasecmp(v->name, "overlapdial")) { 16709 if (ast_true(v->value)) { 16710 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 16711 } else if (!strcasecmp(v->value, "incoming")) { 16712 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING; 16713 } else if (!strcasecmp(v->value, "outgoing")) { 16714 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING; 16715 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) { 16716 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH; 16717 } else { 16718 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE; 16719 } 16720 #ifdef HAVE_PRI_PROG_W_CAUSE 16721 } else if (!strcasecmp(v->name, "qsigchannelmapping")) { 16722 if (!strcasecmp(v->value, "logical")) { 16723 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL; 16724 } else if (!strcasecmp(v->value, "physical")) { 16725 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 16726 } else { 16727 confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL; 16728 } 16729 #endif 16730 } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) { 16731 confp->pri.discardremoteholdretrieval = ast_true(v->value); 16732 #ifdef HAVE_PRI_INBANDDISCONNECT 16733 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 16734 confp->pri.inbanddisconnect = ast_true(v->value); 16735 #endif 16736 } else if (!strcasecmp(v->name, "pritimer")) { 16737 #ifdef PRI_GETSET_TIMERS 16738 char tmp[20]; 16739 char *timerc; 16740 char *c; 16741 int timer; 16742 int timeridx; 16743 16744 ast_copy_string(tmp, v->value, sizeof(tmp)); 16745 c = tmp; 16746 timerc = strsep(&c, ","); 16747 if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) { 16748 timeridx = pri_timer2idx(timerc); 16749 timer = atoi(c); 16750 if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) { 16751 ast_log(LOG_WARNING, 16752 "'%s' is not a valid ISDN timer at line %d.\n", timerc, 16753 v->lineno); 16754 } else if (!timer) { 16755 ast_log(LOG_WARNING, 16756 "'%s' is not a valid value for ISDN timer '%s' at line %d.\n", 16757 c, timerc, v->lineno); 16758 } else { 16759 pritimers[timeridx] = timer; 16760 } 16761 } else { 16762 ast_log(LOG_WARNING, 16763 "'%s' is not a valid ISDN timer configuration string at line %d.\n", 16764 v->value, v->lineno); 16765 } 16766 16767 } else if (!strcasecmp(v->name, "facilityenable")) { 16768 confp->pri.facilityenable = ast_true(v->value); 16769 #endif /* PRI_GETSET_TIMERS */ 16770 #endif /* HAVE_PRI */ 16771 #ifdef HAVE_SS7 16772 } else if (!strcasecmp(v->name, "ss7type")) { 16773 if (!strcasecmp(v->value, "itu")) { 16774 cur_ss7type = SS7_ITU; 16775 } else if (!strcasecmp(v->value, "ansi")) { 16776 cur_ss7type = SS7_ANSI; 16777 } else 16778 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno); 16779 } else if (!strcasecmp(v->name, "linkset")) { 16780 cur_linkset = atoi(v->value); 16781 } else if (!strcasecmp(v->name, "pointcode")) { 16782 cur_pointcode = parse_pointcode(v->value); 16783 } else if (!strcasecmp(v->name, "adjpointcode")) { 16784 cur_adjpointcode = parse_pointcode(v->value); 16785 } else if (!strcasecmp(v->name, "defaultdpc")) { 16786 cur_defaultdpc = parse_pointcode(v->value); 16787 } else if (!strcasecmp(v->name, "cicbeginswith")) { 16788 cur_cicbeginswith = atoi(v->value); 16789 } else if (!strcasecmp(v->name, "networkindicator")) { 16790 if (!strcasecmp(v->value, "national")) 16791 cur_networkindicator = SS7_NI_NAT; 16792 else if (!strcasecmp(v->value, "national_spare")) 16793 cur_networkindicator = SS7_NI_NAT_SPARE; 16794 else if (!strcasecmp(v->value, "international")) 16795 cur_networkindicator = SS7_NI_INT; 16796 else if (!strcasecmp(v->value, "international_spare")) 16797 cur_networkindicator = SS7_NI_INT_SPARE; 16798 else 16799 cur_networkindicator = -1; 16800 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) { 16801 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix)); 16802 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) { 16803 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix)); 16804 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) { 16805 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix)); 16806 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) { 16807 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix)); 16808 } else if (!strcasecmp(v->name, "ss7_called_nai")) { 16809 if (!strcasecmp(v->value, "national")) { 16810 confp->ss7.called_nai = SS7_NAI_NATIONAL; 16811 } else if (!strcasecmp(v->value, "international")) { 16812 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL; 16813 } else if (!strcasecmp(v->value, "subscriber")) { 16814 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER; 16815 } else if (!strcasecmp(v->value, "dynamic")) { 16816 confp->ss7.called_nai = SS7_NAI_DYNAMIC; 16817 } else { 16818 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno); 16819 } 16820 } else if (!strcasecmp(v->name, "ss7_calling_nai")) { 16821 if (!strcasecmp(v->value, "national")) { 16822 confp->ss7.calling_nai = SS7_NAI_NATIONAL; 16823 } else if (!strcasecmp(v->value, "international")) { 16824 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL; 16825 } else if (!strcasecmp(v->value, "subscriber")) { 16826 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER; 16827 } else if (!strcasecmp(v->value, "dynamic")) { 16828 confp->ss7.calling_nai = SS7_NAI_DYNAMIC; 16829 } else { 16830 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno); 16831 } 16832 } else if (!strcasecmp(v->name, "sigchan")) { 16833 int sigchan, res; 16834 sigchan = atoi(v->value); 16835 res = linkset_addsigchan(sigchan); 16836 if (res < 0) 16837 return -1; 16838 16839 } else if (!strcasecmp(v->name, "ss7_explicitacm")) { 16840 struct dahdi_ss7 *link; 16841 link = ss7_resolve_linkset(cur_linkset); 16842 if (!link) { 16843 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1); 16844 return -1; 16845 } 16846 if (ast_true(v->value)) 16847 link->flags |= LINKSET_FLAG_EXPLICITACM; 16848 #endif /* HAVE_SS7 */ 16849 #ifdef HAVE_OPENR2 16850 } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) { 16851 ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file)); 16852 ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file); 16853 } else if (!strcasecmp(v->name, "mfcr2_logdir")) { 16854 ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir)); 16855 } else if (!strcasecmp(v->name, "mfcr2_variant")) { 16856 confp->mfcr2.variant = openr2_proto_get_variant(v->value); 16857 if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) { 16858 ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno); 16859 confp->mfcr2.variant = OR2_VAR_ITU; 16860 } 16861 } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) { 16862 confp->mfcr2.mfback_timeout = atoi(v->value); 16863 if (!confp->mfcr2.mfback_timeout) { 16864 ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n"); 16865 confp->mfcr2.mfback_timeout = -1; 16866 } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) { 16867 ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n"); 16868 } 16869 } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) { 16870 confp->mfcr2.metering_pulse_timeout = atoi(v->value); 16871 if (confp->mfcr2.metering_pulse_timeout > 500) { 16872 ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n"); 16873 } 16874 } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) { 16875 confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0; 16876 } else if (!strcasecmp(v->name, "mfcr2_double_answer")) { 16877 confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0; 16878 } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) { 16879 confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0; 16880 } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) { 16881 confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0; 16882 } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) { 16883 confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0; 16884 } else if (!strcasecmp(v->name, "mfcr2_forced_release")) { 16885 confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0; 16886 } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) { 16887 confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0; 16888 } else if (!strcasecmp(v->name, "mfcr2_call_files")) { 16889 confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0; 16890 } else if (!strcasecmp(v->name, "mfcr2_max_ani")) { 16891 confp->mfcr2.max_ani = atoi(v->value); 16892 if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){ 16893 confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1; 16894 } 16895 } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) { 16896 confp->mfcr2.max_dnis = atoi(v->value); 16897 if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){ 16898 confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1; 16899 } 16900 } else if (!strcasecmp(v->name, "mfcr2_category")) { 16901 confp->mfcr2.category = openr2_proto_get_category(v->value); 16902 if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) { 16903 confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER; 16904 ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n", 16905 v->value, v->lineno); 16906 } 16907 } else if (!strcasecmp(v->name, "mfcr2_logging")) { 16908 openr2_log_level_t tmplevel; 16909 char *clevel; 16910 char *logval = ast_strdupa(v->value); 16911 while (logval) { 16912 clevel = strsep(&logval,","); 16913 if (-1 == (tmplevel = openr2_log_get_level(clevel))) { 16914 ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno); 16915 continue; 16916 } 16917 confp->mfcr2.loglevel |= tmplevel; 16918 } 16919 #endif /* HAVE_OPENR2 */ 16920 } else if (!strcasecmp(v->name, "cadence")) { 16921 /* setup to scan our argument */ 16922 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 16923 int i; 16924 struct dahdi_ring_cadence new_cadence; 16925 int cid_location = -1; 16926 int firstcadencepos = 0; 16927 char original_args[80]; 16928 int cadence_is_ok = 1; 16929 16930 ast_copy_string(original_args, v->value, sizeof(original_args)); 16931 /* 16 cadences allowed (8 pairs) */ 16932 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]); 16933 16934 /* Cadence must be even (on/off) */ 16935 if (element_count % 2 == 1) { 16936 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno); 16937 cadence_is_ok = 0; 16938 } 16939 16940 /* Ring cadences cannot be negative */ 16941 for (i = 0; i < element_count; i++) { 16942 if (c[i] == 0) { 16943 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno); 16944 cadence_is_ok = 0; 16945 break; 16946 } else if (c[i] < 0) { 16947 if (i % 2 == 1) { 16948 /* Silence duration, negative possibly okay */ 16949 if (cid_location == -1) { 16950 cid_location = i; 16951 c[i] *= -1; 16952 } else { 16953 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno); 16954 cadence_is_ok = 0; 16955 break; 16956 } 16957 } else { 16958 if (firstcadencepos == 0) { 16959 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 16960 /* duration will be passed negative to the DAHDI driver */ 16961 } else { 16962 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno); 16963 cadence_is_ok = 0; 16964 break; 16965 } 16966 } 16967 } 16968 } 16969 16970 /* Substitute our scanned cadence */ 16971 for (i = 0; i < 16; i++) { 16972 new_cadence.ringcadence[i] = c[i]; 16973 } 16974 16975 if (cadence_is_ok) { 16976 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 16977 if (element_count < 2) { 16978 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno); 16979 } else { 16980 if (cid_location == -1) { 16981 /* user didn't say; default to first pause */ 16982 cid_location = 1; 16983 } else { 16984 /* convert element_index to cidrings value */ 16985 cid_location = (cid_location + 1) / 2; 16986 } 16987 /* ---we like their cadence; try to install it--- */ 16988 if (!user_has_defined_cadences++) 16989 /* this is the first user-defined cadence; clear the default user cadences */ 16990 num_cadence = 0; 16991 if ((num_cadence+1) >= NUM_CADENCE_MAX) 16992 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno); 16993 else { 16994 cadences[num_cadence] = new_cadence; 16995 cidrings[num_cadence++] = cid_location; 16996 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args); 16997 } 16998 } 16999 } 17000 } else if (!strcasecmp(v->name, "ringtimeout")) { 17001 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 17002 } else if (!strcasecmp(v->name, "prewink")) { 17003 confp->timing.prewinktime = atoi(v->value); 17004 } else if (!strcasecmp(v->name, "preflash")) { 17005 confp->timing.preflashtime = atoi(v->value); 17006 } else if (!strcasecmp(v->name, "wink")) { 17007 confp->timing.winktime = atoi(v->value); 17008 } else if (!strcasecmp(v->name, "flash")) { 17009 confp->timing.flashtime = atoi(v->value); 17010 } else if (!strcasecmp(v->name, "start")) { 17011 confp->timing.starttime = atoi(v->value); 17012 } else if (!strcasecmp(v->name, "rxwink")) { 17013 confp->timing.rxwinktime = atoi(v->value); 17014 } else if (!strcasecmp(v->name, "rxflash")) { 17015 confp->timing.rxflashtime = atoi(v->value); 17016 } else if (!strcasecmp(v->name, "debounce")) { 17017 confp->timing.debouncetime = atoi(v->value); 17018 } else if (!strcasecmp(v->name, "toneduration")) { 17019 int toneduration; 17020 int ctlfd; 17021 int res; 17022 struct dahdi_dialparams dps; 17023 17024 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 17025 if (ctlfd == -1) { 17026 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno); 17027 return -1; 17028 } 17029 17030 toneduration = atoi(v->value); 17031 if (toneduration > -1) { 17032 memset(&dps, 0, sizeof(dps)); 17033 17034 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 17035 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 17036 if (res < 0) { 17037 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno)); 17038 return -1; 17039 } 17040 } 17041 close(ctlfd); 17042 } else if (!strcasecmp(v->name, "defaultcic")) { 17043 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 17044 } else if (!strcasecmp(v->name, "defaultozz")) { 17045 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 17046 } else if (!strcasecmp(v->name, "mwilevel")) { 17047 mwilevel = atoi(v->value); 17048 } 17049 } else if (!(options & PROC_DAHDI_OPT_NOWARN) ) 17050 ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno); 17051 } 17052 if (dahdichan[0]) { 17053 /* The user has set 'dahdichan' */ 17054 /*< \todo pass proper line number instead of 0 */ 17055 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 17056 return -1; 17057 } 17058 } 17059 /*< \todo why check for the pseudo in the per-channel section. 17060 * Any actual use for manual setup of the pseudo channel? */ 17061 if (!found_pseudo && reload != 1) { 17062 /* use the default configuration for a channel, so 17063 that any settings from real configured channels 17064 don't "leak" into the pseudo channel config 17065 */ 17066 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 17067 17068 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload); 17069 17070 if (tmp) { 17071 ast_verb(3, "Automatically generated pseudo channel\n"); 17072 } else { 17073 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 17074 } 17075 } 17076 return 0; 17077 }
| static void process_echocancel | ( | struct dahdi_chan_conf * | confp, | |
| const char * | data, | |||
| unsigned int | line | |||
| ) | [static] |
Definition at line 16040 of file chan_dahdi.c.
References ARRAY_LEN, ast_app_separate_args, ast_log(), ast_strlen_zero(), ast_true(), dahdi_chan_conf::chan, dahdi_pvt::echocancel, dahdi_pvt::head, LOG_WARNING, name, and dahdi_pvt::params.
Referenced by process_dahdi().
16041 { 16042 char *parse = ast_strdupa(data); 16043 char *params[DAHDI_MAX_ECHOCANPARAMS + 1]; 16044 unsigned int param_count; 16045 unsigned int x; 16046 16047 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params)))) 16048 return; 16049 16050 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel)); 16051 16052 /* first parameter is tap length, process it here */ 16053 16054 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]); 16055 16056 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024)) 16057 confp->chan.echocancel.head.tap_length = x; 16058 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0]))) 16059 confp->chan.echocancel.head.tap_length = 128; 16060 16061 /* now process any remaining parameters */ 16062 16063 for (x = 1; x < param_count; x++) { 16064 struct { 16065 char *name; 16066 char *value; 16067 } param; 16068 16069 if (ast_app_separate_args(params[x], '=', (char **) ¶m, 2) < 1) { 16070 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]); 16071 continue; 16072 } 16073 16074 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) { 16075 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name); 16076 continue; 16077 } 16078 16079 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name); 16080 16081 if (param.value) { 16082 if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) { 16083 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value); 16084 continue; 16085 } 16086 } 16087 confp->chan.echocancel.head.param_count++; 16088 } 16089 }
| static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 12344 of file chan_dahdi.c.
Referenced by pri_dchannel().
| static int reload | ( | void | ) | [static] |
Definition at line 17480 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and setup_dahdi().
17481 { 17482 int res = 0; 17483 17484 res = setup_dahdi(1); 17485 if (res) { 17486 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 17487 return -1; 17488 } 17489 return 0; 17490 }
| static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2590 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().
02591 { 02592 p->confno = -1; 02593 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 02594 if (p->subs[SUB_REAL].dfd > -1) { 02595 struct dahdi_confinfo zi; 02596 02597 memset(&zi, 0, sizeof(zi)); 02598 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 02599 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 02600 } 02601 return 0; 02602 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 9705 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().
09706 { 09707 /* If we're supposed to be stopped -- stay stopped */ 09708 if (monitor_thread == AST_PTHREADT_STOP) 09709 return 0; 09710 ast_mutex_lock(&monlock); 09711 if (monitor_thread == pthread_self()) { 09712 ast_mutex_unlock(&monlock); 09713 ast_log(LOG_WARNING, "Cannot kill myself\n"); 09714 return -1; 09715 } 09716 if (monitor_thread != AST_PTHREADT_NULL) { 09717 /* Wake up the thread */ 09718 pthread_kill(monitor_thread, SIGURG); 09719 } else { 09720 /* Start a new monitor */ 09721 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 09722 ast_mutex_unlock(&monlock); 09723 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 09724 return -1; 09725 } 09726 } 09727 ast_mutex_unlock(&monlock); 09728 return 0; 09729 }
| static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2969 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().
02970 { 02971 int res; 02972 if (p->saveconf.confmode) { 02973 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 02974 p->saveconf.confmode = 0; 02975 if (res) { 02976 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 02977 return -1; 02978 } 02979 } 02980 ast_debug(1, "Restored conferencing\n"); 02981 return 0; 02982 }
| static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2850 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().
02851 { 02852 int res; 02853 02854 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 02855 if (res) { 02856 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 02857 return -1; 02858 } 02859 02860 return 0; 02861 }
| static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2896 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().
02897 { 02898 struct dahdi_confinfo c; 02899 int res; 02900 if (p->saveconf.confmode) { 02901 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 02902 return -1; 02903 } 02904 p->saveconf.chan = 0; 02905 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 02906 if (res) { 02907 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 02908 p->saveconf.confmode = 0; 02909 return -1; 02910 } 02911 memset(&c, 0, sizeof(c)); 02912 c.confmode = DAHDI_CONF_NORMAL; 02913 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 02914 if (res) { 02915 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 02916 return -1; 02917 } 02918 ast_debug(1, "Disabled conferencing\n"); 02919 return 0; 02920 }
| static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3026 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().
03027 { 03028 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 03029 int res; 03030 /* Take out of linear mode if necessary */ 03031 if (p->subs[SUB_REAL].linear) { 03032 p->subs[SUB_REAL].linear = 0; 03033 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 03034 } 03035 while (p->cidpos < p->cidlen) { 03036 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 03037 if (res < 0) { 03038 if (errno == EAGAIN) 03039 return 0; 03040 else { 03041 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 03042 return -1; 03043 } 03044 } 03045 if (!res) 03046 return 0; 03047 p->cidpos += res; 03048 } 03049 ast_free(p->cidspill); 03050 p->cidspill = NULL; 03051 if (p->callwaitcas) { 03052 /* Wait for CID/CW to expire */ 03053 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 03054 } else 03055 restore_conference(p); 03056 return 0; 03057 }
| static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2986 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().
02987 { 02988 p->callwaitcas = 0; 02989 p->cidcwexpire = 0; 02990 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 02991 return -1; 02992 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 02993 /* Make sure we account for the end */ 02994 p->cidlen += READ_SIZE * 4; 02995 p->cidpos = 0; 02996 send_callerid(p); 02997 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 02998 return 0; 02999 }
| static int set_actual_gain | ( | int | fd, | |
| int | chan, | |||
| float | rxgain, | |||
| float | txgain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2831 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().
02832 { 02833 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 02834 }
| static int set_actual_rxgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2813 of file chan_dahdi.c.
References ast_debug, errno, and fill_rxgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02814 { 02815 struct dahdi_gains g; 02816 int res; 02817 02818 memset(&g, 0, sizeof(g)); 02819 g.chan = chan; 02820 res = ioctl(fd, DAHDI_GETGAINS, &g); 02821 if (res) { 02822 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02823 return res; 02824 } 02825 02826 fill_rxgain(&g, gain, law); 02827 02828 return ioctl(fd, DAHDI_SETGAINS, &g); 02829 }
| static int set_actual_txgain | ( | int | fd, | |
| int | chan, | |||
| float | gain, | |||
| int | law | |||
| ) | [static] |
Definition at line 2795 of file chan_dahdi.c.
References ast_debug, errno, and fill_txgain().
Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().
02796 { 02797 struct dahdi_gains g; 02798 int res; 02799 02800 memset(&g, 0, sizeof(g)); 02801 g.chan = chan; 02802 res = ioctl(fd, DAHDI_GETGAINS, &g); 02803 if (res) { 02804 ast_debug(1, "Failed to read gains: %s\n", strerror(errno)); 02805 return res; 02806 } 02807 02808 fill_txgain(&g, gain, law); 02809 02810 return ioctl(fd, DAHDI_SETGAINS, &g); 02811 }
| static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 17079 of file chan_dahdi.c.
References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, dahdi_chan_conf_default(), global_jbconf, iflock, ast_variable::lineno, linksets, LOG_ERROR, LOG_NOTICE, LOG_WARNING, master, ast_variable::name, ast_variable::next, NUM_DCHANS, 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().
17080 { 17081 struct ast_config *cfg, *ucfg; 17082 struct ast_variable *v; 17083 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default(); 17084 struct dahdi_chan_conf conf; 17085 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 17086 const char *cat; 17087 int res; 17088 17089 #ifdef HAVE_PRI 17090 char *c; 17091 int spanno; 17092 int i; 17093 int logicalspan; 17094 int trunkgroup; 17095 int dchannels[NUM_DCHANS]; 17096 #endif 17097 17098 cfg = ast_config_load(config, config_flags); 17099 17100 /* Error if we have no config file */ 17101 if (!cfg) { 17102 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 17103 return 0; 17104 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 17105 ucfg = ast_config_load("users.conf", config_flags); 17106 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 17107 return 0; 17108 } else if (ucfg == CONFIG_STATUS_FILEINVALID) { 17109 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 17110 return 0; 17111 } 17112 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 17113 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) { 17114 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 17115 ast_config_destroy(ucfg); 17116 return 0; 17117 } 17118 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 17119 ast_log(LOG_ERROR, "File %s cannot be parsed. Aborting.\n", config); 17120 return 0; 17121 } else { 17122 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 17123 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) { 17124 ast_log(LOG_ERROR, "File users.conf cannot be parsed. Aborting.\n"); 17125 ast_config_destroy(cfg); 17126 return 0; 17127 } 17128 } 17129 17130 /* It's a little silly to lock it, but we mind as well just to be sure */ 17131 ast_mutex_lock(&iflock); 17132 #ifdef HAVE_PRI 17133 if (reload != 1) { 17134 /* Process trunkgroups first */ 17135 v = ast_variable_browse(cfg, "trunkgroups"); 17136 while (v) { 17137 if (!strcasecmp(v->name, "trunkgroup")) { 17138 trunkgroup = atoi(v->value); 17139 if (trunkgroup > 0) { 17140 if ((c = strchr(v->value, ','))) { 17141 i = 0; 17142 memset(dchannels, 0, sizeof(dchannels)); 17143 while (c && (i < NUM_DCHANS)) { 17144 dchannels[i] = atoi(c + 1); 17145 if (dchannels[i] < 0) { 17146 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); 17147 } else 17148 i++; 17149 c = strchr(c + 1, ','); 17150 } 17151 if (i) { 17152 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 17153 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); 17154 } else 17155 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"); 17156 } else 17157 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 17158 } else 17159 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 17160 } else 17161 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 17162 } else if (!strcasecmp(v->name, "spanmap")) { 17163 spanno = atoi(v->value); 17164 if (spanno > 0) { 17165 if ((c = strchr(v->value, ','))) { 17166 trunkgroup = atoi(c + 1); 17167 if (trunkgroup > 0) { 17168 if ((c = strchr(c + 1, ','))) 17169 logicalspan = atoi(c + 1); 17170 else 17171 logicalspan = 0; 17172 if (logicalspan >= 0) { 17173 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 17174 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 17175 } else 17176 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 17177 } else 17178 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); 17179 } else 17180 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 17181 } else 17182 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 17183 } else 17184 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 17185 } else { 17186 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 17187 } 17188 v = v->next; 17189 } 17190 } 17191 #endif 17192 17193 /* Copy the default jb config over global_jbconf */ 17194 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf)); 17195 17196 mwimonitornotify[0] = '\0'; 17197 17198 v = ast_variable_browse(cfg, "channels"); 17199 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) { 17200 ast_mutex_unlock(&iflock); 17201 ast_config_destroy(cfg); 17202 if (ucfg) { 17203 ast_config_destroy(ucfg); 17204 } 17205 return res; 17206 } 17207 17208 /* Now get configuration from all normal sections in chan_dahdi.conf: */ 17209 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 17210 /* [channels] and [trunkgroups] are used. Let's also reserve 17211 * [globals] and [general] for future use 17212 */ 17213 if (!strcasecmp(cat, "general") || 17214 !strcasecmp(cat, "trunkgroups") || 17215 !strcasecmp(cat, "globals") || 17216 !strcasecmp(cat, "channels")) { 17217 continue; 17218 } 17219 17220 memcpy(&conf, &base_conf, sizeof(conf)); 17221 17222 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) { 17223 ast_mutex_unlock(&iflock); 17224 ast_config_destroy(cfg); 17225 if (ucfg) { 17226 ast_config_destroy(cfg); 17227 } 17228 return res; 17229 } 17230 } 17231 17232 ast_config_destroy(cfg); 17233 17234 if (ucfg) { 17235 const char *chans; 17236 17237 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0); 17238 17239 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 17240 if (!strcasecmp(cat, "general")) { 17241 continue; 17242 } 17243 17244 chans = ast_variable_retrieve(ucfg, cat, "dahdichan"); 17245 17246 if (ast_strlen_zero(chans)) { 17247 continue; 17248 } 17249 17250 memcpy(&conf, &base_conf, sizeof(conf)); 17251 17252 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) { 17253 ast_config_destroy(ucfg); 17254 ast_mutex_unlock(&iflock); 17255 return res; 17256 } 17257 } 17258 ast_config_destroy(ucfg); 17259 } 17260 ast_mutex_unlock(&iflock); 17261 17262 #ifdef HAVE_PRI 17263 if (reload != 1) { 17264 int x; 17265 for (x = 0; x < NUM_SPANS; x++) { 17266 if (pris[x].pvts[0]) { 17267 if (start_pri(pris + x)) { 17268 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 17269 return -1; 17270 } else 17271 ast_verb(2, "Starting D-Channel on span %d\n", x + 1); 17272 } 17273 } 17274 } 17275 #endif 17276 #ifdef HAVE_SS7 17277 if (reload != 1) { 17278 int x; 17279 for (x = 0; x < NUM_SPANS; x++) { 17280 if (linksets[x].ss7) { 17281 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) { 17282 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1); 17283 return -1; 17284 } else 17285 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1); 17286 } 17287 } 17288 } 17289 #endif 17290 #ifdef HAVE_OPENR2 17291 if (reload != 1) { 17292 int x; 17293 for (x = 0; x < r2links_count; x++) { 17294 if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) { 17295 ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1); 17296 return -1; 17297 } else { 17298 ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1); 17299 } 17300 } 17301 } 17302 #endif 17303 /* And start the monitor for the first time */ 17304 restart_monitor(); 17305 return 0; 17306 }
| static int sigtype_to_signalling | ( | int | sigtype | ) | [static] |
Definition at line 9985 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 11353 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().
11354 { 11355 if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */ 11356 if (size) { 11357 *buf = '\0'; 11358 } 11359 return; 11360 } 11361 switch (nai) { 11362 case SS7_NAI_INTERNATIONAL: 11363 snprintf(buf, size, "%s%s", ss7->internationalprefix, number); 11364 break; 11365 case SS7_NAI_NATIONAL: 11366 snprintf(buf, size, "%s%s", ss7->nationalprefix, number); 11367 break; 11368 case SS7_NAI_SUBSCRIBER: 11369 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number); 11370 break; 11371 case SS7_NAI_UNKNOWN: 11372 snprintf(buf, size, "%s%s", ss7->unknownprefix, number); 11373 break; 11374 default: 11375 snprintf(buf, size, "%s", number); 11376 break; 11377 } 11378 }
| 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 11162 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().
11163 { 11164 int i; 11165 11166 for (i = 0; i < linkset->numchans; i++) { 11167 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 11168 if (state) { 11169 if (state[i]) 11170 linkset->pvts[i]->remotelyblocked = block; 11171 } else 11172 linkset->pvts[i]->remotelyblocked = block; 11173 } 11174 } 11175 }
| static int ss7_find_cic | ( | struct dahdi_ss7 * | linkset, | |
| int | cic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 11097 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 1456 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().
01457 { 01458 int res; 01459 /* Grab the lock first */ 01460 do { 01461 res = ast_mutex_trylock(&pri->lock); 01462 if (res) { 01463 DEADLOCK_AVOIDANCE(&pvt->lock); 01464 } 01465 } while (res); 01466 /* Then break the poll */ 01467 if (pri->master != AST_PTHREADT_NULL) 01468 pthread_kill(pri->master, SIGURG); 01469 return 0; 01470 }
| static void ss7_handle_cqm | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 11112 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().
11113 { 11114 unsigned char status[32]; 11115 struct dahdi_pvt *p = NULL; 11116 int i, offset; 11117 11118 for (i = 0; i < linkset->numchans; i++) { 11119 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 11120 p = linkset->pvts[i]; 11121 offset = p->cic - startcic; 11122 status[offset] = 0; 11123 if (p->locallyblocked) 11124 status[offset] |= (1 << 0) | (1 << 4); 11125 if (p->remotelyblocked) 11126 status[offset] |= (1 << 1) | (1 << 5); 11127 if (p->ss7call) { 11128 if (p->outgoing) 11129 status[offset] |= (1 << 3); 11130 else 11131 status[offset] |= (1 << 2); 11132 } else 11133 status[offset] |= 0x3 << 2; 11134 } 11135 } 11136 11137 if (p) 11138 isup_cqr(linkset->ss7, startcic, endcic, dpc, status); 11139 else 11140 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n"); 11141 11142 }
| static void ss7_hangup_cics | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [inline, static] |
Definition at line 11146 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_pvt::lock, dahdi_ss7::numchans, dahdi_pvt::owner, and dahdi_ss7::pvts.
Referenced by ss7_linkset().
11147 { 11148 int i; 11149 11150 for (i = 0; i < linkset->numchans; i++) { 11151 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) { 11152 ast_mutex_lock(&linkset->pvts[i]->lock); 11153 if (linkset->pvts[i]->owner) 11154 linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11155 ast_mutex_unlock(&linkset->pvts[i]->lock); 11156 } 11157 } 11158 }
| static void ss7_inservice | ( | struct dahdi_ss7 * | linkset, | |
| int | startcic, | |||
| int | endcic, | |||
| unsigned int | dpc | |||
| ) | [static] |
Definition at line 11179 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 11389 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_hangup_cics(), 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().
11390 { 11391 int res, i; 11392 struct timeval *next = NULL, tv; 11393 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data; 11394 struct ss7 *ss7 = linkset->ss7; 11395 ss7_event *e = NULL; 11396 struct dahdi_pvt *p; 11397 int chanpos; 11398 struct pollfd pollers[NUM_DCHANS]; 11399 int cic; 11400 unsigned int dpc; 11401 int nextms = 0; 11402 11403 ss7_start(ss7); 11404 11405 while(1) { 11406 ast_mutex_lock(&linkset->lock); 11407 if ((next = ss7_schedule_next(ss7))) { 11408 tv = ast_tvnow(); 11409 tv.tv_sec = next->tv_sec - tv.tv_sec; 11410 tv.tv_usec = next->tv_usec - tv.tv_usec; 11411 if (tv.tv_usec < 0) { 11412 tv.tv_usec += 1000000; 11413 tv.tv_sec -= 1; 11414 } 11415 if (tv.tv_sec < 0) { 11416 tv.tv_sec = 0; 11417 tv.tv_usec = 0; 11418 } 11419 nextms = tv.tv_sec * 1000; 11420 nextms += tv.tv_usec / 1000; 11421 } 11422 ast_mutex_unlock(&linkset->lock); 11423 11424 for (i = 0; i < linkset->numsigchans; i++) { 11425 pollers[i].fd = linkset->fds[i]; 11426 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]); 11427 pollers[i].revents = 0; 11428 } 11429 11430 res = poll(pollers, linkset->numsigchans, nextms); 11431 if ((res < 0) && (errno != EINTR)) { 11432 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno)); 11433 } else if (!res) { 11434 ast_mutex_lock(&linkset->lock); 11435 ss7_schedule_run(ss7); 11436 ast_mutex_unlock(&linkset->lock); 11437 continue; 11438 } 11439 11440 ast_mutex_lock(&linkset->lock); 11441 for (i = 0; i < linkset->numsigchans; i++) { 11442 if (pollers[i].revents & POLLPRI) { 11443 int x; 11444 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) { 11445 ast_log(LOG_ERROR, "Error in exception retrieval!\n"); 11446 } 11447 switch (x) { 11448 case DAHDI_EVENT_OVERRUN: 11449 ast_debug(1, "Overrun detected!\n"); 11450 break; 11451 case DAHDI_EVENT_BADFCS: 11452 ast_debug(1, "Bad FCS\n"); 11453 break; 11454 case DAHDI_EVENT_ABORT: 11455 ast_debug(1, "HDLC Abort\n"); 11456 break; 11457 case DAHDI_EVENT_ALARM: 11458 ast_log(LOG_ERROR, "Alarm on link!\n"); 11459 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM); 11460 linkset->linkstate[i] &= ~LINKSTATE_UP; 11461 ss7_link_alarm(ss7, pollers[i].fd); 11462 break; 11463 case DAHDI_EVENT_NOALARM: 11464 ast_log(LOG_ERROR, "Alarm cleared on link\n"); 11465 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN); 11466 linkset->linkstate[i] |= LINKSTATE_STARTING; 11467 ss7_link_noalarm(ss7, pollers[i].fd); 11468 break; 11469 default: 11470 ast_log(LOG_ERROR, "Got exception %d!\n", x); 11471 break; 11472 } 11473 } 11474 11475 if (pollers[i].revents & POLLIN) { 11476 res = ss7_read(ss7, pollers[i].fd); 11477 } 11478 11479 if (pollers[i].revents & POLLOUT) { 11480 res = ss7_write(ss7, pollers[i].fd); 11481 if (res < 0) { 11482 ast_debug(1, "Error in write %s\n", strerror(errno)); 11483 } 11484 } 11485 } 11486 11487 while ((e = ss7_check_event(ss7))) { 11488 switch (e->e) { 11489 case SS7_EVENT_UP: 11490 if (linkset->state != LINKSET_STATE_UP) { 11491 ast_verbose("--- SS7 Up ---\n"); 11492 ss7_reset_linkset(linkset); 11493 } 11494 linkset->state = LINKSET_STATE_UP; 11495 break; 11496 case SS7_EVENT_DOWN: 11497 ast_verbose("--- SS7 Down ---\n"); 11498 linkset->state = LINKSET_STATE_DOWN; 11499 for (i = 0; i < linkset->numchans; i++) { 11500 struct dahdi_pvt *p = linkset->pvts[i]; 11501 if (p) 11502 p->inalarm = 1; 11503 } 11504 break; 11505 case MTP2_LINK_UP: 11506 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data); 11507 break; 11508 case MTP2_LINK_DOWN: 11509 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data); 11510 break; 11511 case ISUP_EVENT_CPG: 11512 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc); 11513 if (chanpos < 0) { 11514 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic); 11515 break; 11516 } 11517 p = linkset->pvts[chanpos]; 11518 ast_mutex_lock(&p->lock); 11519 switch (e->cpg.event) { 11520 case CPG_EVENT_ALERTING: 11521 p->alerting = 1; 11522 p->subs[SUB_REAL].needringing = 1; 11523 break; 11524 case CPG_EVENT_PROGRESS: 11525 case CPG_EVENT_INBANDINFO: 11526 { 11527 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, }; 11528 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic); 11529 dahdi_queue_frame(p, &f, linkset); 11530 p->progress = 1; 11531 p->dialing = 0; 11532 if (p->dsp && p->dsp_features) { 11533 ast_dsp_set_features(p->dsp, p->dsp_features); 11534 p->dsp_features = 0; 11535 } 11536 } 11537 break; 11538 default: 11539 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event); 11540 } 11541 11542 ast_mutex_unlock(&p->lock); 11543 break; 11544 case ISUP_EVENT_RSC: 11545 ast_verbose("Resetting CIC %d\n", e->rsc.cic); 11546 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc); 11547 if (chanpos < 0) { 11548 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic); 11549 break; 11550 } 11551 p = linkset->pvts[chanpos]; 11552 ast_mutex_lock(&p->lock); 11553 p->inservice = 1; 11554 p->remotelyblocked = 0; 11555 dpc = p->dpc; 11556 isup_set_call_dpc(e->rsc.call, dpc); 11557 if (p->ss7call) 11558 p->ss7call = NULL; 11559 if (p->owner) 11560 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11561 ast_mutex_unlock(&p->lock); 11562 isup_rlc(ss7, e->rsc.call); 11563 break; 11564 case ISUP_EVENT_GRS: 11565 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic); 11566 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc); 11567 if (chanpos < 0) { 11568 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic); 11569 break; 11570 } 11571 p = linkset->pvts[chanpos]; 11572 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc); 11573 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0); 11574 ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc); 11575 break; 11576 case ISUP_EVENT_CQM: 11577 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic); 11578 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc); 11579 break; 11580 case ISUP_EVENT_GRA: 11581 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic); 11582 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc); 11583 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1); 11584 break; 11585 case ISUP_EVENT_IAM: 11586 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); 11587 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc); 11588 if (chanpos < 0) { 11589 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic); 11590 isup_rel(ss7, e->iam.call, -1); 11591 break; 11592 } 11593 p = linkset->pvts[chanpos]; 11594 ast_mutex_lock(&p->lock); 11595 if (p->owner) { 11596 if (p->ss7call == e->iam.call) { 11597 ast_mutex_unlock(&p->lock); 11598 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic); 11599 break; 11600 } else { 11601 ast_mutex_unlock(&p->lock); 11602 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic); 11603 break; 11604 } 11605 } 11606 11607 dpc = p->dpc; 11608 p->ss7call = e->iam.call; 11609 isup_set_call_dpc(p->ss7call, dpc); 11610 11611 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) { 11612 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai); 11613 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind); 11614 } else 11615 p->cid_num[0] = 0; 11616 11617 if (p->immediate) { 11618 p->exten[0] = 's'; 11619 p->exten[1] = '\0'; 11620 } else if (!ast_strlen_zero(e->iam.called_party_num)) { 11621 char *st; 11622 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai); 11623 st = strchr(p->exten, '#'); 11624 if (st) 11625 *st = '\0'; 11626 } else 11627 p->exten[0] = '\0'; 11628 11629 p->cid_ani[0] = '\0'; 11630 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name))) 11631 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name)); 11632 else 11633 p->cid_name[0] = '\0'; 11634 11635 p->cid_ani2 = e->iam.oli_ani2; 11636 p->cid_ton = 0; 11637 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number)); 11638 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number)); 11639 p->gen_add_type = e->iam.gen_add_type; 11640 p->gen_add_nai = e->iam.gen_add_nai; 11641 p->gen_add_pres_ind = e->iam.gen_add_pres_ind; 11642 p->gen_add_num_plan = e->iam.gen_add_num_plan; 11643 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number)); 11644 p->gen_dig_type = e->iam.gen_dig_type; 11645 p->gen_dig_scheme = e->iam.gen_dig_scheme; 11646 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number)); 11647 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num)); 11648 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num)); 11649 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name)); 11650 p->calling_party_cat = e->iam.calling_party_cat; 11651 11652 /* Set DNID */ 11653 if (!ast_strlen_zero(e->iam.called_party_num)) 11654 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai); 11655 11656 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) { 11657 11658 if (e->iam.cot_check_required) { 11659 dahdi_loopback(p, 1); 11660 } else 11661 ss7_start_call(p, linkset); 11662 } else { 11663 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten); 11664 p->alreadyhungup = 1; 11665 isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED); 11666 } 11667 ast_mutex_unlock(&p->lock); 11668 break; 11669 case ISUP_EVENT_COT: 11670 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc); 11671 if (chanpos < 0) { 11672 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic); 11673 isup_rel(ss7, e->cot.call, -1); 11674 break; 11675 } 11676 p = linkset->pvts[chanpos]; 11677 11678 ast_mutex_lock(&p->lock); 11679 11680 if (p->loopedback) { 11681 dahdi_loopback(p, 0); 11682 ss7_start_call(p, linkset); 11683 } 11684 11685 ast_mutex_unlock(&p->lock); 11686 11687 break; 11688 case ISUP_EVENT_CCR: 11689 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic); 11690 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc); 11691 if (chanpos < 0) { 11692 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic); 11693 break; 11694 } 11695 11696 p = linkset->pvts[chanpos]; 11697 11698 ast_mutex_lock(&p->lock); 11699 dahdi_loopback(p, 1); 11700 ast_mutex_unlock(&p->lock); 11701 11702 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc); 11703 break; 11704 case ISUP_EVENT_CVT: 11705 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic); 11706 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc); 11707 if (chanpos < 0) { 11708 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic); 11709 break; 11710 } 11711 11712 p = linkset->pvts[chanpos]; 11713 11714 ast_mutex_lock(&p->lock); 11715 dahdi_loopback(p, 1); 11716 ast_mutex_unlock(&p->lock); 11717 11718 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc); 11719 break; 11720 case ISUP_EVENT_REL: 11721 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc); 11722 if (chanpos < 0) { 11723 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic); 11724 break; 11725 } 11726 p = linkset->pvts[chanpos]; 11727 ast_mutex_lock(&p->lock); 11728 if (p->owner) { 11729 p->owner->hangupcause = e->rel.cause; 11730 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 11731 } else if (!p->restartpending) 11732 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic); 11733 11734 /* End the loopback if we have one */ 11735 dahdi_loopback(p, 0); 11736 11737 isup_rlc(ss7, e->rel.call); 11738 p->ss7call = NULL; 11739 11740 ast_mutex_unlock(&p->lock); 11741 break; 11742 case ISUP_EVENT_ACM: 11743 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc); 11744 if (chanpos < 0) { 11745 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic); 11746 isup_rel(ss7, e->acm.call, -1); 11747 break; 11748 } else { 11749 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, }; 11750 11751 p = linkset->pvts[chanpos]; 11752 11753 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic); 11754 11755 if (e->acm.call_ref_ident > 0) { 11756 p->rlt = 1; /* Setting it but not using it here*/ 11757 } 11758 11759 ast_mutex_lock(&p->lock); 11760 dahdi_queue_frame(p, &f, linkset); 11761 p->proceeding = 1; 11762 p->dialing = 0; 11763 /* Send alerting if subscriber is free */ 11764 if (e->acm.called_party_status_ind == 1) { 11765 p->alerting = 1; 11766 p->subs[SUB_REAL].needringing = 1; 11767 } 11768 ast_mutex_unlock(&p->lock); 11769 } 11770 break; 11771 case ISUP_EVENT_CGB: 11772 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc); 11773 if (chanpos < 0) { 11774 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic); 11775 break; 11776 } 11777 p = linkset->pvts[chanpos]; 11778 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1); 11779 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type); 11780 break; 11781 case ISUP_EVENT_CGU: 11782 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc); 11783 if (chanpos < 0) { 11784 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic); 11785 break; 11786 } 11787 p = linkset->pvts[chanpos]; 11788 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0); 11789 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type); 11790 break; 11791 case ISUP_EVENT_UCIC: 11792 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc); 11793 if (chanpos < 0) { 11794 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic); 11795 break; 11796 } 11797 p = linkset->pvts[chanpos]; 11798 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic); 11799 ast_mutex_lock(&p->lock); 11800 p->remotelyblocked = 1; 11801 p->inservice = 0; 11802 ast_mutex_unlock(&p->lock); //doesn't require a SS7 acknowledgement 11803 break; 11804 case ISUP_EVENT_BLO: 11805 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc); 11806 if (chanpos < 0) { 11807 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic); 11808 break; 11809 } 11810 p = linkset->pvts[chanpos]; 11811 ast_debug(1, "Blocking CIC %d\n", e->blo.cic); 11812 ast_mutex_lock(&p->lock); 11813 p->remotelyblocked = 1; 11814 ast_mutex_unlock(&p->lock); 11815 isup_bla(linkset->ss7, e->blo.cic, p->dpc); 11816 break; 11817 case ISUP_EVENT_BLA: 11818 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc); 11819 if (chanpos < 0) { 11820 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic); 11821 break; 11822 } 11823 ast_debug(1, "Blocking CIC %d\n", e->bla.cic); 11824 p = linkset->pvts[chanpos]; 11825 ast_mutex_lock(&p->lock); 11826 p->locallyblocked = 1; 11827 ast_mutex_unlock(&p->lock); 11828 break; 11829 case ISUP_EVENT_UBL: 11830 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc); 11831 if (chanpos < 0) { 11832 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic); 11833 break; 11834 } 11835 p = linkset->pvts[chanpos]; 11836 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic); 11837 ast_mutex_lock(&p->lock); 11838 p->remotelyblocked = 0; 11839 ast_mutex_unlock(&p->lock); 11840 isup_uba(linkset->ss7, e->ubl.cic, p->dpc); 11841 break; 11842 case ISUP_EVENT_UBA: 11843 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc); 11844 if (chanpos < 0) { 11845 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic); 11846 break; 11847 } 11848 p = linkset->pvts[chanpos]; 11849 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic); 11850 ast_mutex_lock(&p->lock); 11851 p->locallyblocked = 0; 11852 ast_mutex_unlock(&p->lock); 11853 break; 11854 case ISUP_EVENT_CON: 11855 case ISUP_EVENT_ANM: 11856 if (e->e == ISUP_EVENT_CON) 11857 cic = e->con.cic; 11858 else 11859 cic = e->anm.cic; 11860 11861 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc); 11862 if (chanpos < 0) { 11863 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic); 11864 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1); 11865 break; 11866 } else { 11867 p = linkset->pvts[chanpos]; 11868 ast_mutex_lock(&p->lock); 11869 p->subs[SUB_REAL].needanswer = 1; 11870 if (p->dsp && p->dsp_features) { 11871 ast_dsp_set_features(p->dsp, p->dsp_features); 11872 p->dsp_features = 0; 11873 } 11874 dahdi_enable_ec(p); 11875 ast_mutex_unlock(&p->lock); 11876 } 11877 break; 11878 case ISUP_EVENT_RLC: 11879 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc); 11880 if (chanpos < 0) { 11881 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic); 11882 break; 11883 } else { 11884 p = linkset->pvts[chanpos]; 11885 ast_mutex_lock(&p->lock); 11886 if (p->alreadyhungup) 11887 p->ss7call = NULL; 11888 else 11889 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n"); 11890 ast_mutex_unlock(&p->lock); 11891 } 11892 break; 11893 case ISUP_EVENT_FAA: 11894 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc); 11895 if (chanpos < 0) { 11896 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic); 11897 break; 11898 } else { 11899 p = linkset->pvts[chanpos]; 11900 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic); 11901 ast_mutex_lock(&p->lock); 11902 if (p->alreadyhungup){ 11903 p->ss7call = NULL; 11904 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n"); 11905 } 11906 ast_mutex_unlock(&p->lock); 11907 } 11908 break; 11909 default: 11910 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e)); 11911 break; 11912 } 11913 } 11914 ast_mutex_unlock(&linkset->lock); 11915 } 11916 11917 return 0; 11918 }
| static int ss7_pres_scr2cid_pres | ( | char | presentation_ind, | |
| char | screening_ind | |||
| ) | [static] |
Definition at line 11382 of file chan_dahdi.c.
Referenced by ss7_linkset().
| static void ss7_rel | ( | struct dahdi_ss7 * | ss7 | ) | [inline, static] |
Definition at line 1449 of file chan_dahdi.c.
References ast_mutex_unlock(), and dahdi_ss7::lock.
Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().
01450 { 01451 ast_mutex_unlock(&ss7->lock); 01452 }
| static void ss7_reset_linkset | ( | struct dahdi_ss7 * | linkset | ) | [static] |
Definition at line 11191 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().
11192 { 11193 int i, startcic = -1, endcic, dpc; 11194 11195 if (linkset->numchans <= 0) 11196 return; 11197 11198 startcic = linkset->pvts[0]->cic; 11199 /* DB: CIC's DPC fix */ 11200 dpc = linkset->pvts[0]->dpc; 11201 11202 for (i = 0; i < linkset->numchans; i++) { 11203 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)) { 11204 continue; 11205 } else { 11206 endcic = linkset->pvts[i]->cic; 11207 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic); 11208 isup_grs(linkset->ss7, startcic, endcic, dpc); 11209 11210 /* DB: CIC's DPC fix */ 11211 if (linkset->pvts[i+1]) { 11212 startcic = linkset->pvts[i+1]->cic; 11213 dpc = linkset->pvts[i+1]->dpc; 11214 } 11215 } 11216 } 11217 }
| static struct dahdi_ss7* ss7_resolve_linkset | ( | int | linkset | ) | [static, read] |
Definition at line 9874 of file chan_dahdi.c.
References linksets, and NUM_SPANS.
Referenced by linkset_addsigchan(), mkintf(), and process_dahdi().
Definition at line 11235 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().
11236 { 11237 struct ss7 *ss7 = linkset->ss7; 11238 int res; 11239 int law = 1; 11240 struct ast_channel *c; 11241 char tmp[256]; 11242 11243 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1) 11244 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno)); 11245 11246 if (linkset->type == SS7_ITU) 11247 law = DAHDI_LAW_ALAW; 11248 else 11249 law = DAHDI_LAW_MULAW; 11250 11251 res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law); 11252 if (res < 0) 11253 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel); 11254 11255 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) { 11256 p->proceeding = 1; 11257 isup_acm(ss7, p->ss7call); 11258 } 11259 11260 ast_mutex_unlock(&linkset->lock); 11261 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0); 11262 11263 if (!c) { 11264 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic); 11265 /* Holding this lock is assumed entering the function */ 11266 ast_mutex_lock(&linkset->lock); 11267 return; 11268 } else 11269 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic); 11270 11271 dahdi_enable_ec(p); 11272 11273 /* We only reference these variables in the context of the ss7_linkset function 11274 * when receiving either and IAM or a COT message. Since they are only accessed 11275 * from this context, we should be safe to unlock around them */ 11276 11277 ast_mutex_unlock(&p->lock); 11278 11279 if (!ast_strlen_zero(p->charge_number)) { 11280 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number); 11281 /* Clear this after we set it */ 11282 p->charge_number[0] = 0; 11283 } 11284 if (!ast_strlen_zero(p->gen_add_number)) { 11285 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number); 11286 /* Clear this after we set it */ 11287 p->gen_add_number[0] = 0; 11288 } 11289 if (!ast_strlen_zero(p->jip_number)) { 11290 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number); 11291 /* Clear this after we set it */ 11292 p->jip_number[0] = 0; 11293 } 11294 if (!ast_strlen_zero(p->gen_dig_number)) { 11295 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number); 11296 /* Clear this after we set it */ 11297 p->gen_dig_number[0] = 0; 11298 } 11299 if (!ast_strlen_zero(p->orig_called_num)) { 11300 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num); 11301 /* Clear this after we set it */ 11302 p->orig_called_num[0] = 0; 11303 } 11304 11305 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type); 11306 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp); 11307 /* Clear this after we set it */ 11308 p->gen_dig_type = 0; 11309 11310 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme); 11311 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp); 11312 /* Clear this after we set it */ 11313 p->gen_dig_scheme = 0; 11314 11315 if (!ast_strlen_zero(p->lspi_ident)) { 11316 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident); 11317 /* Clear this after we set it */ 11318 p->lspi_ident[0] = 0; 11319 } 11320 11321 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident); 11322 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp); 11323 /* Clear this after we set it */ 11324 p->call_ref_ident = 0; 11325 11326 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc); 11327 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp); 11328 /* Clear this after we set it */ 11329 p->call_ref_pc = 0; 11330 11331 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat); 11332 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp); 11333 /* Clear this after we set it */ 11334 p->calling_party_cat = 0; 11335 11336 if (!ast_strlen_zero(p->redirecting_num)) { 11337 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num); 11338 /* Clear this after we set it */ 11339 p->redirecting_num[0] = 0; 11340 } 11341 if (!ast_strlen_zero(p->generic_name)) { 11342 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name); 11343 /* Clear this after we set it */ 11344 p->generic_name[0] = 0; 11345 } 11346 11347 ast_mutex_lock(&p->lock); 11348 ast_mutex_lock(&linkset->lock); 11349 }
| static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 7675 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, dahdi_pvt::channel, ast_channel::cid, CID_MSGWAITING, ast_callerid::cid_name, dahdi_pvt::cid_name, CID_NOMSGWAITING, ast_callerid::cid_num, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, dahdi_pvt::exten, exten, ast_frame::frametype, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, dahdi_pvt::inalarm, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_rpas, my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, notify_message(), dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, PVT_TO_CHANNEL, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, dahdi_pvt::span, ss_thread_lock, 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().
07676 { 07677 struct ast_channel *chan = data; 07678 struct dahdi_pvt *p = chan->tech_pvt; 07679 char exten[AST_MAX_EXTENSION] = ""; 07680 char exten2[AST_MAX_EXTENSION] = ""; 07681 unsigned char buf[256]; 07682 char dtmfcid[300]; 07683 char dtmfbuf[300]; 07684 struct callerid_state *cs = NULL; 07685 char *name = NULL, *number = NULL; 07686 int distMatches; 07687 int curRingData[3]; 07688 int receivedRingT; 07689 int counter1; 07690 int counter; 07691 int samples = 0; 07692 struct ast_smdi_md_message *smdi_msg = NULL; 07693 int flags = 0; 07694 int i; 07695 int timeout; 07696 int getforward = 0; 07697 char *s1, *s2; 07698 int len = 0; 07699 int res; 07700 int idx; 07701 07702 ast_mutex_lock(&ss_thread_lock); 07703 ss_thread_count++; 07704 ast_mutex_unlock(&ss_thread_lock); 07705 /* in the bizarre case where the channel has become a zombie before we 07706 even get started here, abort safely 07707 */ 07708 if (!p) { 07709 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 07710 ast_hangup(chan); 07711 goto quit; 07712 } 07713 ast_verb(3, "Starting simple switch on '%s'\n", chan->name); 07714 idx = dahdi_get_index(chan, p, 1); 07715 if (idx < 0) { 07716 ast_log(LOG_WARNING, "Huh?\n"); 07717 ast_hangup(chan); 07718 goto quit; 07719 } 07720 if (p->dsp) 07721 ast_dsp_digitreset(p->dsp); 07722 switch (p->sig) { 07723 #ifdef HAVE_PRI 07724 case SIG_PRI: 07725 case SIG_BRI: 07726 case SIG_BRI_PTMP: 07727 /* Now loop looking for an extension */ 07728 ast_copy_string(exten, p->exten, sizeof(exten)); 07729 len = strlen(exten); 07730 res = 0; 07731 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 07732 if (len && !ast_ignore_pattern(chan->context, exten)) 07733 tone_zone_play_tone(p->subs[idx].dfd, -1); 07734 else 07735 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 07736 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 07737 timeout = matchdigittimeout; 07738 else 07739 timeout = gendigittimeout; 07740 res = ast_waitfordigit(chan, timeout); 07741 if (res < 0) { 07742 ast_debug(1, "waitfordigit returned < 0...\n"); 07743 ast_hangup(chan); 07744 goto quit; 07745 } else if (res) { 07746 exten[len++] = res; 07747 exten[len] = '\0'; 07748 } else 07749 break; 07750 } 07751 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 07752 if (ast_strlen_zero(exten)) { 07753 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n"); 07754 exten[0] = 's'; 07755 exten[1] = '\0'; 07756 } 07757 tone_zone_play_tone(p->subs[idx].dfd, -1); 07758 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 07759 /* Start the real PBX */ 07760 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 07761 if (p->dsp) { 07762 ast_dsp_digitreset(p->dsp); 07763 } 07764 if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) { 07765 if (p->pri->pri) { 07766 if (!pri_grab(p, p->pri)) { 07767 pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0); 07768 p->proceeding = 1; 07769 pri_rel(p->pri); 07770 } else { 07771 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 07772 } 07773 } 07774 } 07775 dahdi_enable_ec(p); 07776 ast_setstate(chan, AST_STATE_RING); 07777 res = ast_pbx_run(chan); 07778 if (res) { 07779 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 07780 } 07781 } else { 07782 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 07783 chan->hangupcause = AST_CAUSE_UNALLOCATED; 07784 ast_hangup(chan); 07785 p->exten[0] = '\0'; 07786 /* Since we send release complete here, we won't get one */ 07787 p->call = NULL; 07788 } 07789 goto quit; 07790 break; 07791 #endif 07792 case SIG_FEATD: 07793 case SIG_FEATDMF: 07794 case SIG_FEATDMF_TA: 07795 case SIG_E911: 07796 case SIG_FGC_CAMAMF: 07797 case SIG_FEATB: 07798 case SIG_EMWINK: 07799 case SIG_SF_FEATD: 07800 case SIG_SF_FEATDMF: 07801 case SIG_SF_FEATB: 07802 case SIG_SFWINK: 07803 if (dahdi_wink(p, idx)) 07804 goto quit; 07805 /* Fall through */ 07806 case SIG_EM: 07807 case SIG_EM_E1: 07808 case SIG_SF: 07809 case SIG_FGC_CAMA: 07810 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 07811 if (p->dsp) 07812 ast_dsp_digitreset(p->dsp); 07813 /* set digit mode appropriately */ 07814 if (p->dsp) { 07815 if (NEED_MFDETECT(p)) 07816 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 07817 else 07818 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 07819 } 07820 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 07821 /* Wait for the first digit only if immediate=no */ 07822 if (!p->immediate) 07823 /* Wait for the first digit (up to 5 seconds). */ 07824 res = ast_waitfordigit(chan, 5000); 07825 else 07826 res = 0; 07827 if (res > 0) { 07828 /* save first char */ 07829 dtmfbuf[0] = res; 07830 switch (p->sig) { 07831 case SIG_FEATD: 07832 case SIG_SF_FEATD: 07833 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 07834 if (res > 0) 07835 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 07836 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07837 break; 07838 case SIG_FEATDMF_TA: 07839 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07840 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07841 if (dahdi_wink(p, idx)) goto quit; 07842 dtmfbuf[0] = 0; 07843 /* Wait for the first digit (up to 5 seconds). */ 07844 res = ast_waitfordigit(chan, 5000); 07845 if (res <= 0) break; 07846 dtmfbuf[0] = res; 07847 /* fall through intentionally */ 07848 case SIG_FEATDMF: 07849 case SIG_E911: 07850 case SIG_FGC_CAMAMF: 07851 case SIG_SF_FEATDMF: 07852 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07853 /* if international caca, do it again to get real ANO */ 07854 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 07855 { 07856 if (dahdi_wink(p, idx)) goto quit; 07857 dtmfbuf[0] = 0; 07858 /* Wait for the first digit (up to 5 seconds). */ 07859 res = ast_waitfordigit(chan, 5000); 07860 if (res <= 0) break; 07861 dtmfbuf[0] = res; 07862 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07863 } 07864 if (res > 0) { 07865 /* if E911, take off hook */ 07866 if (p->sig == SIG_E911) 07867 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07868 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 07869 } 07870 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07871 break; 07872 case SIG_FEATB: 07873 case SIG_SF_FEATB: 07874 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 07875 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07876 break; 07877 case SIG_EMWINK: 07878 /* if we received a '*', we are actually receiving Feature Group D 07879 dial syntax, so use that mode; otherwise, fall through to normal 07880 mode 07881 */ 07882 if (res == '*') { 07883 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 07884 if (res > 0) 07885 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 07886 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 07887 break; 07888 } 07889 default: 07890 /* If we got the first digit, get the rest */ 07891 len = 1; 07892 dtmfbuf[len] = '\0'; 07893 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 07894 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 07895 timeout = matchdigittimeout; 07896 } else { 07897 timeout = gendigittimeout; 07898 } 07899 res = ast_waitfordigit(chan, timeout); 07900 if (res < 0) { 07901 ast_debug(1, "waitfordigit returned < 0...\n"); 07902 ast_hangup(chan); 07903 goto quit; 07904 } else if (res) { 07905 dtmfbuf[len++] = res; 07906 dtmfbuf[len] = '\0'; 07907 } else { 07908 break; 07909 } 07910 } 07911 break; 07912 } 07913 } 07914 if (res == -1) { 07915 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 07916 ast_hangup(chan); 07917 goto quit; 07918 } else if (res < 0) { 07919 ast_debug(1, "Got hung up before digits finished\n"); 07920 ast_hangup(chan); 07921 goto quit; 07922 } 07923 07924 if (p->sig == SIG_FGC_CAMA) { 07925 char anibuf[100]; 07926 07927 if (ast_safe_sleep(chan,1000) == -1) { 07928 ast_hangup(chan); 07929 goto quit; 07930 } 07931 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 07932 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 07933 res = my_getsigstr(chan, anibuf, "#", 10000); 07934 if ((res > 0) && (strlen(anibuf) > 2)) { 07935 if (anibuf[strlen(anibuf) - 1] == '#') 07936 anibuf[strlen(anibuf) - 1] = 0; 07937 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 07938 } 07939 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 07940 } 07941 07942 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 07943 if (ast_strlen_zero(exten)) 07944 ast_copy_string(exten, "s", sizeof(exten)); 07945 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 07946 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 07947 if (exten[0] == '*') { 07948 char *stringp=NULL; 07949 ast_copy_string(exten2, exten, sizeof(exten2)); 07950 /* Parse out extension and callerid */ 07951 stringp=exten2 +1; 07952 s1 = strsep(&stringp, "*"); 07953 s2 = strsep(&stringp, "*"); 07954 if (s2) { 07955 if (!ast_strlen_zero(p->cid_num)) 07956 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07957 else 07958 ast_set_callerid(chan, s1, NULL, s1); 07959 ast_copy_string(exten, s2, sizeof(exten)); 07960 } else 07961 ast_copy_string(exten, s1, sizeof(exten)); 07962 } else if (p->sig == SIG_FEATD) 07963 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07964 } 07965 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 07966 if (exten[0] == '*') { 07967 char *stringp=NULL; 07968 ast_copy_string(exten2, exten, sizeof(exten2)); 07969 /* Parse out extension and callerid */ 07970 stringp=exten2 +1; 07971 s1 = strsep(&stringp, "#"); 07972 s2 = strsep(&stringp, "#"); 07973 if (s2) { 07974 if (!ast_strlen_zero(p->cid_num)) 07975 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 07976 else 07977 if (*(s1 + 2)) 07978 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 07979 ast_copy_string(exten, s2 + 1, sizeof(exten)); 07980 } else 07981 ast_copy_string(exten, s1 + 2, sizeof(exten)); 07982 } else 07983 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 07984 } 07985 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 07986 if (exten[0] == '*') { 07987 char *stringp=NULL; 07988 ast_copy_string(exten2, exten, sizeof(exten2)); 07989 /* Parse out extension and callerid */ 07990 stringp=exten2 +1; 07991 s1 = strsep(&stringp, "#"); 07992 s2 = strsep(&stringp, "#"); 07993 if (s2 && (*(s2 + 1) == '0')) { 07994 if (*(s2 + 2)) 07995 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 07996 } 07997 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 07998 else ast_copy_string(exten, "911", sizeof(exten)); 07999 } else 08000 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 08001 } 08002 if (p->sig == SIG_FEATB) { 08003 if (exten[0] == '*') { 08004 char *stringp=NULL; 08005 ast_copy_string(exten2, exten, sizeof(exten2)); 08006 /* Parse out extension and callerid */ 08007 stringp=exten2 +1; 08008 s1 = strsep(&stringp, "#"); 08009 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 08010 } else 08011 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 08012 } 08013 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 08014 dahdi_wink(p, idx); 08015 /* some switches require a minimum guard time between 08016 the last FGD wink and something that answers 08017 immediately. This ensures it */ 08018 if (ast_safe_sleep(chan,100)) goto quit; 08019 } 08020 dahdi_enable_ec(p); 08021 if (NEED_MFDETECT(p)) { 08022 if (p->dsp) { 08023 if (!p->hardwaredtmf) 08024 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 08025 else { 08026 ast_dsp_free(p->dsp); 08027 p->dsp = NULL; 08028 } 08029 } 08030 } 08031 08032 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 08033 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08034 if (p->dsp) ast_dsp_digitreset(p->dsp); 08035 res = ast_pbx_run(chan); 08036 if (res) { 08037 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 08038 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08039 } 08040 goto quit; 08041 } else { 08042 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 08043 sleep(2); 08044 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO); 08045 if (res < 0) 08046 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 08047 else 08048 sleep(1); 08049 res = ast_streamfile(chan, "ss-noservice", chan->language); 08050 if (res >= 0) 08051 ast_waitstream(chan, ""); 08052 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08053 ast_hangup(chan); 08054 goto quit; 08055 } 08056 break; 08057 case SIG_FXOLS: 08058 case SIG_FXOGS: 08059 case SIG_FXOKS: 08060 /* Read the first digit */ 08061 timeout = firstdigittimeout; 08062 /* If starting a threeway call, never timeout on the first digit so someone 08063 can use flash-hook as a "hold" feature */ 08064 if (p->subs[SUB_THREEWAY].owner) 08065 timeout = 999999; 08066 while (len < AST_MAX_EXTENSION-1) { 08067 /* Read digit unless it's supposed to be immediate, in which case the 08068 only answer is 's' */ 08069 if (p->immediate) 08070 res = 's'; 08071 else 08072 res = ast_waitfordigit(chan, timeout); 08073 timeout = 0; 08074 if (res < 0) { 08075 ast_debug(1, "waitfordigit returned < 0...\n"); 08076 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 08077 ast_hangup(chan); 08078 goto quit; 08079 } else if (res) { 08080 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout); 08081 exten[len++]=res; 08082 exten[len] = '\0'; 08083 } 08084 if (!ast_ignore_pattern(chan->context, exten)) 08085 tone_zone_play_tone(p->subs[idx].dfd, -1); 08086 else 08087 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 08088 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 08089 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 08090 if (getforward) { 08091 /* Record this as the forwarding extension */ 08092 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 08093 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 08094 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08095 if (res) 08096 break; 08097 usleep(500000); 08098 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 08099 sleep(1); 08100 memset(exten, 0, sizeof(exten)); 08101 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE); 08102 len = 0; 08103 getforward = 0; 08104 } else { 08105 res = tone_zone_play_tone(p->subs[idx].dfd, -1); 08106 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 08107 if (!ast_strlen_zero(p->cid_num)) { 08108 if (!p->hidecallerid) 08109 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 08110 else 08111 ast_set_callerid(chan, NULL, NULL, p->cid_num); 08112 } 08113 if (!ast_strlen_zero(p->cid_name)) { 08114 if (!p->hidecallerid) 08115 ast_set_callerid(chan, NULL, p->cid_name, NULL); 08116 } 08117 ast_setstate(chan, AST_STATE_RING); 08118 dahdi_enable_ec(p); 08119 res = ast_pbx_run(chan); 08120 if (res) { 08121 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 08122 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08123 } 08124 goto quit; 08125 } 08126 } else { 08127 /* It's a match, but they just typed a digit, and there is an ambiguous match, 08128 so just set the timeout to matchdigittimeout and wait some more */ 08129 timeout = matchdigittimeout; 08130 } 08131 } else if (res == 0) { 08132 ast_debug(1, "not enough digits (and no ambiguous match)...\n"); 08133 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08134 dahdi_wait_event(p->subs[idx].dfd); 08135 ast_hangup(chan); 08136 goto quit; 08137 } else if (p->callwaiting && !strcmp(exten, "*70")) { 08138 ast_verb(3, "Disabling call waiting on %s\n", chan->name); 08139 /* Disable call waiting if enabled */ 08140 p->callwaiting = 0; 08141 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08142 if (res) { 08143 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 08144 chan->name, strerror(errno)); 08145 } 08146 len = 0; 08147 ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len); 08148 memset(exten, 0, sizeof(exten)); 08149 timeout = firstdigittimeout; 08150 08151 } else if (!strcmp(exten,ast_pickup_ext())) { 08152 /* Scan all channels and see if there are any 08153 * ringing channels that have call groups 08154 * that equal this channels pickup group 08155 */ 08156 if (idx == SUB_REAL) { 08157 /* Switch us from Third call to Call Wait */ 08158 if (p->subs[SUB_THREEWAY].owner) { 08159 /* If you make a threeway call and the *8# a call, it should actually 08160 look like a callwait */ 08161 alloc_sub(p, SUB_CALLWAIT); 08162 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 08163 unalloc_sub(p, SUB_THREEWAY); 08164 } 08165 dahdi_enable_ec(p); 08166 if (ast_pickup_call(chan)) { 08167 ast_debug(1, "No call pickup possible...\n"); 08168 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08169 dahdi_wait_event(p->subs[idx].dfd); 08170 } 08171 ast_hangup(chan); 08172 goto quit; 08173 } else { 08174 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 08175 ast_hangup(chan); 08176 goto quit; 08177 } 08178 08179 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 08180 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name); 08181 /* Disable Caller*ID if enabled */ 08182 p->hidecallerid = 1; 08183 if (chan->cid.cid_num) 08184 ast_free(chan->cid.cid_num); 08185 chan->cid.cid_num = NULL; 08186 if (chan->cid.cid_name) 08187 ast_free(chan->cid.cid_name); 08188 chan->cid.cid_name = NULL; 08189 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08190 if (res) { 08191 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 08192 chan->name, strerror(errno)); 08193 } 08194 len = 0; 08195 memset(exten, 0, sizeof(exten)); 08196 timeout = firstdigittimeout; 08197 } else if (p->callreturn && !strcmp(exten, "*69")) { 08198 res = 0; 08199 if (!ast_strlen_zero(p->lastcid_num)) { 08200 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 08201 } 08202 if (!res) 08203 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08204 break; 08205 } else if (!strcmp(exten, "*78")) { 08206 dahdi_dnd(p, 1); 08207 /* Do not disturb */ 08208 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08209 getforward = 0; 08210 memset(exten, 0, sizeof(exten)); 08211 len = 0; 08212 } else if (!strcmp(exten, "*79")) { 08213 dahdi_dnd(p, 0); 08214 /* Do not disturb */ 08215 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08216 getforward = 0; 08217 memset(exten, 0, sizeof(exten)); 08218 len = 0; 08219 } else if (p->cancallforward && !strcmp(exten, "*72")) { 08220 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08221 getforward = 1; 08222 memset(exten, 0, sizeof(exten)); 08223 len = 0; 08224 } else if (p->cancallforward && !strcmp(exten, "*73")) { 08225 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel); 08226 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08227 memset(p->call_forward, 0, sizeof(p->call_forward)); 08228 getforward = 0; 08229 memset(exten, 0, sizeof(exten)); 08230 len = 0; 08231 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 08232 p->subs[SUB_THREEWAY].owner && 08233 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 08234 /* This is a three way call, the main call being a real channel, 08235 and we're parking the first call. */ 08236 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 08237 ast_verb(3, "Parking call to '%s'\n", chan->name); 08238 break; 08239 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 08240 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num); 08241 res = ast_db_put("blacklist", p->lastcid_num, "1"); 08242 if (!res) { 08243 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08244 memset(exten, 0, sizeof(exten)); 08245 len = 0; 08246 } 08247 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 08248 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name); 08249 /* Enable Caller*ID if enabled */ 08250 p->hidecallerid = 0; 08251 if (chan->cid.cid_num) 08252 ast_free(chan->cid.cid_num); 08253 chan->cid.cid_num = NULL; 08254 if (chan->cid.cid_name) 08255 ast_free(chan->cid.cid_name); 08256 chan->cid.cid_name = NULL; 08257 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 08258 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL); 08259 if (res) { 08260 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 08261 chan->name, strerror(errno)); 08262 } 08263 len = 0; 08264 memset(exten, 0, sizeof(exten)); 08265 timeout = firstdigittimeout; 08266 } else if (!strcmp(exten, "*0")) { 08267 struct ast_channel *nbridge = 08268 p->subs[SUB_THREEWAY].owner; 08269 struct dahdi_pvt *pbridge = NULL; 08270 /* set up the private struct of the bridged one, if any */ 08271 if (nbridge && ast_bridged_channel(nbridge)) 08272 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 08273 if (nbridge && pbridge && 08274 (nbridge->tech == &dahdi_tech) && 08275 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) && 08276 ISTRUNK(pbridge)) { 08277 int func = DAHDI_FLASH; 08278 /* Clear out the dial buffer */ 08279 p->dop.dialstr[0] = '\0'; 08280 /* flash hookswitch */ 08281 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 08282 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 08283 nbridge->name, strerror(errno)); 08284 } 08285 swap_subs(p, SUB_REAL, SUB_THREEWAY); 08286 unalloc_sub(p, SUB_THREEWAY); 08287 p->owner = p->subs[SUB_REAL].owner; 08288 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 08289 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 08290 ast_hangup(chan); 08291 goto quit; 08292 } else { 08293 tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08294 dahdi_wait_event(p->subs[idx].dfd); 08295 tone_zone_play_tone(p->subs[idx].dfd, -1); 08296 swap_subs(p, SUB_REAL, SUB_THREEWAY); 08297 unalloc_sub(p, SUB_THREEWAY); 08298 p->owner = p->subs[SUB_REAL].owner; 08299 ast_hangup(chan); 08300 goto quit; 08301 } 08302 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 08303 ((exten[0] != '*') || (strlen(exten) > 2))) { 08304 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); 08305 break; 08306 } 08307 if (!timeout) 08308 timeout = gendigittimeout; 08309 if (len && !ast_ignore_pattern(chan->context, exten)) 08310 tone_zone_play_tone(p->subs[idx].dfd, -1); 08311 } 08312 break; 08313 case SIG_FXSLS: 08314 case SIG_FXSGS: 08315 case SIG_FXSKS: 08316 #ifdef HAVE_PRI 08317 if (p->pri) { 08318 /* This is a GR-303 trunk actually. Wait for the first ring... */ 08319 struct ast_frame *f; 08320 int res; 08321 time_t start; 08322 08323 time(&start); 08324 ast_setstate(chan, AST_STATE_RING); 08325 while (time(NULL) < start + 3) { 08326 res = ast_waitfor(chan, 1000); 08327 if (res) { 08328 f = ast_read(chan); 08329 if (!f) { 08330 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 08331 ast_hangup(chan); 08332 goto quit; 08333 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 08334 res = 1; 08335 } else 08336 res = 0; 08337 ast_frfree(f); 08338 if (res) { 08339 ast_debug(1, "Got ring!\n"); 08340 res = 0; 08341 break; 08342 } 08343 } 08344 } 08345 } 08346 #endif 08347 /* check for SMDI messages */ 08348 if (p->use_smdi && p->smdi_iface) { 08349 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 08350 08351 if (smdi_msg != NULL) { 08352 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 08353 08354 if (smdi_msg->type == 'B') 08355 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 08356 else if (smdi_msg->type == 'N') 08357 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 08358 08359 ast_debug(1, "Received SMDI message on %s\n", chan->name); 08360 } else { 08361 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 08362 } 08363 } 08364 08365 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 08366 number = smdi_msg->calling_st; 08367 08368 /* If we want caller id, we're in a prering state due to a polarity reversal 08369 * and we're set to use a polarity reversal to trigger the start of caller id, 08370 * grab the caller id and wait for ringing to start... */ 08371 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) { 08372 /* If set to use DTMF CID signalling, listen for DTMF */ 08373 if (p->cid_signalling == CID_SIG_DTMF) { 08374 int k = 0; 08375 cs = NULL; 08376 ast_debug(1, "Receiving DTMF cid on " 08377 "channel %s\n", chan->name); 08378 dahdi_setlinear(p->subs[idx].dfd, 0); 08379 res = 2000; 08380 for (;;) { 08381 struct ast_frame *f; 08382 res = ast_waitfor(chan, res); 08383 if (res <= 0) { 08384 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 08385 "Exiting simple switch\n"); 08386 ast_hangup(chan); 08387 goto quit; 08388 } 08389 f = ast_read(chan); 08390 if (!f) 08391 break; 08392 if (f->frametype == AST_FRAME_DTMF) { 08393 dtmfbuf[k++] = f->subclass; 08394 ast_debug(1, "CID got digit '%c'\n", f->subclass); 08395 res = 2000; 08396 } 08397 ast_frfree(f); 08398 if (chan->_state == AST_STATE_RING || 08399 chan->_state == AST_STATE_RINGING) 08400 break; /* Got ring */ 08401 } 08402 dtmfbuf[k] = '\0'; 08403 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 08404 /* Got cid and ring. */ 08405 ast_debug(1, "CID got string '%s'\n", dtmfbuf); 08406 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 08407 ast_debug(1, "CID is '%s', flags %d\n", 08408 dtmfcid, flags); 08409 /* If first byte is NULL, we have no cid */ 08410 if (!ast_strlen_zero(dtmfcid)) 08411 number = dtmfcid; 08412 else 08413 number = NULL; 08414 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 08415 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 08416 cs = callerid_new(p->cid_signalling); 08417 if (cs) { 08418 samples = 0; 08419 #if 1 08420 bump_gains(p); 08421 #endif 08422 /* Take out of linear mode for Caller*ID processing */ 08423 dahdi_setlinear(p->subs[idx].dfd, 0); 08424 08425 /* First we wait and listen for the Caller*ID */ 08426 for (;;) { 08427 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08428 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 08429 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08430 callerid_free(cs); 08431 ast_hangup(chan); 08432 goto quit; 08433 } 08434 if (i & DAHDI_IOMUX_SIGEVENT) { 08435 res = dahdi_get_event(p->subs[idx].dfd); 08436 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08437 if (res == DAHDI_EVENT_NOALARM) { 08438 p->inalarm = 0; 08439 } 08440 08441 if (p->cid_signalling == CID_SIG_V23_JP) { 08442 if (res == DAHDI_EVENT_RINGBEGIN) { 08443 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 08444 usleep(1); 08445 } 08446 } else { 08447 res = 0; 08448 break; 08449 } 08450 } else if (i & DAHDI_IOMUX_READ) { 08451 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 08452 if (res < 0) { 08453 if (errno != ELAST) { 08454 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08455 callerid_free(cs); 08456 ast_hangup(chan); 08457 goto quit; 08458 } 08459 break; 08460 } 08461 samples += res; 08462 08463 if (p->cid_signalling == CID_SIG_V23_JP) { 08464 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 08465 } else { 08466 res = callerid_feed(cs, buf, res, AST_LAW(p)); 08467 } 08468 08469 if (res < 0) { 08470 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 08471 break; 08472 } else if (res) 08473 break; 08474 else if (samples > (8000 * 10)) 08475 break; 08476 } 08477 } 08478 if (res == 1) { 08479 callerid_get(cs, &name, &number, &flags); 08480 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 08481 } 08482 08483 if (p->cid_signalling == CID_SIG_V23_JP) { 08484 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 08485 usleep(1); 08486 res = 4000; 08487 } else { 08488 08489 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 08490 res = 2000; 08491 } 08492 08493 for (;;) { 08494 struct ast_frame *f; 08495 res = ast_waitfor(chan, res); 08496 if (res <= 0) { 08497 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 08498 "Exiting simple switch\n"); 08499 ast_hangup(chan); 08500 goto quit; 08501 } 08502 if (!(f = ast_read(chan))) { 08503 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 08504 ast_hangup(chan); 08505 goto quit; 08506 } 08507 ast_frfree(f); 08508 if (chan->_state == AST_STATE_RING || 08509 chan->_state == AST_STATE_RINGING) 08510 break; /* Got ring */ 08511 } 08512 08513 /* We must have a ring by now, so, if configured, lets try to listen for 08514 * distinctive ringing */ 08515 if (p->usedistinctiveringdetection) { 08516 len = 0; 08517 distMatches = 0; 08518 /* Clear the current ring data array so we dont have old data in it. */ 08519 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 08520 curRingData[receivedRingT] = 0; 08521 receivedRingT = 0; 08522 counter = 0; 08523 counter1 = 0; 08524 /* Check to see if context is what it should be, if not set to be. */ 08525 if (strcmp(p->context,p->defcontext) != 0) { 08526 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 08527 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 08528 } 08529 08530 for (;;) { 08531 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08532 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 08533 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08534 callerid_free(cs); 08535 ast_hangup(chan); 08536 goto quit; 08537 } 08538 if (i & DAHDI_IOMUX_SIGEVENT) { 08539 res = dahdi_get_event(p->subs[idx].dfd); 08540 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08541 if (res == DAHDI_EVENT_NOALARM) { 08542 p->inalarm = 0; 08543 } 08544 res = 0; 08545 /* Let us detect distinctive ring */ 08546 08547 curRingData[receivedRingT] = p->ringt; 08548 08549 if (p->ringt < p->ringt_base/2) 08550 break; 08551 /* Increment the ringT counter so we can match it against 08552 values in chan_dahdi.conf for distinctive ring */ 08553 if (++receivedRingT == ARRAY_LEN(curRingData)) 08554 break; 08555 } else if (i & DAHDI_IOMUX_READ) { 08556 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 08557 if (res < 0) { 08558 if (errno != ELAST) { 08559 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08560 callerid_free(cs); 08561 ast_hangup(chan); 08562 goto quit; 08563 } 08564 break; 08565 } 08566 if (p->ringt) 08567 p->ringt--; 08568 if (p->ringt == 1) { 08569 res = -1; 08570 break; 08571 } 08572 } 08573 } 08574 /* this only shows up if you have n of the dring patterns filled in */ 08575 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 08576 for (counter = 0; counter < 3; counter++) { 08577 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 08578 channel */ 08579 distMatches = 0; 08580 for (counter1 = 0; counter1 < 3; counter1++) { 08581 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 08582 if (p->drings.ringnum[counter].ring[counter1] == -1) { 08583 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 08584 curRingData[counter1]); 08585 distMatches++; 08586 } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 08587 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 08588 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 08589 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 08590 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 08591 distMatches++; 08592 } 08593 } 08594 08595 if (distMatches == 3) { 08596 /* The ring matches, set the context to whatever is for distinctive ring.. */ 08597 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 08598 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 08599 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 08600 break; 08601 } 08602 } 08603 } 08604 /* Restore linear mode (if appropriate) for Caller*ID processing */ 08605 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 08606 #if 1 08607 restore_gains(p); 08608 #endif 08609 } else 08610 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 08611 } else { 08612 ast_log(LOG_WARNING, "Channel %s in prering " 08613 "state, but I have nothing to do. " 08614 "Terminating simple switch, should be " 08615 "restarted by the actual ring.\n", 08616 chan->name); 08617 ast_hangup(chan); 08618 goto quit; 08619 } 08620 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 08621 if (p->cid_signalling == CID_SIG_DTMF) { 08622 int k = 0; 08623 cs = NULL; 08624 dahdi_setlinear(p->subs[idx].dfd, 0); 08625 res = 2000; 08626 for (;;) { 08627 struct ast_frame *f; 08628 res = ast_waitfor(chan, res); 08629 if (res <= 0) { 08630 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 08631 "Exiting simple switch\n"); 08632 ast_hangup(chan); 08633 return NULL; 08634 } 08635 f = ast_read(chan); 08636 if (f->frametype == AST_FRAME_DTMF) { 08637 dtmfbuf[k++] = f->subclass; 08638 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 08639 res = 2000; 08640 } 08641 ast_frfree(f); 08642 08643 if (p->ringt_base == p->ringt) 08644 break; 08645 } 08646 dtmfbuf[k] = '\0'; 08647 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 08648 /* Got cid and ring. */ 08649 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 08650 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 08651 dtmfcid, flags); 08652 /* If first byte is NULL, we have no cid */ 08653 if (!ast_strlen_zero(dtmfcid)) 08654 number = dtmfcid; 08655 else 08656 number = NULL; 08657 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 08658 } else { 08659 /* FSK Bell202 callerID */ 08660 cs = callerid_new(p->cid_signalling); 08661 if (cs) { 08662 #if 1 08663 bump_gains(p); 08664 #endif 08665 samples = 0; 08666 len = 0; 08667 distMatches = 0; 08668 /* Clear the current ring data array so we dont have old data in it. */ 08669 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++) 08670 curRingData[receivedRingT] = 0; 08671 receivedRingT = 0; 08672 counter = 0; 08673 counter1 = 0; 08674 /* Check to see if context is what it should be, if not set to be. */ 08675 if (strcmp(p->context,p->defcontext) != 0) { 08676 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 08677 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 08678 } 08679 08680 /* Take out of linear mode for Caller*ID processing */ 08681 dahdi_setlinear(p->subs[idx].dfd, 0); 08682 for (;;) { 08683 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08684 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 08685 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08686 callerid_free(cs); 08687 ast_hangup(chan); 08688 goto quit; 08689 } 08690 if (i & DAHDI_IOMUX_SIGEVENT) { 08691 res = dahdi_get_event(p->subs[idx].dfd); 08692 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08693 if (res == DAHDI_EVENT_NOALARM) { 08694 p->inalarm = 0; 08695 } 08696 /* If we get a PR event, they hung up while processing calerid */ 08697 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 08698 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 08699 p->polarity = POLARITY_IDLE; 08700 callerid_free(cs); 08701 ast_hangup(chan); 08702 goto quit; 08703 } 08704 res = 0; 08705 /* Let us detect callerid when the telco uses distinctive ring */ 08706 08707 curRingData[receivedRingT] = p->ringt; 08708 08709 if (p->ringt < p->ringt_base/2) 08710 break; 08711 /* Increment the ringT counter so we can match it against 08712 values in chan_dahdi.conf for distinctive ring */ 08713 if (++receivedRingT == ARRAY_LEN(curRingData)) 08714 break; 08715 } else if (i & DAHDI_IOMUX_READ) { 08716 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 08717 if (res < 0) { 08718 if (errno != ELAST) { 08719 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08720 callerid_free(cs); 08721 ast_hangup(chan); 08722 goto quit; 08723 } 08724 break; 08725 } 08726 if (p->ringt) 08727 p->ringt--; 08728 if (p->ringt == 1) { 08729 res = -1; 08730 break; 08731 } 08732 samples += res; 08733 res = callerid_feed(cs, buf, res, AST_LAW(p)); 08734 if (res < 0) { 08735 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 08736 break; 08737 } else if (res) 08738 break; 08739 else if (samples > (8000 * 10)) 08740 break; 08741 } 08742 } 08743 if (res == 1) { 08744 callerid_get(cs, &name, &number, &flags); 08745 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 08746 } 08747 if (distinctiveringaftercid == 1) { 08748 /* Clear the current ring data array so we dont have old data in it. */ 08749 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 08750 curRingData[receivedRingT] = 0; 08751 } 08752 receivedRingT = 0; 08753 ast_verb(3, "Detecting post-CID distinctive ring\n"); 08754 for (;;) { 08755 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 08756 if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { 08757 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 08758 callerid_free(cs); 08759 ast_hangup(chan); 08760 goto quit; 08761 } 08762 if (i & DAHDI_IOMUX_SIGEVENT) { 08763 res = dahdi_get_event(p->subs[idx].dfd); 08764 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 08765 if (res == DAHDI_EVENT_NOALARM) { 08766 p->inalarm = 0; 08767 } 08768 res = 0; 08769 /* Let us detect callerid when the telco uses distinctive ring */ 08770 08771 curRingData[receivedRingT] = p->ringt; 08772 08773 if (p->ringt < p->ringt_base/2) 08774 break; 08775 /* Increment the ringT counter so we can match it against 08776 values in chan_dahdi.conf for distinctive ring */ 08777 if (++receivedRingT == ARRAY_LEN(curRingData)) 08778 break; 08779 } else if (i & DAHDI_IOMUX_READ) { 08780 res = read(p->subs[idx].dfd, buf, sizeof(buf)); 08781 if (res < 0) { 08782 if (errno != ELAST) { 08783 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 08784 callerid_free(cs); 08785 ast_hangup(chan); 08786 goto quit; 08787 } 08788 break; 08789 } 08790 if (p->ringt) 08791 p->ringt--; 08792 if (p->ringt == 1) { 08793 res = -1; 08794 break; 08795 } 08796 } 08797 } 08798 } 08799 if (p->usedistinctiveringdetection) { 08800 /* this only shows up if you have n of the dring patterns filled in */ 08801 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 08802 08803 for (counter = 0; counter < 3; counter++) { 08804 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 08805 channel */ 08806 /* this only shows up if you have n of the dring patterns filled in */ 08807 ast_verb(3, "Checking %d,%d,%d\n", 08808 p->drings.ringnum[counter].ring[0], 08809 p->drings.ringnum[counter].ring[1], 08810 p->drings.ringnum[counter].ring[2]); 08811 distMatches = 0; 08812 for (counter1 = 0; counter1 < 3; counter1++) { 08813 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); 08814 if (p->drings.ringnum[counter].ring[counter1] == -1) { 08815 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", 08816 curRingData[counter1]); 08817 distMatches++; 08818 } 08819 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && 08820 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { 08821 ast_verb(3, "Ring pattern matched in range: %d to %d\n", 08822 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), 08823 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); 08824 distMatches++; 08825 } 08826 } 08827 if (distMatches == 3) { 08828 /* The ring matches, set the context to whatever is for distinctive ring.. */ 08829 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 08830 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 08831 ast_verb(3, "Distinctive Ring matched context %s\n",p->context); 08832 break; 08833 } 08834 } 08835 } 08836 /* Restore linear mode (if appropriate) for Caller*ID processing */ 08837 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); 08838 #if 1 08839 restore_gains(p); 08840 #endif 08841 if (res < 0) { 08842 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 08843 } 08844 } else 08845 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 08846 } 08847 } else 08848 cs = NULL; 08849 08850 if (number) 08851 ast_shrink_phone_number(number); 08852 ast_set_callerid(chan, number, name, number); 08853 08854 if (smdi_msg) 08855 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 08856 08857 if (cs) 08858 callerid_free(cs); 08859 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */ 08860 if (flags & CID_MSGWAITING) { 08861 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel); 08862 notify_message(p->mailbox, 1); 08863 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 08864 if (p->mwimonitor_rpas) { 08865 ast_hangup(chan); 08866 return NULL; 08867 } 08868 } else if (flags & CID_NOMSGWAITING) { 08869 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel); 08870 notify_message(p->mailbox, 0); 08871 /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */ 08872 if (p->mwimonitor_rpas) { 08873 ast_hangup(chan); 08874 return NULL; 08875 } 08876 } 08877 08878 ast_setstate(chan, AST_STATE_RING); 08879 chan->rings = 1; 08880 p->ringt = p->ringt_base; 08881 res = ast_pbx_run(chan); 08882 if (res) { 08883 ast_hangup(chan); 08884 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 08885 } 08886 goto quit; 08887 default: 08888 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 08889 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08890 if (res < 0) 08891 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 08892 } 08893 res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION); 08894 if (res < 0) 08895 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 08896 ast_hangup(chan); 08897 quit: 08898 ast_mutex_lock(&ss_thread_lock); 08899 ss_thread_count--; 08900 ast_cond_signal(&ss_thread_complete); 08901 ast_mutex_unlock(&ss_thread_lock); 08902 return NULL; 08903 }
| static int start_pri | ( | struct dahdi_pri * | pri | ) | [static] |
Definition at line 13537 of file chan_dahdi.c.
References ast_log(), ast_pthread_create_background, DAHDI_CHAN_MAPPING_LOGICAL, 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, NUM_DCHANS, dahdi_pri::overlapdial, dahdi_pri::pri, pri_dchannel(), dahdi_pri::qsigchannelmapping, dahdi_pri::resetpos, dahdi_pri::sig, SIG_BRI, SIG_BRI_PTMP, and dahdi_pri::switchtype.
Referenced by setup_dahdi().
13538 { 13539 int res, x; 13540 struct dahdi_params p; 13541 struct dahdi_bufferinfo bi; 13542 struct dahdi_spaninfo si; 13543 int i; 13544 13545 for (i = 0; i < NUM_DCHANS; i++) { 13546 if (!pri->dchannels[i]) 13547 break; 13548 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR); 13549 x = pri->dchannels[i]; 13550 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) { 13551 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno)); 13552 return -1; 13553 } 13554 memset(&p, 0, sizeof(p)); 13555 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p); 13556 if (res) { 13557 dahdi_close_pri_fd(pri, i); 13558 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno)); 13559 return -1; 13560 } 13561 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) { 13562 dahdi_close_pri_fd(pri, i); 13563 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x); 13564 return -1; 13565 } 13566 memset(&si, 0, sizeof(si)); 13567 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si); 13568 if (res) { 13569 dahdi_close_pri_fd(pri, i); 13570 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno)); 13571 } 13572 if (!si.alarms) 13573 pri->dchanavail[i] |= DCHAN_NOTINALARM; 13574 else 13575 pri->dchanavail[i] &= ~DCHAN_NOTINALARM; 13576 memset(&bi, 0, sizeof(bi)); 13577 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 13578 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 13579 bi.numbufs = 32; 13580 bi.bufsize = 1024; 13581 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) { 13582 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno)); 13583 dahdi_close_pri_fd(pri, i); 13584 return -1; 13585 } 13586 switch (pri->sig) { 13587 case SIG_BRI: 13588 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype); 13589 break; 13590 case SIG_BRI_PTMP: 13591 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype); 13592 break; 13593 default: 13594 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype); 13595 break; 13596 } 13597 /* Force overlap dial if we're doing GR-303! */ 13598 if (pri->switchtype == PRI_SWITCH_GR303_TMC) 13599 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH; 13600 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0); 13601 #ifdef HAVE_PRI_PROG_W_CAUSE 13602 pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL); 13603 #endif 13604 #ifdef HAVE_PRI_INBANDDISCONNECT 13605 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect); 13606 #endif 13607 /* Enslave to master if appropriate */ 13608 if (i) 13609 pri_enslave(pri->dchans[0], pri->dchans[i]); 13610 if (!pri->dchans[i]) { 13611 dahdi_close_pri_fd(pri, i); 13612 ast_log(LOG_ERROR, "Unable to create PRI structure\n"); 13613 return -1; 13614 } 13615 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG); 13616 pri_set_nsf(pri->dchans[i], pri->nsf); 13617 #ifdef PRI_GETSET_TIMERS 13618 for (x = 0; x < PRI_MAX_TIMERS; x++) { 13619 if (pritimers[x] != 0) 13620 pri_set_timer(pri->dchans[i], x, pritimers[x]); 13621 } 13622 #endif 13623 } 13624 /* Assume primary is the one we use */ 13625 pri->pri = pri->dchans[0]; 13626 pri->resetpos = -1; 13627 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { 13628 for (i = 0; i < NUM_DCHANS; i++) { 13629 if (!pri->dchannels[i]) 13630 break; 13631 dahdi_close_pri_fd(pri, i); 13632 } 13633 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno)); 13634 return -1; 13635 } 13636 return 0; 13637 }
| static void swap_subs | ( | struct dahdi_pvt * | p, | |
| int | a, | |||
| int | b | |||
| ) | [static] |
Definition at line 2062 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().
02063 { 02064 int tchan; 02065 int tinthreeway; 02066 struct ast_channel *towner; 02067 02068 ast_debug(1, "Swapping %d and %d\n", a, b); 02069 02070 tchan = p->subs[a].chan; 02071 towner = p->subs[a].owner; 02072 tinthreeway = p->subs[a].inthreeway; 02073 02074 p->subs[a].chan = p->subs[b].chan; 02075 p->subs[a].owner = p->subs[b].owner; 02076 p->subs[a].inthreeway = p->subs[b].inthreeway; 02077 02078 p->subs[b].chan = tchan; 02079 p->subs[b].owner = towner; 02080 p->subs[b].inthreeway = tinthreeway; 02081 02082 if (p->subs[a].owner) 02083 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd); 02084 if (p->subs[b].owner) 02085 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd); 02086 wakeup_sub(p, a, NULL); 02087 wakeup_sub(p, b, NULL); 02088 }
| static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
| int | x | |||
| ) | [static] |
Definition at line 2212 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().
02213 { 02214 if (!x) { 02215 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 02216 return -1; 02217 } 02218 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel); 02219 dahdi_close_sub(p, x); 02220 p->subs[x].linear = 0; 02221 p->subs[x].chan = 0; 02222 p->subs[x].owner = NULL; 02223 p->subs[x].inthreeway = 0; 02224 p->polarity = POLARITY_IDLE; 02225 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 02226 return 0; 02227 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 15932 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), linksets, lock, NUM_SPANS, and pris.
15933 { 15934 #if defined(HAVE_PRI) || defined(HAVE_SS7) 15935 int y; 15936 #endif 15937 #ifdef HAVE_PRI 15938 for (y = 0; y < NUM_SPANS; y++) 15939 ast_mutex_destroy(&pris[y].lock); 15940 #endif 15941 #ifdef HAVE_SS7 15942 for (y = 0; y < NUM_SPANS; y++) 15943 ast_mutex_destroy(&linksets[y].lock); 15944 #endif /* HAVE_SS7 */ 15945 return __unload_module(); 15946 }
| static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 2604 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().
02605 { 02606 int needconf = 0; 02607 int x; 02608 int useslavenative; 02609 struct dahdi_pvt *slave = NULL; 02610 02611 useslavenative = isslavenative(p, &slave); 02612 /* Start with the obvious, general stuff */ 02613 for (x = 0; x < 3; x++) { 02614 /* Look for three way calls */ 02615 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 02616 conf_add(p, &p->subs[x], x, 0); 02617 needconf++; 02618 } else { 02619 conf_del(p, &p->subs[x], x); 02620 } 02621 } 02622 /* If we have a slave, add him to our conference now. or DAX 02623 if this is slave native */ 02624 for (x = 0; x < MAX_SLAVES; x++) { 02625 if (p->slaves[x]) { 02626 if (useslavenative) 02627 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 02628 else { 02629 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 02630 needconf++; 02631 } 02632 } 02633 } 02634 /* If we're supposed to be in there, do so now */ 02635 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 02636 if (useslavenative) 02637 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 02638 else { 02639 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 02640 needconf++; 02641 } 02642 } 02643 /* If we have a master, add ourselves to his conference */ 02644 if (p->master) { 02645 if (isslavenative(p->master, NULL)) { 02646 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 02647 } else { 02648 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 02649 } 02650 } 02651 if (!needconf) { 02652 /* Nobody is left (or should be left) in our conference. 02653 Kill it. */ 02654 p->confno = -1; 02655 } 02656 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 02657 return 0; 02658 }
Definition at line 1520 of file chan_dahdi.c.
References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by pri_fixup_principle(), and swap_subs().
01521 { 01522 #ifdef HAVE_PRI 01523 if (pri) 01524 ast_mutex_unlock(&pri->lock); 01525 #endif 01526 for (;;) { 01527 if (p->subs[a].owner) { 01528 if (ast_channel_trylock(p->subs[a].owner)) { 01529 DEADLOCK_AVOIDANCE(&p->lock); 01530 } else { 01531 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 01532 ast_channel_unlock(p->subs[a].owner); 01533 break; 01534 } 01535 } else 01536 break; 01537 } 01538 #ifdef HAVE_PRI 01539 if (pri) 01540 ast_mutex_lock(&pri->lock); 01541 #endif 01542 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 17500 of file chan_dahdi.c.
| int alarm |
Definition at line 2367 of file chan_dahdi.c.
struct { ... } alarms[] [static] |
Referenced by alarm2str().
struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static] |
Definition at line 1495 of file chan_dahdi.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 17500 of file chan_dahdi.c.
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 1476 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 1487 of file chan_dahdi.c.
const char config[] = "chan_dahdi.conf" [static] |
Definition at line 238 of file chan_dahdi.c.
int cur_adjpointcode = -1 [static] |
Definition at line 456 of file chan_dahdi.c.
int cur_cicbeginswith = -1 [static] |
Definition at line 455 of file chan_dahdi.c.
int cur_defaultdpc = -1 [static] |
Definition at line 458 of file chan_dahdi.c.
int cur_linkset = -1 [static] |
Definition at line 453 of file chan_dahdi.c.
int cur_networkindicator = -1 [static] |
Definition at line 457 of file chan_dahdi.c.
int cur_pointcode = -1 [static] |
Definition at line 454 of file chan_dahdi.c.
int cur_ss7type = -1 [static] |
Definition at line 452 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
Definition at line 15169 of file chan_dahdi.c.
struct ast_cli_entry dahdi_pri_cli[] [static] |
Definition at line 13943 of file chan_dahdi.c.
char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static] |
Definition at line 3960 of file chan_dahdi.c.
struct ast_cli_entry dahdi_ss7_cli[] [static] |
Definition at line 15838 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
Definition at line 1401 of file chan_dahdi.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 173 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 296 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 297 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 310 of file chan_dahdi.c.
char* events[] [static] |
Definition at line 2344 of file chan_dahdi.c.
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 326 of file chan_dahdi.c.
Referenced by disa_exec().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 329 of file chan_dahdi.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 181 of file chan_dahdi.c.
Referenced by dahdi_new(), process_dahdi(), and setup_dahdi().
int ifcount = 0 [static] |
Definition at line 342 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), duplicate_pseudo(), find_channel(), load_module(), mkintf(), and phone_request().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the interface list (of dahdi_pvt's).
Definition at line 335 of file chan_dahdi.c.
Referenced by __unload_module(), action_dahdishowchannels(), dahdi_hangup(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), and setup_dahdi().
struct ast_channel inuse [static] |
Definition at line 317 of file chan_dahdi.c.
Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), pri_dchannel(), and update_call_counter().
const char* lbostr[] [static] |
Definition at line 161 of file chan_dahdi.c.
Definition at line 450 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), dahdi_ss7_error(), dahdi_ss7_message(), handle_ss7_block_cic(), handle_ss7_block_linkset(), handle_ss7_debug(), handle_ss7_show_linkset(), handle_ss7_unblock_cic(), handle_ss7_unblock_linkset(), load_module(), setup_dahdi(), ss7_resolve_linkset(), and unload_module().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 332 of file chan_dahdi.c.
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 354 of file chan_dahdi.c.
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 350 of file chan_dahdi.c.
Referenced by __unload_module(), dahdi_restart(), and restart_monitor().
int mwilevel = 512 [static] |
Definition at line 314 of file chan_dahdi.c.
char mwimonitornotify[PATH_MAX] = "" [static] |
Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled
Definition at line 302 of file chan_dahdi.c.
int mwisend_rpas = 0 [static] |
Definition at line 304 of file chan_dahdi.c.
| char* name |
Definition at line 2368 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 1473 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 359 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 312 of file chan_dahdi.c.
char parkinglot[AST_MAX_EXTENSION] = "" [static] |
Default parking lot for this channel
Definition at line 299 of file chan_dahdi.c.
Referenced by __find_callno(), ast_iax2_new(), build_peer(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), func_channel_write(), gtalk_load_config(), gtalk_new(), set_pvt_defaults(), sip_alloc(), sip_new(), sip_park(), skinny_new(), and store_config_core().
int pridebugfd = -1 [static] |
Definition at line 321 of file chan_dahdi.c.
ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 345 of file chan_dahdi.c.
Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_debug(), handle_pri_set_debug_file(), and handle_pri_show_debug().
char pridebugfilename[1024] = "" [static] |
Definition at line 322 of file chan_dahdi.c.
Definition at line 561 of file chan_dahdi.c.
Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().
char progzone[10] = "" [static] |
Definition at line 307 of file chan_dahdi.c.
ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 357 of file chan_dahdi.c.
Referenced by dahdi_restart().
int ringt_base = DEFAULT_RINGT [static] |
Configured ring timeout base.
Definition at line 414 of file chan_dahdi.c.
| struct dahdi_pvt* round_robin[32] |
Definition at line 1428 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 355 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 358 of file chan_dahdi.c.
ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 356 of file chan_dahdi.c.
Referenced by dahdi_restart(), and ss_thread().
char* subnames[] [static] |
{
"Real",
"Callwait",
"Threeway"
}
Definition at line 600 of file chan_dahdi.c.
const char tdesc[] [static] |
Definition at line 215 of file chan_dahdi.c.
int usedistinctiveringdetection = 0 [static] |
Definition at line 309 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 1474 of file chan_dahdi.c.
1.6.2