#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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/dahdi_compat.h"
#include "asterisk/tonezone_compat.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_pvt |
struct | dahdi_subchannel |
struct | distRingData |
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 | 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_EVENT_DTMFDOWN 0 |
#define | DAHDI_EVENT_DTMFUP 0 |
#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_RINGT ( (8000 * 8) / READ_SIZE) |
#define | END_SILENCE_LEN 400 |
#define | FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" |
#define | FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define | FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" |
#define | FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define | GET_CHANNEL(p) ((p)->channel) |
#define | HANGUP 1 |
#define | HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) |
#define | HEADER_MS 50 |
#define | ISTRUNK(p) |
#define | local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0) |
#define | local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr) |
#define | local_astman_register(a, b, c, d) |
#define | local_astman_unregister(a) |
#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 | READ_SIZE 160 |
#define | sig2str dahdi_sig2str |
#define | SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
#define | SIG_EM DAHDI_SIG_EM |
#define | SIG_EM_E1 DAHDI_SIG_EM_E1 |
#define | SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
#define | SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
#define | SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
#define | SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
#define | SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
#define | SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
#define | SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
#define | SIG_FXOGS DAHDI_SIG_FXOGS |
#define | SIG_FXOKS DAHDI_SIG_FXOKS |
#define | SIG_FXOLS DAHDI_SIG_FXOLS |
#define | SIG_FXSGS DAHDI_SIG_FXSGS |
#define | SIG_FXSKS DAHDI_SIG_FXSKS |
#define | SIG_FXSLS DAHDI_SIG_FXSLS |
#define | SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
#define | SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS) |
#define | SIG_PRI DAHDI_SIG_CLEAR |
#define | SIG_SF DAHDI_SIG_SF |
#define | SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
#define | SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
#define | SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
#define | SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
#define | SMDI_MD_WAIT_TIMEOUT 1500 |
#define | SUB_CALLWAIT 1 |
#define | SUB_REAL 0 |
#define | SUB_THREEWAY 2 |
#define | tdesc "DAHDI Telephony" |
#define | TRAILER_MS 5 |
#define | TRANSFER 0 |
Functions | |
static int | __action_dialoffhook (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_dnd (struct mansession *s, const struct message *m, int zap_mode, int dnd) |
static int | __action_restart (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_showchannels (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_transfer (struct mansession *s, const struct message *m, int zap_mode) |
static int | __action_transferhangup (struct mansession *s, const struct message *m, int zap_mode) |
static struct ast_frame * | __dahdi_exception (struct ast_channel *ast) |
static int | __unload_module (void) |
static char * | alarm2str (int alarm) |
static int | alloc_sub (struct dahdi_pvt *p, int x) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,.load=load_module,.unload=unload_module,.reload=reload,) | |
AST_MUTEX_DEFINE_STATIC (restart_lock) | |
AST_MUTEX_DEFINE_STATIC (ss_thread_lock) | |
AST_MUTEX_DEFINE_STATIC (monlock) | |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
AST_MUTEX_DEFINE_STATIC (iflock) | |
Protect the interface list (of dahdi_pvt's). | |
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 int | bump_gains (struct dahdi_pvt *p) |
static struct dahdi_pvt * | chandup (struct dahdi_pvt *src) |
static int | check_for_conference (struct dahdi_pvt *p) |
static int | conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel) |
static int | conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index) |
static int | dahdi_action_dialoffhook (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndoff (struct mansession *s, const struct message *m) |
static int | dahdi_action_dndon (struct mansession *s, const struct message *m) |
static int | dahdi_action_restart (struct mansession *s, const struct message *m) |
static int | dahdi_action_showchannels (struct mansession *s, const struct message *m) |
static int | dahdi_action_transfer (struct mansession *s, const struct message *m) |
static int | dahdi_action_transferhangup (struct mansession *s, const struct message *m) |
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_sub (struct dahdi_pvt *chan_pvt, int sub_num) |
static int | dahdi_confmute (struct dahdi_pvt *p, int muted) |
static int | dahdi_destroy_channel (int fd, int argc, char **argv) |
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_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, 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 index, 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 struct ast_channel * | dahdi_new (struct dahdi_pvt *, int, int, int, int, int) |
static int | dahdi_open (char *fn) |
static void | dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, void *pri) |
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 int | dahdi_restart_cmd (int fd, int argc, char **argv) |
static int | dahdi_ring_phone (struct dahdi_pvt *p) |
static int | dahdi_sendtext (struct ast_channel *c, const char *text) |
static int | dahdi_set_hook (int fd, int hs) |
static int | dahdi_setlinear (int dfd, int linear) |
static int | dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen) |
static int | dahdi_show_channel (int fd, int argc, char **argv) |
static int | dahdi_show_channels (int fd, int argc, char **argv) |
static int | dahdi_show_status (int fd, int argc, char *argv[]) |
static char * | dahdi_sig2str (int sig) |
static void | dahdi_softhangup_all (void) |
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 index) |
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 int | digit_to_dtmfindex (char digit) |
static void | disable_dtmf_detect (struct dahdi_pvt *p) |
static void * | do_monitor (void *data) |
static void | enable_dtmf_detect (struct dahdi_pvt *p) |
static char * | event2str (int event) |
static void | fill_rxgain (struct dahdi_gains *g, float gain, int law) |
static void | fill_txgain (struct dahdi_gains *g, float gain, int law) |
static struct dahdi_pvt * | find_channel (int channel) |
static int | get_alarms (struct dahdi_pvt *p) |
static void | handle_alarms (struct dahdi_pvt *p, int alarms) |
static int | handle_dahdi_show_cadences (int fd, int argc, char *argv[]) |
static int | handle_init_event (struct dahdi_pvt *i, int event) |
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 | load_module (void) |
static struct dahdi_pvt * | mkintf (int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading) |
static int | my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear) |
static int | my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms) |
static int | process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels) |
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 void * | ss_thread (void *data) |
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, void *pri) |
static int | zap_action_dialoffhook (struct mansession *s, const struct message *m) |
static int | zap_action_dndoff (struct mansession *s, const struct message *m) |
static int | zap_action_dndon (struct mansession *s, const struct message *m) |
static int | zap_action_restart (struct mansession *s, const struct message *m) |
static int | zap_action_showchannels (struct mansession *s, const struct message *m) |
static int | zap_action_transfer (struct mansession *s, const struct message *m) |
static int | zap_action_transferhangup (struct mansession *s, const struct message *m) |
Variables | |
struct { | |
int alarm | |
char * name | |
} | alarms [] |
static struct dahdi_ring_cadence | cadences [NUM_CADENCE_MAX] |
static struct ast_channel_tech * | chan_tech |
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 struct ast_cli_entry | cli_zap_destroy_channel_deprecated |
static struct ast_cli_entry | cli_zap_restart_deprecated |
static struct ast_cli_entry | cli_zap_show_cadences_deprecated |
static struct ast_cli_entry | cli_zap_show_channel_deprecated |
static struct ast_cli_entry | cli_zap_show_channels_deprecated |
static struct ast_cli_entry | cli_zap_show_status_deprecated |
static struct ast_cli_entry | dahdi_cli [] |
static char | dahdi_restart_usage [] |
static char | dahdi_show_cadences_usage [] |
static char | dahdi_show_status_usage [] |
static struct ast_channel_tech | dahdi_tech |
static struct ast_jb_conf | default_jbconf |
static char | defaultcic [64] = "" |
static char | defaultozz [64] = "" |
static char | destroy_channel_usage [] |
static int | distinctiveringaftercid = 0 |
static struct dahdi_distRings | drings |
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 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 int | num_cadence = 4 |
static int | num_restart_pending = 0 |
static int | numbufs = 4 |
static char | progzone [10] = "" |
static int | ringt_base = DEFAULT_RINGT |
dahdi_pvt * | round_robin [32] |
static char | show_channel_usage [] |
static char | show_channels_usage [] |
static ast_cond_t | ss_thread_complete |
static int | ss_thread_count = 0 |
static char * | subnames [] |
static const char | tdesc [] = "DAHDI Telephony Driver" |
static int | user_has_defined_cadences = 0 |
static struct ast_channel_tech | zap_tech |
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 151 of file chan_dahdi.c.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), send_cwcidspill(), and ss_thread().
#define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) |
#define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) |
300 ms
Definition at line 282 of file chan_dahdi.c.
#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 |
Definition at line 191 of file chan_dahdi.c.
Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), and mkintf().
#define CHANNEL_PSEUDO -12 |
Definition at line 149 of file chan_dahdi.c.
#define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) |
#define CONF_USER_REAL (1 << 0) |
Definition at line 409 of file chan_dahdi.c.
#define CONF_USER_THIRDCALL (1 << 1) |
Definition at line 410 of file chan_dahdi.c.
#define DAHDI_EVENT_DTMFDOWN 0 |
#define DAHDI_EVENT_DTMFUP 0 |
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP) |
Definition at line 197 of file chan_dahdi.c.
#define DCHAN_NOTINALARM (1 << 1) |
Definition at line 194 of file chan_dahdi.c.
#define DCHAN_PROVISIONED (1 << 0) |
Definition at line 193 of file chan_dahdi.c.
#define DCHAN_UP (1 << 2) |
Definition at line 195 of file chan_dahdi.c.
#define DEFAULT_CIDRINGS 1 |
Typically, how many rings before we should send Caller*ID.
Definition at line 147 of file chan_dahdi.c.
Referenced by dahdi_chan_conf_default().
#define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) |
8,000 ms
Definition at line 286 of file chan_dahdi.c.
#define END_SILENCE_LEN 400 |
Referenced by dahdi_sendtext().
#define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" |
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" |
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" |
#define GET_CHANNEL | ( | p | ) | ((p)->channel) |
Definition at line 751 of file chan_dahdi.c.
#define HANGUP 1 |
Definition at line 10584 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 | ) |
Value:
Definition at line 796 of file chan_dahdi.c.
Referenced by dahdi_indicate(), dahdi_show_channel(), and ss_thread().
#define local_astman_ack | ( | s, | |||
m, | |||||
msg, | |||||
zap | ) | do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0) |
Definition at line 10614 of file chan_dahdi.c.
Referenced by __action_dialoffhook(), __action_dnd(), __action_restart(), __action_showchannels(), __action_transfer(), and __action_transferhangup().
#define local_astman_header | ( | m, | |||
hdr, | |||||
zap | ) | astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr) |
Definition at line 10615 of file chan_dahdi.c.
Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().
#define local_astman_register | ( | a, | |||
b, | |||||
c, | |||||
d | ) |
#define local_astman_unregister | ( | a | ) |
#define MASK_AVAIL (1 << 0) |
Channel available for PRI use
Definition at line 279 of file chan_dahdi.c.
#define MASK_INUSE (1 << 1) |
Channel currently in use
Definition at line 280 of file chan_dahdi.c.
#define MAX_CHANLIST_LEN 80 |
The length of the parameters list of 'dahdichan'.
Definition at line 11002 of file chan_dahdi.c.
Referenced by process_dahdi().
#define MAX_CHANNELS 672 |
No more than a DS3 per trunk group
Definition at line 189 of file chan_dahdi.c.
Referenced by mkintf().
#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.
Definition at line 154 of file chan_dahdi.c.
Referenced by dahdi_new(), and ss_thread().
#define NUM_CADENCE_MAX 25 |
Definition at line 774 of file chan_dahdi.c.
#define NUM_DCHANS 4 |
No more than 4 d-channels
Definition at line 188 of file chan_dahdi.c.
#define NUM_SPANS 32 |
Definition at line 187 of file chan_dahdi.c.
#define POLARITY_IDLE 0 |
Definition at line 367 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().
#define POLARITY_REV 1 |
Definition at line 368 of file chan_dahdi.c.
Referenced by dahdi_handle_event(), and handle_init_event().
#define READ_SIZE 160 |
Chunk size to read -- we use 20ms chunks to make things happy.
Definition at line 277 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 1278 of file chan_dahdi.c.
Referenced by __action_showchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().
#define SIG_E911 (0x1000000 | DAHDI_SIG_EM) |
Definition at line 167 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM DAHDI_SIG_EM |
Definition at line 162 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EM_E1 DAHDI_SIG_EM_E1 |
Definition at line 183 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM) |
Definition at line 163 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATB (0x0800000 | DAHDI_SIG_EM) |
Definition at line 166 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATD (0x0200000 | DAHDI_SIG_EM) |
Definition at line 164 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM) |
Definition at line 165 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM) |
Definition at line 168 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM) |
Definition at line 169 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM) |
Definition at line 170 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOGS DAHDI_SIG_FXOGS |
Definition at line 175 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXOKS DAHDI_SIG_FXOKS |
Definition at line 176 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 174 of file chan_dahdi.c.
Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_FXSGS DAHDI_SIG_FXSGS |
Definition at line 172 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 173 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(), process_dahdi(), and ss_thread().
#define SIG_FXSLS DAHDI_SIG_FXSLS |
Definition at line 171 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_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS) |
Definition at line 184 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 185 of file chan_dahdi.c.
Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().
#define SIG_PRI DAHDI_SIG_CLEAR |
Definition at line 177 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_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().
#define SIG_SF DAHDI_SIG_SF |
Definition at line 178 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF) |
Definition at line 182 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF) |
Definition at line 180 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF) |
Definition at line 181 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().
#define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF) |
Definition at line 179 of file chan_dahdi.c.
Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().
#define SMDI_MD_WAIT_TIMEOUT 1500 |
#define SUB_CALLWAIT 1 |
Call-Waiting call on hold
Definition at line 363 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(), features_hangup(), and ss_thread().
#define SUB_REAL 0 |
Active call
Definition at line 362 of file chan_dahdi.c.
Referenced by __dahdi_exception(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_setoption(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mkintf(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), and ss_thread().
#define SUB_THREEWAY 2 |
Three-way call
Definition at line 364 of file chan_dahdi.c.
Referenced by attempt_transfer(), available(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), features_hangup(), and ss_thread().
#define tdesc "DAHDI Telephony" |
Definition at line 12041 of file chan_dahdi.c.
#define TRAILER_MS 5 |
Referenced by dahdi_sendtext().
#define TRANSFER 0 |
Definition at line 10583 of file chan_dahdi.c.
Referenced by __action_transfer(), and dahdi_fake_event().
static int __action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10713 of file chan_dahdi.c.
References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_error(), dahdi_queue_frame(), f, find_channel(), local_astman_ack, local_astman_header, dahdi_pvt::owner, and s.
Referenced by dahdi_action_dialoffhook(), and zap_action_dialoffhook().
10714 { 10715 struct dahdi_pvt *p = NULL; 10716 const char *channel = local_astman_header(m, "Channel", zap_mode); 10717 const char *number = astman_get_header(m, "Number"); 10718 int i; 10719 10720 if (ast_strlen_zero(channel)) { 10721 astman_send_error(s, m, "No channel specified"); 10722 return 0; 10723 } 10724 if (ast_strlen_zero(number)) { 10725 astman_send_error(s, m, "No number specified"); 10726 return 0; 10727 } 10728 if (!(p = find_channel(atoi(channel)))) { 10729 astman_send_error(s, m, "No such channel"); 10730 return 0; 10731 } 10732 if (!p->owner) { 10733 astman_send_error(s, m, "Channel does not have an owner"); 10734 return 0; 10735 } 10736 for (i = 0; i < strlen(number); i++) { 10737 struct ast_frame f = { AST_FRAME_DTMF, number[i] }; 10738 10739 dahdi_queue_frame(p, &f, NULL); 10740 } 10741 local_astman_ack(s, m, "DialOffHook", zap_mode); 10742 10743 return 0; 10744 }
static int __action_dnd | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode, | |||
int | dnd | |||
) | [static] |
Definition at line 10617 of file chan_dahdi.c.
References ast_strlen_zero(), astman_send_error(), dahdi_pvt::dnd, find_channel(), local_astman_ack, local_astman_header, and s.
Referenced by dahdi_action_dndoff(), dahdi_action_dndon(), zap_action_dndoff(), and zap_action_dndon().
10618 { 10619 struct dahdi_pvt *p = NULL; 10620 const char *channel = local_astman_header(m, "Channel", zap_mode); 10621 10622 if (ast_strlen_zero(channel)) { 10623 astman_send_error(s, m, "No channel specified"); 10624 return 0; 10625 } 10626 if (!(p = find_channel(atoi(channel)))) { 10627 astman_send_error(s, m, "No such channel"); 10628 return 0; 10629 } 10630 p->dnd = dnd; 10631 local_astman_ack(s, m, "DND", zap_mode); 10632 10633 return 0; 10634 }
static int __action_restart | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10811 of file chan_dahdi.c.
References astman_send_error(), dahdi_restart(), local_astman_ack, and s.
Referenced by dahdi_action_restart(), and zap_action_restart().
10812 { 10813 if (dahdi_restart() != 0) { 10814 if (zap_mode) { 10815 astman_send_error(s, m, "Failed to restart Zap"); 10816 } else { 10817 astman_send_error(s, m, "Failed to restart DAHDI"); 10818 } 10819 return 1; 10820 } 10821 local_astman_ack(s, m, "Restart: Success", zap_mode); 10822 return 0; 10823 }
static int __action_showchannels | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10756 of file chan_dahdi.c.
References alarm, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_chan_name, dahdi_pvt::dnd, get_alarms(), iflist, local_astman_ack, dahdi_pvt::next, s, dahdi_pvt::sig, and sig2str.
Referenced by dahdi_action_showchannels(), and zap_action_showchannels().
10757 { 10758 struct dahdi_pvt *tmp = NULL; 10759 const char *id = astman_get_header(m, "ActionID"); 10760 char idText[256] = ""; 10761 10762 local_astman_ack(s, m, " channel status will follow", zap_mode); 10763 if (!ast_strlen_zero(id)) 10764 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id); 10765 10766 ast_mutex_lock(&iflock); 10767 10768 tmp = iflist; 10769 while (tmp) { 10770 if (tmp->channel > 0) { 10771 int alarm = get_alarms(tmp); 10772 astman_append(s, 10773 "Event: %sShowChannels\r\n" 10774 "Channel: %d\r\n" 10775 "Signalling: %s\r\n" 10776 "Context: %s\r\n" 10777 "DND: %s\r\n" 10778 "Alarm: %s\r\n" 10779 "%s" 10780 "\r\n", 10781 dahdi_chan_name, 10782 tmp->channel, sig2str(tmp->sig), tmp->context, 10783 tmp->dnd ? "Enabled" : "Disabled", 10784 alarm2str(alarm), idText); 10785 } 10786 10787 tmp = tmp->next; 10788 } 10789 10790 ast_mutex_unlock(&iflock); 10791 10792 astman_append(s, 10793 "Event: %sShowChannelsComplete\r\n" 10794 "%s" 10795 "\r\n", 10796 dahdi_chan_name, 10797 idText); 10798 return 0; 10799 }
static int __action_transfer | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10656 of file chan_dahdi.c.
References ast_strlen_zero(), astman_send_error(), dahdi_fake_event(), find_channel(), local_astman_ack, local_astman_header, s, and TRANSFER.
Referenced by dahdi_action_transfer(), and zap_action_transfer().
10657 { 10658 struct dahdi_pvt *p = NULL; 10659 const char *channel = local_astman_header(m, "Channel", zap_mode); 10660 10661 if (ast_strlen_zero(channel)) { 10662 astman_send_error(s, m, "No channel specified"); 10663 return 0; 10664 } 10665 if (!(p = find_channel(atoi(channel)))) { 10666 astman_send_error(s, m, "No such channel"); 10667 return 0; 10668 } 10669 dahdi_fake_event(p,TRANSFER); 10670 local_astman_ack(s, m, "Transfer", zap_mode); 10671 10672 return 0; 10673 }
static int __action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | zap_mode | |||
) | [static] |
Definition at line 10685 of file chan_dahdi.c.
References ast_strlen_zero(), astman_send_error(), dahdi_fake_event(), find_channel(), HANGUP, local_astman_ack, local_astman_header, and s.
Referenced by dahdi_action_transferhangup(), and zap_action_transferhangup().
10686 { 10687 struct dahdi_pvt *p = NULL; 10688 const char *channel = local_astman_header(m, "Channel", zap_mode); 10689 10690 if (ast_strlen_zero(channel)) { 10691 astman_send_error(s, m, "No channel specified"); 10692 return 0; 10693 } 10694 if (!(p = find_channel(atoi(channel)))) { 10695 astman_send_error(s, m, "No such channel"); 10696 return 0; 10697 } 10698 dahdi_fake_event(p, HANGUP); 10699 local_astman_ack(s, m, "Hangup", zap_mode); 10700 return 0; 10701 }
static struct ast_frame* __dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4639 of file chan_dahdi.c.
References ast_bridged_channel(), AST_CONTROL_UNHOLD, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_verbose(), dahdi_pvt::channel, 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, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, update_conf(), and VERBOSE_PREFIX_3.
Referenced by dahdi_exception(), and dahdi_read().
04640 { 04641 struct dahdi_pvt *p = ast->tech_pvt; 04642 int res; 04643 int usedindex=-1; 04644 int index; 04645 struct ast_frame *f; 04646 04647 04648 index = dahdi_get_index(ast, p, 1); 04649 04650 p->subs[index].f.frametype = AST_FRAME_NULL; 04651 p->subs[index].f.datalen = 0; 04652 p->subs[index].f.samples = 0; 04653 p->subs[index].f.mallocd = 0; 04654 p->subs[index].f.offset = 0; 04655 p->subs[index].f.subclass = 0; 04656 p->subs[index].f.delivery = ast_tv(0,0); 04657 p->subs[index].f.src = "dahdi_exception"; 04658 p->subs[index].f.data = NULL; 04659 04660 04661 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) { 04662 /* If nobody owns us, absorb the event appropriately, otherwise 04663 we loop indefinitely. This occurs when, during call waiting, the 04664 other end hangs up our channel so that it no longer exists, but we 04665 have neither FLASH'd nor ONHOOK'd to signify our desire to 04666 change to the other channel. */ 04667 if (p->fake_event) { 04668 res = p->fake_event; 04669 p->fake_event = 0; 04670 } else 04671 res = dahdi_get_event(p->subs[SUB_REAL].dfd); 04672 /* Switch to real if there is one and this isn't something really silly... */ 04673 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) && 04674 (res != DAHDI_EVENT_HOOKCOMPLETE)) { 04675 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res); 04676 p->owner = p->subs[SUB_REAL].owner; 04677 if (p->owner && ast_bridged_channel(p->owner)) 04678 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04679 p->subs[SUB_REAL].needunhold = 1; 04680 } 04681 switch (res) { 04682 case DAHDI_EVENT_ONHOOK: 04683 dahdi_disable_ec(p); 04684 if (p->owner) { 04685 if (option_verbose > 2) 04686 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name); 04687 dahdi_ring_phone(p); 04688 p->callwaitingrepeat = 0; 04689 p->cidcwexpire = 0; 04690 } else 04691 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 04692 update_conf(p); 04693 break; 04694 case DAHDI_EVENT_RINGOFFHOOK: 04695 dahdi_enable_ec(p); 04696 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 04697 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) { 04698 p->subs[SUB_REAL].needanswer = 1; 04699 p->dialing = 0; 04700 } 04701 break; 04702 case DAHDI_EVENT_HOOKCOMPLETE: 04703 case DAHDI_EVENT_RINGERON: 04704 case DAHDI_EVENT_RINGEROFF: 04705 /* Do nothing */ 04706 break; 04707 case DAHDI_EVENT_WINKFLASH: 04708 gettimeofday(&p->flashtime, NULL); 04709 if (p->owner) { 04710 if (option_verbose > 2) 04711 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name); 04712 if (p->owner->_state != AST_STATE_UP) { 04713 /* Answer if necessary */ 04714 usedindex = dahdi_get_index(p->owner, p, 0); 04715 if (usedindex > -1) { 04716 p->subs[usedindex].needanswer = 1; 04717 } 04718 ast_setstate(p->owner, AST_STATE_UP); 04719 } 04720 p->callwaitingrepeat = 0; 04721 p->cidcwexpire = 0; 04722 if (ast_bridged_channel(p->owner)) 04723 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04724 p->subs[SUB_REAL].needunhold = 1; 04725 } else 04726 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); 04727 update_conf(p); 04728 break; 04729 default: 04730 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res)); 04731 } 04732 f = &p->subs[index].f; 04733 return f; 04734 } 04735 if (!(p->radio || (p->oprmode < 0)) && option_debug) 04736 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel); 04737 /* If it's not us, return NULL immediately */ 04738 if (ast != p->owner) { 04739 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name); 04740 f = &p->subs[index].f; 04741 return f; 04742 } 04743 f = dahdi_handle_event(ast); 04744 return f; 04745 }
static int __unload_module | ( | void | ) | [static] |
Definition at line 10842 of file chan_dahdi.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, destroy_all_channels(), iflist, local_astman_unregister, master, dahdi_pvt::next, and dahdi_pvt::owner.
Referenced by load_module(), and unload_module().
10843 { 10844 struct dahdi_pvt *p; 10845 10846 #ifdef HAVE_PRI 10847 int i, j; 10848 for (i = 0; i < NUM_SPANS; i++) { 10849 if (pris[i].master != AST_PTHREADT_NULL) 10850 pthread_cancel(pris[i].master); 10851 } 10852 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 10853 10854 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 10855 ast_unregister_application(dahdi_send_keypad_facility_app); 10856 } 10857 ast_unregister_application(zap_send_keypad_facility_app); 10858 #endif 10859 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 10860 local_astman_unregister("DialOffHook"); 10861 local_astman_unregister("Hangup"); 10862 local_astman_unregister("Transfer"); 10863 local_astman_unregister("DNDoff"); 10864 local_astman_unregister("DNDon"); 10865 local_astman_unregister("ShowChannels"); 10866 local_astman_unregister("Restart"); 10867 ast_channel_unregister(chan_tech); 10868 ast_mutex_lock(&iflock); 10869 /* Hangup all interfaces if they have an owner */ 10870 p = iflist; 10871 while (p) { 10872 if (p->owner) 10873 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 10874 p = p->next; 10875 } 10876 ast_mutex_unlock(&iflock); 10877 ast_mutex_lock(&monlock); 10878 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 10879 pthread_cancel(monitor_thread); 10880 pthread_kill(monitor_thread, SIGURG); 10881 pthread_join(monitor_thread, NULL); 10882 } 10883 monitor_thread = AST_PTHREADT_STOP; 10884 ast_mutex_unlock(&monlock); 10885 10886 destroy_all_channels(); 10887 #ifdef HAVE_PRI 10888 for (i = 0; i < NUM_SPANS; i++) { 10889 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) 10890 pthread_join(pris[i].master, NULL); 10891 for (j = 0; j < NUM_DCHANS; j++) { 10892 dahdi_close_pri_fd(&(pris[i]), j); 10893 } 10894 } 10895 #endif 10896 ast_cond_destroy(&ss_thread_complete); 10897 return 0; 10898 }
static char* alarm2str | ( | int | alarm | ) | [static] |
Definition at line 1189 of file chan_dahdi.c.
Referenced by __action_showchannels(), and handle_alarms().
01190 { 01191 int x; 01192 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) { 01193 if (alarms[x].alarm & alarm) 01194 return alarms[x].name; 01195 } 01196 return alarm ? "Unknown Alarm" : "No Alarm"; 01197 }
static int alloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 987 of file chan_dahdi.c.
References 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_DEBUG, LOG_WARNING, option_debug, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().
00988 { 00989 struct dahdi_bufferinfo bi; 00990 int res; 00991 if (p->subs[x].dfd < 0) { 00992 #ifdef HAVE_ZAPTEL 00993 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo"); 00994 #else 00995 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo"); 00996 #endif 00997 if (p->subs[x].dfd > -1) { 00998 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi); 00999 if (!res) { 01000 bi.txbufpolicy = p->buf_policy; 01001 bi.rxbufpolicy = p->buf_policy; 01002 bi.numbufs = p->buf_no; 01003 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi); 01004 if (res < 0) { 01005 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno)); 01006 } 01007 } else 01008 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno)); 01009 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) { 01010 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno)); 01011 dahdi_close_sub(p, x); 01012 return -1; 01013 } 01014 if (option_debug) 01015 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan); 01016 return 0; 01017 } else 01018 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 01019 return -1; 01020 } 01021 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel); 01022 return -1; 01023 }
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
tdesc | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
AST_MUTEX_DEFINE_STATIC | ( | restart_lock | ) |
AST_MUTEX_DEFINE_STATIC | ( | ss_thread_lock | ) |
AST_MUTEX_DEFINE_STATIC | ( | monlock | ) |
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
AST_MUTEX_DEFINE_STATIC | ( | iflock | ) |
Protect the interface list (of dahdi_pvt's).
static int attempt_transfer | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3601 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_indicate(), ast_log(), ast_mutex_unlock(), ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, ast_channel::lock, LOG_DEBUG, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().
Referenced by dahdi_handle_event(), handle_onhook_message(), handle_request(), handle_soft_key_event_message(), and local_attended_transfer().
03602 { 03603 /* In order to transfer, we need at least one of the channels to 03604 actually be in a call bridge. We can't conference two applications 03605 together (but then, why would we want to?) */ 03606 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 03607 /* The three-way person we're about to transfer to could still be in MOH, so 03608 stop if now if appropriate */ 03609 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) 03610 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); 03611 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) { 03612 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING); 03613 } 03614 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) { 03615 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 03616 } 03617 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) { 03618 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03619 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name); 03620 return -1; 03621 } 03622 /* Orphan the channel after releasing the lock */ 03623 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 03624 unalloc_sub(p, SUB_THREEWAY); 03625 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 03626 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 03627 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) { 03628 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING); 03629 } 03630 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) { 03631 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 03632 } 03633 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) { 03634 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n", 03635 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name); 03636 return -1; 03637 } 03638 /* Three-way is now the REAL */ 03639 swap_subs(p, SUB_THREEWAY, SUB_REAL); 03640 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock); 03641 unalloc_sub(p, SUB_THREEWAY); 03642 /* Tell the caller not to hangup */ 03643 return 1; 03644 } else { 03645 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n", 03646 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name); 03647 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 03648 return -1; 03649 } 03650 return 0; 03651 }
static int available | ( | struct dahdi_pvt * | p, | |
int | channelmatch, | |||
ast_group_t | groupmatch, | |||
int * | busy, | |||
int * | channelmatched, | |||
int * | groupmatched | |||
) | [inline, static] |
Definition at line 7792 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::callwaiting, dahdi_pvt::channel, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, LOG_DEBUG, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.
Referenced by dahdi_request().
07793 { 07794 int res; 07795 struct dahdi_params par; 07796 07797 /* First, check group matching */ 07798 if (groupmatch) { 07799 if ((p->group & groupmatch) != groupmatch) 07800 return 0; 07801 *groupmatched = 1; 07802 } 07803 /* Check to see if we have a channel match */ 07804 if (channelmatch != -1) { 07805 if (p->channel != channelmatch) 07806 return 0; 07807 *channelmatched = 1; 07808 } 07809 /* We're at least busy at this point */ 07810 if (busy) { 07811 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) 07812 *busy = 1; 07813 } 07814 /* If do not disturb, definitely not */ 07815 if (p->dnd) 07816 return 0; 07817 /* If guard time, definitely not */ 07818 if (p->guardtime && (time(NULL) < p->guardtime)) 07819 return 0; 07820 07821 /* If no owner definitely available */ 07822 if (!p->owner) { 07823 #ifdef HAVE_PRI 07824 /* Trust PRI */ 07825 if (p->pri) { 07826 if (p->resetting || p->call) 07827 return 0; 07828 else 07829 return 1; 07830 } 07831 #endif 07832 if (!(p->radio || (p->oprmode < 0))) 07833 { 07834 if (!p->sig || (p->sig == SIG_FXSLS)) 07835 return 1; 07836 /* Check hook state */ 07837 if (p->subs[SUB_REAL].dfd > -1) 07838 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 07839 else { 07840 /* Assume not off hook on CVRS */ 07841 res = 0; 07842 par.rxisoffhook = 0; 07843 } 07844 if (res) { 07845 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno)); 07846 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) { 07847 /* When "onhook" that means no battery on the line, and thus 07848 it is out of service..., if it's on a TDM card... If it's a channel 07849 bank, there is no telling... */ 07850 if (par.rxbits > -1) 07851 return 1; 07852 if (par.rxisoffhook) 07853 return 1; 07854 else 07855 #ifdef DAHDI_CHECK_HOOKSTATE 07856 return 0; 07857 #else 07858 return 1; 07859 #endif 07860 } else if (par.rxisoffhook) { 07861 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel); 07862 /* Not available when the other end is off hook */ 07863 return 0; 07864 } 07865 } 07866 return 1; 07867 } 07868 07869 /* If it's not an FXO, forget about call wait */ 07870 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 07871 return 0; 07872 07873 if (!p->callwaiting) { 07874 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */ 07875 return 0; 07876 } 07877 07878 if (p->subs[SUB_CALLWAIT].dfd > -1) { 07879 /* If there is already a call waiting call, then we can't take a second one */ 07880 return 0; 07881 } 07882 07883 if ((p->owner->_state != AST_STATE_UP) && 07884 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) { 07885 /* If the current call is not up, then don't allow the call */ 07886 return 0; 07887 } 07888 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) { 07889 /* Can't take a call wait when the three way calling hasn't been merged yet. */ 07890 return 0; 07891 } 07892 /* We're cool */ 07893 return 1; 07894 }
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 10910 of file chan_dahdi.c.
References ast_log(), ast_strdupa, ast_verbose(), dahdi_chan_conf::chan, CHAN_PSEUDO, HAVE_PRI, LOG_ERROR, mkintf(), option_verbose, dahdi_pvt::sig, sig2str, strsep(), and VERBOSE_PREFIX_3.
Referenced by process_dahdi().
10911 { 10912 char *c, *chan; 10913 int x, start, finish; 10914 struct dahdi_pvt *tmp; 10915 #ifdef HAVE_PRI 10916 struct dahdi_pri *pri; 10917 int trunkgroup, y; 10918 #endif 10919 10920 if ((reload == 0) && (conf->chan.sig < 0)) { 10921 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n"); 10922 return -1; 10923 } 10924 10925 c = ast_strdupa(value); 10926 10927 #ifdef HAVE_PRI 10928 pri = NULL; 10929 if (iscrv) { 10930 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) { 10931 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno); 10932 return -1; 10933 } 10934 if (trunkgroup < 1) { 10935 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno); 10936 return -1; 10937 } 10938 c += y; 10939 for (y = 0; y < NUM_SPANS; y++) { 10940 if (pris[y].trunkgroup == trunkgroup) { 10941 pri = pris + y; 10942 break; 10943 } 10944 } 10945 if (!pri) { 10946 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno); 10947 return -1; 10948 } 10949 } 10950 #endif 10951 10952 while ((chan = strsep(&c, ","))) { 10953 if (sscanf(chan, "%d-%d", &start, &finish) == 2) { 10954 /* Range */ 10955 } else if (sscanf(chan, "%d", &start)) { 10956 /* Just one */ 10957 finish = start; 10958 } else if (!strcasecmp(chan, "pseudo")) { 10959 finish = start = CHAN_PSEUDO; 10960 if (found_pseudo) 10961 *found_pseudo = 1; 10962 } else { 10963 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan); 10964 return -1; 10965 } 10966 if (finish < start) { 10967 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish); 10968 x = finish; 10969 finish = start; 10970 start = x; 10971 } 10972 10973 for (x = start; x <= finish; x++) { 10974 #ifdef HAVE_PRI 10975 tmp = mkintf(x, conf, pri, reload); 10976 #else 10977 tmp = mkintf(x, conf, NULL, reload); 10978 #endif 10979 10980 if (tmp) { 10981 if (option_verbose > 2) { 10982 #ifdef HAVE_PRI 10983 if (pri) 10984 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig)); 10985 else 10986 #endif 10987 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig)); 10988 } 10989 } else { 10990 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n", 10991 (reload == 1) ? "reconfigure" : "register", value); 10992 return -1; 10993 } 10994 } 10995 } 10996 10997 return 0; 10998 }
static int bump_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1640 of file chan_dahdi.c.
References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.
Referenced by ss_thread().
01641 { 01642 int res; 01643 01644 /* Bump receive gain by 5.0db */ 01645 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law); 01646 if (res) { 01647 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno)); 01648 return -1; 01649 } 01650 01651 return 0; 01652 }
Definition at line 7896 of file chan_dahdi.c.
References ast_log(), ast_malloc, ast_mutex_init(), dahdi_open(), destroy_dahdi_pvt(), errno, iflist, LOG_ERROR, dahdi_pvt::next, dahdi_pvt::prev, and SUB_REAL.
Referenced by dahdi_request().
07897 { 07898 struct dahdi_pvt *p; 07899 struct dahdi_bufferinfo bi; 07900 int res; 07901 07902 if ((p = ast_malloc(sizeof(*p)))) { 07903 memcpy(p, src, sizeof(struct dahdi_pvt)); 07904 ast_mutex_init(&p->lock); 07905 #ifdef HAVE_ZAPTEL 07906 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo"); 07907 #else 07908 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo"); 07909 #endif 07910 /* Allocate a DAHDI structure */ 07911 if (p->subs[SUB_REAL].dfd < 0) { 07912 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno)); 07913 destroy_dahdi_pvt(&p); 07914 return NULL; 07915 } 07916 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 07917 if (!res) { 07918 bi.txbufpolicy = p->buf_policy; 07919 bi.rxbufpolicy = p->buf_policy; 07920 bi.numbufs = p->buf_no; 07921 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 07922 if (res < 0) { 07923 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno)); 07924 } 07925 } else 07926 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno)); 07927 } 07928 p->destroy = 1; 07929 p->next = iflist; 07930 p->prev = NULL; 07931 iflist = p; 07932 if (iflist->next) 07933 iflist->next->prev = p; 07934 return p; 07935 }
static int check_for_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3653 of file chan_dahdi.c.
References ast_log(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, option_verbose, SUB_REAL, dahdi_pvt::subs, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event().
03654 { 03655 struct dahdi_confinfo ci; 03656 /* Fine if we already have a master, etc */ 03657 if (p->master || (p->confno > -1)) 03658 return 0; 03659 memset(&ci, 0, sizeof(ci)); 03660 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 03661 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno)); 03662 return 0; 03663 } 03664 /* If we have no master and don't have a confno, then 03665 if we're in a conference, it's probably a MeetMe room or 03666 some such, so don't let us 3-way out! */ 03667 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) { 03668 if (option_verbose > 2) 03669 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n"); 03670 return 1; 03671 } 03672 return 0; 03673 }
static int conf_add | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index, | |||
int | slavechannel | |||
) | [static] |
Definition at line 1280 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_DEBUG, and LOG_WARNING.
Referenced by update_conf().
01281 { 01282 /* If the conference already exists, and we're already in it 01283 don't bother doing anything */ 01284 struct dahdi_confinfo zi; 01285 01286 memset(&zi, 0, sizeof(zi)); 01287 zi.chan = 0; 01288 01289 if (slavechannel > 0) { 01290 /* If we have only one slave, do a digital mon */ 01291 zi.confmode = DAHDI_CONF_DIGITALMON; 01292 zi.confno = slavechannel; 01293 } else { 01294 if (!index) { 01295 /* Real-side and pseudo-side both participate in conference */ 01296 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER | 01297 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER; 01298 } else 01299 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER; 01300 zi.confno = p->confno; 01301 } 01302 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode)) 01303 return 0; 01304 if (c->dfd < 0) 01305 return 0; 01306 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01307 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno)); 01308 return -1; 01309 } 01310 if (slavechannel < 1) { 01311 p->confno = zi.confno; 01312 } 01313 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01314 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01315 return 0; 01316 }
static int conf_del | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c, | |||
int | index | |||
) | [static] |
Definition at line 1329 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), LOG_DEBUG, and LOG_WARNING.
Referenced by dahdi_unlink(), and update_conf().
01330 { 01331 struct dahdi_confinfo zi; 01332 if (/* Can't delete if there's no dfd */ 01333 (c->dfd < 0) || 01334 /* Don't delete from the conference if it's not our conference */ 01335 !isourconf(p, c) 01336 /* Don't delete if we don't think it's conferenced at all (implied) */ 01337 ) return 0; 01338 memset(&zi, 0, sizeof(zi)); 01339 zi.chan = 0; 01340 zi.confno = 0; 01341 zi.confmode = 0; 01342 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) { 01343 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno)); 01344 return -1; 01345 } 01346 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno); 01347 memcpy(&c->curconf, &zi, sizeof(c->curconf)); 01348 return 0; 01349 }
static int dahdi_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10751 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
10752 { 10753 return __action_dialoffhook(s, m, 0); 10754 }
static int dahdi_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10651 of file chan_dahdi.c.
References __action_dnd(), and s.
10652 { 10653 return __action_dnd(s, m, 0, 0); 10654 }
static int dahdi_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10641 of file chan_dahdi.c.
References __action_dnd(), and s.
10642 { 10643 return __action_dnd(s, m, 0, 1); 10644 }
static int dahdi_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10830 of file chan_dahdi.c.
References __action_restart(), and s.
10831 { 10832 return __action_restart(s, m, 0); 10833 }
static int dahdi_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10806 of file chan_dahdi.c.
References __action_showchannels(), and s.
10807 { 10808 return __action_showchannels(s, m, 0); 10809 }
static int dahdi_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10680 of file chan_dahdi.c.
References __action_transfer(), and s.
10681 { 10682 return __action_transfer(s, m, 0); 10683 }
static int dahdi_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10708 of file chan_dahdi.c.
References __action_transferhangup(), and s.
10709 { 10710 return __action_transferhangup(s, m, 0); 10711 }
static int dahdi_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2847 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, 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_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, 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::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.
02848 { 02849 struct dahdi_pvt *p = ast->tech_pvt; 02850 int res = 0; 02851 int index; 02852 int oldstate = ast->_state; 02853 ast_setstate(ast, AST_STATE_UP); 02854 ast_mutex_lock(&p->lock); 02855 index = dahdi_get_index(ast, p, 0); 02856 if (index < 0) 02857 index = SUB_REAL; 02858 /* nothing to do if a radio channel */ 02859 if ((p->radio || (p->oprmode < 0))) { 02860 ast_mutex_unlock(&p->lock); 02861 return 0; 02862 } 02863 switch (p->sig) { 02864 case SIG_FXSLS: 02865 case SIG_FXSGS: 02866 case SIG_FXSKS: 02867 p->ringt = 0; 02868 /* Fall through */ 02869 case SIG_EM: 02870 case SIG_EM_E1: 02871 case SIG_EMWINK: 02872 case SIG_FEATD: 02873 case SIG_FEATDMF: 02874 case SIG_FEATDMF_TA: 02875 case SIG_E911: 02876 case SIG_FGC_CAMA: 02877 case SIG_FGC_CAMAMF: 02878 case SIG_FEATB: 02879 case SIG_SF: 02880 case SIG_SFWINK: 02881 case SIG_SF_FEATD: 02882 case SIG_SF_FEATDMF: 02883 case SIG_SF_FEATB: 02884 case SIG_FXOLS: 02885 case SIG_FXOGS: 02886 case SIG_FXOKS: 02887 /* Pick up the line */ 02888 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name); 02889 if (p->hanguponpolarityswitch) { 02890 gettimeofday(&p->polaritydelaytv, NULL); 02891 } 02892 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 02893 tone_zone_play_tone(p->subs[index].dfd, -1); 02894 p->dialing = 0; 02895 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) { 02896 if (oldstate == AST_STATE_RINGING) { 02897 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n"); 02898 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1); 02899 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02900 p->owner = p->subs[SUB_REAL].owner; 02901 } 02902 } 02903 if (p->sig & __DAHDI_SIG_FXS) { 02904 dahdi_enable_ec(p); 02905 dahdi_train_ec(p); 02906 } 02907 break; 02908 #ifdef HAVE_PRI 02909 case SIG_PRI: 02910 /* Send a pri acknowledge */ 02911 if (!pri_grab(p, p->pri)) { 02912 p->proceeding = 1; 02913 res = pri_answer(p->pri->pri, p->call, 0, !p->digital); 02914 pri_rel(p->pri); 02915 } else { 02916 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 02917 res = -1; 02918 } 02919 break; 02920 #endif 02921 case 0: 02922 ast_mutex_unlock(&p->lock); 02923 return 0; 02924 default: 02925 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel); 02926 res = -1; 02927 } 02928 ast_mutex_unlock(&p->lock); 02929 return res; 02930 }
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 3254 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_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_subchannel::inthreeway, dahdi_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, master, option_verbose, 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, update_conf(), and VERBOSE_PREFIX_3.
03255 { 03256 struct ast_channel *who; 03257 struct dahdi_pvt *p0, *p1, *op0, *op1; 03258 struct dahdi_pvt *master = NULL, *slave = NULL; 03259 struct ast_frame *f; 03260 int inconf = 0; 03261 int nothingok = 1; 03262 int ofd0, ofd1; 03263 int oi0, oi1, i0 = -1, i1 = -1, t0, t1; 03264 int os0 = -1, os1 = -1; 03265 int priority = 0; 03266 struct ast_channel *oc0, *oc1; 03267 enum ast_bridge_result res; 03268 03269 #ifdef PRI_2BCT 03270 int triedtopribridge = 0; 03271 q931_call *q931c0 = NULL, *q931c1 = NULL; 03272 #endif 03273 03274 /* For now, don't attempt to native bridge if either channel needs DTMF detection. 03275 There is code below to handle it properly until DTMF is actually seen, 03276 but due to currently unresolved issues it's ignored... 03277 */ 03278 03279 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) 03280 return AST_BRIDGE_FAILED_NOWARN; 03281 03282 ast_mutex_lock(&c0->lock); 03283 while (ast_mutex_trylock(&c1->lock)) { 03284 DEADLOCK_AVOIDANCE(&c0->lock); 03285 } 03286 03287 p0 = c0->tech_pvt; 03288 p1 = c1->tech_pvt; 03289 /* cant do pseudo-channels here */ 03290 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) { 03291 ast_mutex_unlock(&c0->lock); 03292 ast_mutex_unlock(&c1->lock); 03293 return AST_BRIDGE_FAILED_NOWARN; 03294 } 03295 03296 oi0 = dahdi_get_index(c0, p0, 0); 03297 oi1 = dahdi_get_index(c1, p1, 0); 03298 if ((oi0 < 0) || (oi1 < 0)) { 03299 ast_mutex_unlock(&c0->lock); 03300 ast_mutex_unlock(&c1->lock); 03301 return AST_BRIDGE_FAILED; 03302 } 03303 03304 op0 = p0 = c0->tech_pvt; 03305 op1 = p1 = c1->tech_pvt; 03306 ofd0 = c0->fds[0]; 03307 ofd1 = c1->fds[0]; 03308 oc0 = p0->owner; 03309 oc1 = p1->owner; 03310 03311 if (ast_mutex_trylock(&p0->lock)) { 03312 /* Don't block, due to potential for deadlock */ 03313 ast_mutex_unlock(&c0->lock); 03314 ast_mutex_unlock(&c1->lock); 03315 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03316 return AST_BRIDGE_RETRY; 03317 } 03318 if (ast_mutex_trylock(&p1->lock)) { 03319 /* Don't block, due to potential for deadlock */ 03320 ast_mutex_unlock(&p0->lock); 03321 ast_mutex_unlock(&c0->lock); 03322 ast_mutex_unlock(&c1->lock); 03323 ast_log(LOG_NOTICE, "Avoiding deadlock...\n"); 03324 return AST_BRIDGE_RETRY; 03325 } 03326 03327 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03328 if (p0->owner && p1->owner) { 03329 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */ 03330 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) { 03331 master = p0; 03332 slave = p1; 03333 inconf = 1; 03334 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) { 03335 master = p1; 03336 slave = p0; 03337 inconf = 1; 03338 } else { 03339 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n"); 03340 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n", 03341 p0->channel, 03342 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03343 p0->subs[SUB_REAL].inthreeway, p0->channel, 03344 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0, 03345 p1->subs[SUB_REAL].inthreeway); 03346 } 03347 nothingok = 0; 03348 } 03349 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) { 03350 if (p1->subs[SUB_THREEWAY].inthreeway) { 03351 master = p1; 03352 slave = p0; 03353 nothingok = 0; 03354 } 03355 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) { 03356 if (p0->subs[SUB_THREEWAY].inthreeway) { 03357 master = p0; 03358 slave = p1; 03359 nothingok = 0; 03360 } 03361 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) { 03362 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise, 03363 don't put us in anything */ 03364 if (p1->subs[SUB_CALLWAIT].inthreeway) { 03365 master = p1; 03366 slave = p0; 03367 nothingok = 0; 03368 } 03369 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) { 03370 /* Same as previous */ 03371 if (p0->subs[SUB_CALLWAIT].inthreeway) { 03372 master = p0; 03373 slave = p1; 03374 nothingok = 0; 03375 } 03376 } 03377 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n", 03378 master ? master->channel : 0, slave ? slave->channel : 0, nothingok); 03379 if (master && slave) { 03380 /* Stop any tones, or play ringtone as appropriate. If they're bridged 03381 in an active threeway call with a channel that is ringing, we should 03382 indicate ringing. */ 03383 if ((oi1 == SUB_THREEWAY) && 03384 p1->subs[SUB_THREEWAY].inthreeway && 03385 p1->subs[SUB_REAL].owner && 03386 p1->subs[SUB_REAL].inthreeway && 03387 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03388 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name); 03389 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE); 03390 os1 = p1->subs[SUB_REAL].owner->_state; 03391 } else { 03392 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1); 03393 tone_zone_play_tone(p0->subs[oi0].dfd, -1); 03394 } 03395 if ((oi0 == SUB_THREEWAY) && 03396 p0->subs[SUB_THREEWAY].inthreeway && 03397 p0->subs[SUB_REAL].owner && 03398 p0->subs[SUB_REAL].inthreeway && 03399 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) { 03400 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name); 03401 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE); 03402 os0 = p0->subs[SUB_REAL].owner->_state; 03403 } else { 03404 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0); 03405 tone_zone_play_tone(p1->subs[oi0].dfd, -1); 03406 } 03407 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) { 03408 if (!p0->echocanbridged || !p1->echocanbridged) { 03409 /* Disable echo cancellation if appropriate */ 03410 dahdi_disable_ec(p0); 03411 dahdi_disable_ec(p1); 03412 } 03413 } 03414 dahdi_link(slave, master); 03415 master->inconference = inconf; 03416 } else if (!nothingok) 03417 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]); 03418 03419 update_conf(p0); 03420 update_conf(p1); 03421 t0 = p0->subs[SUB_REAL].inthreeway; 03422 t1 = p1->subs[SUB_REAL].inthreeway; 03423 03424 ast_mutex_unlock(&p0->lock); 03425 ast_mutex_unlock(&p1->lock); 03426 03427 ast_mutex_unlock(&c0->lock); 03428 ast_mutex_unlock(&c1->lock); 03429 03430 /* Native bridge failed */ 03431 if ((!master || !slave) && !nothingok) { 03432 dahdi_enable_ec(p0); 03433 dahdi_enable_ec(p1); 03434 return AST_BRIDGE_FAILED; 03435 } 03436 03437 if (option_verbose > 2) 03438 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 03439 03440 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03441 disable_dtmf_detect(op0); 03442 03443 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03444 disable_dtmf_detect(op1); 03445 03446 for (;;) { 03447 struct ast_channel *c0_priority[2] = {c0, c1}; 03448 struct ast_channel *c1_priority[2] = {c1, c0}; 03449 03450 /* Here's our main loop... Start by locking things, looking for private parts, 03451 and then balking if anything is wrong */ 03452 ast_mutex_lock(&c0->lock); 03453 while (ast_mutex_trylock(&c1->lock)) { 03454 DEADLOCK_AVOIDANCE(&c0->lock); 03455 } 03456 03457 p0 = c0->tech_pvt; 03458 p1 = c1->tech_pvt; 03459 03460 if (op0 == p0) 03461 i0 = dahdi_get_index(c0, p0, 1); 03462 if (op1 == p1) 03463 i1 = dahdi_get_index(c1, p1, 1); 03464 ast_mutex_unlock(&c0->lock); 03465 ast_mutex_unlock(&c1->lock); 03466 03467 if (!timeoutms || 03468 (op0 != p0) || 03469 (op1 != p1) || 03470 (ofd0 != c0->fds[0]) || 03471 (ofd1 != c1->fds[0]) || 03472 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 03473 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 03474 (oc0 != p0->owner) || 03475 (oc1 != p1->owner) || 03476 (t0 != p0->subs[SUB_REAL].inthreeway) || 03477 (t1 != p1->subs[SUB_REAL].inthreeway) || 03478 (oi0 != i0) || 03479 (oi1 != i1)) { 03480 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n", 03481 op0->channel, oi0, op1->channel, oi1); 03482 res = AST_BRIDGE_RETRY; 03483 goto return_from_bridge; 03484 } 03485 03486 #ifdef PRI_2BCT 03487 q931c0 = p0->call; 03488 q931c1 = p1->call; 03489 if (p0->transfer && p1->transfer 03490 && q931c0 && q931c1 03491 && !triedtopribridge) { 03492 pri_channel_bridge(q931c0, q931c1); 03493 triedtopribridge = 1; 03494 } 03495 #endif 03496 03497 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms); 03498 if (!who) { 03499 ast_log(LOG_DEBUG, "Ooh, empty read...\n"); 03500 continue; 03501 } 03502 f = ast_read(who); 03503 if (!f || (f->frametype == AST_FRAME_CONTROL)) { 03504 *fo = f; 03505 *rc = who; 03506 res = AST_BRIDGE_COMPLETE; 03507 goto return_from_bridge; 03508 } 03509 if (f->frametype == AST_FRAME_DTMF) { 03510 if ((who == c0) && p0->pulsedial) { 03511 ast_write(c1, f); 03512 } else if ((who == c1) && p1->pulsedial) { 03513 ast_write(c0, f); 03514 } else { 03515 *fo = f; 03516 *rc = who; 03517 res = AST_BRIDGE_COMPLETE; 03518 goto return_from_bridge; 03519 } 03520 } 03521 ast_frfree(f); 03522 03523 /* Swap who gets priority */ 03524 priority = !priority; 03525 } 03526 03527 return_from_bridge: 03528 if (op0 == p0) 03529 dahdi_enable_ec(p0); 03530 03531 if (op1 == p1) 03532 dahdi_enable_ec(p1); 03533 03534 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL)) 03535 enable_dtmf_detect(op0); 03536 03537 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL)) 03538 enable_dtmf_detect(op1); 03539 03540 dahdi_unlink(slave, master, 1); 03541 03542 return res; 03543 }
static int dahdi_call | ( | struct ast_channel * | ast, | |
char * | rdest, | |||
int | timeout | |||
) | [static] |
Definition at line 1829 of file chan_dahdi.c.
References ast_channel::_state, ast_callerid_generate(), AST_LAW, ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, 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_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pvt::finaldial, free, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, MAX_CALLERID_SIZE, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, 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::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, VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
01830 { 01831 struct dahdi_pvt *p = ast->tech_pvt; 01832 int x, res, index,mysig; 01833 char *c, *n, *l; 01834 #ifdef HAVE_PRI 01835 char *s = NULL; 01836 #endif 01837 char dest[256]; /* must be same length as p->dialdest */ 01838 ast_mutex_lock(&p->lock); 01839 ast_copy_string(dest, rdest, sizeof(dest)); 01840 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest)); 01841 if ((ast->_state == AST_STATE_BUSY)) { 01842 p->subs[SUB_REAL].needbusy = 1; 01843 ast_mutex_unlock(&p->lock); 01844 return 0; 01845 } 01846 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 01847 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name); 01848 ast_mutex_unlock(&p->lock); 01849 return -1; 01850 } 01851 p->dialednone = 0; 01852 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */ 01853 { 01854 /* Special pseudo -- automatically up */ 01855 ast_setstate(ast, AST_STATE_UP); 01856 ast_mutex_unlock(&p->lock); 01857 return 0; 01858 } 01859 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE; 01860 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 01861 if (res) 01862 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno)); 01863 p->outgoing = 1; 01864 01865 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 01866 01867 mysig = p->sig; 01868 if (p->outsigmod > -1) 01869 mysig = p->outsigmod; 01870 01871 switch (mysig) { 01872 case SIG_FXOLS: 01873 case SIG_FXOGS: 01874 case SIG_FXOKS: 01875 if (p->owner == ast) { 01876 /* Normal ring, on hook */ 01877 01878 /* Don't send audio while on hook, until the call is answered */ 01879 p->dialing = 1; 01880 if (p->use_callerid) { 01881 /* Generate the Caller-ID spill if desired */ 01882 if (p->cidspill) { 01883 ast_log(LOG_WARNING, "cidspill already exists??\n"); 01884 free(p->cidspill); 01885 } 01886 p->callwaitcas = 0; 01887 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) { 01888 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p)); 01889 p->cidpos = 0; 01890 send_callerid(p); 01891 } 01892 } 01893 /* Choose proper cadence */ 01894 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { 01895 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) 01896 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); 01897 p->cidrings = cidrings[p->distinctivering - 1]; 01898 } else { 01899 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) 01900 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); 01901 p->cidrings = p->sendcalleridafter; 01902 } 01903 01904 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ 01905 c = strchr(dest, '/'); 01906 if (c) 01907 c++; 01908 if (c && (strlen(c) < p->stripmsd)) { 01909 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 01910 c = NULL; 01911 } 01912 if (c) { 01913 p->dop.op = DAHDI_DIAL_OP_REPLACE; 01914 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c); 01915 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c); 01916 } else { 01917 p->dop.dialstr[0] = '\0'; 01918 } 01919 x = DAHDI_RING; 01920 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) { 01921 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno)); 01922 ast_mutex_unlock(&p->lock); 01923 return -1; 01924 } 01925 p->dialing = 1; 01926 } else { 01927 /* Call waiting call */ 01928 p->callwaitrings = 0; 01929 if (ast->cid.cid_num) 01930 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num)); 01931 else 01932 p->callwait_num[0] = '\0'; 01933 if (ast->cid.cid_name) 01934 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name)); 01935 else 01936 p->callwait_name[0] = '\0'; 01937 /* Call waiting tone instead */ 01938 if (dahdi_callwait(ast)) { 01939 ast_mutex_unlock(&p->lock); 01940 return -1; 01941 } 01942 /* Make ring-back */ 01943 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE)) 01944 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name); 01945 01946 } 01947 n = ast->cid.cid_name; 01948 l = ast->cid.cid_num; 01949 if (l) 01950 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num)); 01951 else 01952 p->lastcid_num[0] = '\0'; 01953 if (n) 01954 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name)); 01955 else 01956 p->lastcid_name[0] = '\0'; 01957 ast_setstate(ast, AST_STATE_RINGING); 01958 index = dahdi_get_index(ast, p, 0); 01959 if (index > -1) { 01960 p->subs[index].needringing = 1; 01961 } 01962 break; 01963 case SIG_FXSLS: 01964 case SIG_FXSGS: 01965 case SIG_FXSKS: 01966 case SIG_EMWINK: 01967 case SIG_EM: 01968 case SIG_EM_E1: 01969 case SIG_FEATD: 01970 case SIG_FEATDMF: 01971 case SIG_E911: 01972 case SIG_FGC_CAMA: 01973 case SIG_FGC_CAMAMF: 01974 case SIG_FEATB: 01975 case SIG_SFWINK: 01976 case SIG_SF: 01977 case SIG_SF_FEATD: 01978 case SIG_SF_FEATDMF: 01979 case SIG_FEATDMF_TA: 01980 case SIG_SF_FEATB: 01981 c = strchr(dest, '/'); 01982 if (c) 01983 c++; 01984 else 01985 c = ""; 01986 if (strlen(c) < p->stripmsd) { 01987 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 01988 ast_mutex_unlock(&p->lock); 01989 return -1; 01990 } 01991 #ifdef HAVE_PRI 01992 /* Start the trunk, if not GR-303 */ 01993 if (!p->pri) { 01994 #endif 01995 x = DAHDI_START; 01996 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 01997 if (res < 0) { 01998 if (errno != EINPROGRESS) { 01999 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno)); 02000 ast_mutex_unlock(&p->lock); 02001 return -1; 02002 } 02003 } 02004 #ifdef HAVE_PRI 02005 } 02006 #endif 02007 ast_log(LOG_DEBUG, "Dialing '%s'\n", c); 02008 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02009 02010 c += p->stripmsd; 02011 02012 switch (mysig) { 02013 case SIG_FEATD: 02014 l = ast->cid.cid_num; 02015 if (l) 02016 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c); 02017 else 02018 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c); 02019 break; 02020 case SIG_FEATDMF: 02021 l = ast->cid.cid_num; 02022 if (l) 02023 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c); 02024 else 02025 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c); 02026 break; 02027 case SIG_FEATDMF_TA: 02028 { 02029 const char *cic, *ozz; 02030 02031 /* If you have to go through a Tandem Access point you need to use this */ 02032 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ"); 02033 if (!ozz) 02034 ozz = defaultozz; 02035 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC"); 02036 if (!cic) 02037 cic = defaultcic; 02038 if (!ozz || !cic) { 02039 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n"); 02040 ast_mutex_unlock(&p->lock); 02041 return -1; 02042 } 02043 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic); 02044 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c); 02045 p->whichwink = 0; 02046 } 02047 break; 02048 case SIG_E911: 02049 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr)); 02050 break; 02051 case SIG_FGC_CAMA: 02052 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c); 02053 break; 02054 case SIG_FGC_CAMAMF: 02055 case SIG_FEATB: 02056 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c); 02057 break; 02058 default: 02059 if (p->pulse) 02060 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c); 02061 else 02062 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c); 02063 break; 02064 } 02065 02066 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) { 02067 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 02068 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 02069 p->echorest[sizeof(p->echorest) - 1] = '\0'; 02070 p->echobreak = 1; 02071 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 02072 } else 02073 p->echobreak = 0; 02074 if (!res) { 02075 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 02076 int saveerr = errno; 02077 02078 x = DAHDI_ONHOOK; 02079 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 02080 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 02081 ast_mutex_unlock(&p->lock); 02082 return -1; 02083 } 02084 } else 02085 ast_log(LOG_DEBUG, "Deferring dialing...\n"); 02086 p->dialing = 1; 02087 if (ast_strlen_zero(c)) 02088 p->dialednone = 1; 02089 ast_setstate(ast, AST_STATE_DIALING); 02090 break; 02091 case 0: 02092 /* Special pseudo -- automatically up*/ 02093 ast_setstate(ast, AST_STATE_UP); 02094 break; 02095 case SIG_PRI: 02096 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */ 02097 p->dialdest[0] = '\0'; 02098 break; 02099 default: 02100 ast_log(LOG_DEBUG, "not yet implemented\n"); 02101 ast_mutex_unlock(&p->lock); 02102 return -1; 02103 } 02104 #ifdef HAVE_PRI 02105 if (p->pri) { 02106 struct pri_sr *sr; 02107 #ifdef SUPPORT_USERUSER 02108 const char *useruser; 02109 #endif 02110 int pridialplan; 02111 int dp_strip; 02112 int prilocaldialplan; 02113 int ldp_strip; 02114 int exclusive; 02115 const char *rr_str; 02116 int redirect_reason; 02117 02118 c = strchr(dest, '/'); 02119 if (c) 02120 c++; 02121 else 02122 c = dest; 02123 02124 l = NULL; 02125 n = NULL; 02126 02127 if (!p->hidecallerid) { 02128 l = ast->cid.cid_num; 02129 if (!p->hidecalleridname) { 02130 n = ast->cid.cid_name; 02131 } 02132 } 02133 02134 02135 if (strlen(c) < p->stripmsd) { 02136 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd); 02137 ast_mutex_unlock(&p->lock); 02138 return -1; 02139 } 02140 if (mysig != SIG_FXSKS) { 02141 p->dop.op = DAHDI_DIAL_OP_REPLACE; 02142 s = strchr(c + p->stripmsd, 'w'); 02143 if (s) { 02144 if (strlen(s) > 1) 02145 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s); 02146 else 02147 p->dop.dialstr[0] = '\0'; 02148 *s = '\0'; 02149 } else { 02150 p->dop.dialstr[0] = '\0'; 02151 } 02152 } 02153 if (pri_grab(p, p->pri)) { 02154 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 02155 ast_mutex_unlock(&p->lock); 02156 return -1; 02157 } 02158 if (!(p->call = pri_new_call(p->pri->pri))) { 02159 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel); 02160 pri_rel(p->pri); 02161 ast_mutex_unlock(&p->lock); 02162 return -1; 02163 } 02164 if (!(sr = pri_sr_new())) { 02165 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel); 02166 pri_destroycall(p->pri->pri, p->call); 02167 p->call = NULL; 02168 pri_rel(p->pri); 02169 ast_mutex_unlock(&p->lock); 02170 return -1; 02171 } 02172 if (p->bearer || (mysig == SIG_FXSKS)) { 02173 if (p->bearer) { 02174 ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel); 02175 p->bearer->call = p->call; 02176 } else 02177 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n"); 02178 pri_set_crv(p->pri->pri, p->call, p->channel, 0); 02179 } 02180 p->digital = IS_DIGITAL(ast->transfercapability); 02181 /* Add support for exclusive override */ 02182 if (p->priexclusive) 02183 exclusive = 1; 02184 else { 02185 /* otherwise, traditional behavior */ 02186 if (p->pri->nodetype == PRI_NETWORK) 02187 exclusive = 0; 02188 else 02189 exclusive = 1; 02190 } 02191 02192 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1); 02193 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 02194 (p->digital ? -1 : 02195 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW))); 02196 if (p->pri->facilityenable) 02197 pri_facility_enable(p->pri->pri); 02198 02199 if (option_verbose > 2) 02200 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability)); 02201 dp_strip = 0; 02202 pridialplan = p->pri->dialplan - 1; 02203 if (pridialplan == -2) { /* compute dynamically */ 02204 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02205 dp_strip = strlen(p->pri->internationalprefix); 02206 pridialplan = PRI_INTERNATIONAL_ISDN; 02207 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02208 dp_strip = strlen(p->pri->nationalprefix); 02209 pridialplan = PRI_NATIONAL_ISDN; 02210 } else { 02211 pridialplan = PRI_LOCAL_ISDN; 02212 } 02213 } 02214 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0); 02215 02216 ldp_strip = 0; 02217 prilocaldialplan = p->pri->localdialplan - 1; 02218 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */ 02219 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) { 02220 ldp_strip = strlen(p->pri->internationalprefix); 02221 prilocaldialplan = PRI_INTERNATIONAL_ISDN; 02222 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) { 02223 ldp_strip = strlen(p->pri->nationalprefix); 02224 prilocaldialplan = PRI_NATIONAL_ISDN; 02225 } else { 02226 prilocaldialplan = PRI_LOCAL_ISDN; 02227 } 02228 } 02229 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan, 02230 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE)); 02231 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) { 02232 if (!strcasecmp(rr_str, "UNKNOWN")) 02233 redirect_reason = 0; 02234 else if (!strcasecmp(rr_str, "BUSY")) 02235 redirect_reason = 1; 02236 else if (!strcasecmp(rr_str, "NO_REPLY")) 02237 redirect_reason = 2; 02238 else if (!strcasecmp(rr_str, "UNCONDITIONAL")) 02239 redirect_reason = 15; 02240 else 02241 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02242 } else 02243 redirect_reason = PRI_REDIR_UNCONDITIONAL; 02244 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason); 02245 02246 #ifdef SUPPORT_USERUSER 02247 /* User-user info */ 02248 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO"); 02249 02250 if (useruser) 02251 pri_sr_set_useruser(sr, useruser); 02252 #endif 02253 02254 if (pri_setup(p->pri->pri, p->call, sr)) { 02255 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 02256 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan)); 02257 pri_rel(p->pri); 02258 ast_mutex_unlock(&p->lock); 02259 pri_sr_free(sr); 02260 return -1; 02261 } 02262 pri_sr_free(sr); 02263 ast_setstate(ast, AST_STATE_DIALING); 02264 pri_rel(p->pri); 02265 } 02266 #endif 02267 ast_mutex_unlock(&p->lock); 02268 return 0; 02269 }
static int dahdi_callwait | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 1801 of file chan_dahdi.c.
References 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, free, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.
Referenced by dahdi_call(), and dahdi_read().
01802 { 01803 struct dahdi_pvt *p = ast->tech_pvt; 01804 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES; 01805 if (p->cidspill) { 01806 ast_log(LOG_WARNING, "Spill already exists?!?\n"); 01807 free(p->cidspill); 01808 } 01809 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4))) 01810 return -1; 01811 save_conference(p); 01812 /* Silence */ 01813 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4); 01814 if (!p->callwaitrings && p->callwaitingcallerid) { 01815 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p)); 01816 p->callwaitcas = 1; 01817 p->cidlen = 2400 + 680 + READ_SIZE * 4; 01818 } else { 01819 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p)); 01820 p->callwaitcas = 0; 01821 p->cidlen = 2400 + READ_SIZE * 4; 01822 } 01823 p->cidpos = 0; 01824 send_callerid(p); 01825 01826 return 0; 01827 }
static struct dahdi_chan_conf dahdi_chan_conf_default | ( | void | ) | [static] |
returns a new dahdi_chan_conf with default values (by-value)
Definition at line 609 of file chan_dahdi.c.
References dahdi_chan_conf::chan, CID_SIG_BELL, CID_START_RING, dahdi_pvt::context, and DEFAULT_CIDRINGS.
Referenced by setup_dahdi().
00609 { 00610 /* recall that if a field is not included here it is initialized 00611 * to 0 or equivalent 00612 */ 00613 struct dahdi_chan_conf conf = { 00614 #ifdef HAVE_PRI 00615 .pri = { 00616 .nsf = PRI_NSF_NONE, 00617 .switchtype = PRI_SWITCH_NI2, 00618 .dialplan = PRI_NATIONAL_ISDN + 1, 00619 .localdialplan = PRI_NATIONAL_ISDN + 1, 00620 .nodetype = PRI_CPE, 00621 00622 .minunused = 2, 00623 .idleext = "", 00624 .idledial = "", 00625 .internationalprefix = "", 00626 .nationalprefix = "", 00627 .localprefix = "", 00628 .privateprefix = "", 00629 .unknownprefix = "", 00630 00631 .resetinterval = 3600 00632 }, 00633 #endif 00634 .chan = { 00635 .context = "default", 00636 .cid_num = "", 00637 .cid_name = "", 00638 .mohinterpret = "default", 00639 .mohsuggest = "", 00640 .transfertobusy = 1, 00641 00642 .cid_signalling = CID_SIG_BELL, 00643 .cid_start = CID_START_RING, 00644 .dahditrcallerid = 0, 00645 .use_callerid = 1, 00646 .sig = -1, 00647 .outsigmod = -1, 00648 00649 .tonezone = -1, 00650 00651 .echocancel = 1, 00652 00653 .busycount = 3, 00654 .busycompare = 0, 00655 .busytonelength = 0, 00656 .busyquietlength = 0, 00657 .busyfuzziness = 0, 00658 .silencethreshold = 0, 00659 00660 .accountcode = "", 00661 00662 .mailbox = "", 00663 00664 00665 .polarityonanswerdelay = 600, 00666 00667 .sendcalleridafter = DEFAULT_CIDRINGS, 00668 00669 .buf_policy = DAHDI_POLICY_IMMEDIATE, 00670 .buf_no = numbufs 00671 }, 00672 .timing = { 00673 .prewinktime = -1, 00674 .preflashtime = -1, 00675 .winktime = -1, 00676 .flashtime = -1, 00677 .starttime = -1, 00678 .rxwinktime = -1, 00679 .rxflashtime = -1, 00680 .debouncetime = -1 00681 }, 00682 .smdi_port = "/dev/ttyS0", 00683 }; 00684 00685 return conf; 00686 }
static void dahdi_close | ( | int | fd | ) | [static] |
static void dahdi_close_sub | ( | struct dahdi_pvt * | chan_pvt, | |
int | sub_num | |||
) | [static] |
Definition at line 963 of file chan_dahdi.c.
References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by alloc_sub(), destroy_dahdi_pvt(), and unalloc_sub().
00964 { 00965 dahdi_close(chan_pvt->subs[sub_num].dfd); 00966 chan_pvt->subs[sub_num].dfd = -1; 00967 }
static int dahdi_confmute | ( | struct dahdi_pvt * | p, | |
int | muted | |||
) | [inline, static] |
Definition at line 1684 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_dtmfup(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().
01685 { 01686 int x, y, res; 01687 x = muted; 01688 if (p->sig == SIG_PRI) { 01689 y = 1; 01690 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y); 01691 if (res) 01692 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno)); 01693 } 01694 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x); 01695 if (res < 0) 01696 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno)); 01697 return res; 01698 }
static int dahdi_destroy_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10050 of file chan_dahdi.c.
References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.
10051 { 10052 int channel; 10053 10054 if (argc != 4) 10055 return RESULT_SHOWUSAGE; 10056 10057 channel = atoi(argv[3]); 10058 10059 return dahdi_destroy_channel_bynum(channel); 10060 }
static int dahdi_destroy_channel_bynum | ( | int | channel | ) | [static] |
Definition at line 6721 of file chan_dahdi.c.
References ast_module_unref(), dahdi_pvt::channel, destroy_channel(), iflist, dahdi_pvt::next, dahdi_pvt::prev, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_destroy_channel(), and handle_init_event().
06722 { 06723 struct dahdi_pvt *tmp = NULL; 06724 struct dahdi_pvt *prev = NULL; 06725 06726 tmp = iflist; 06727 while (tmp) { 06728 if (tmp->channel == channel) { 06729 int x = DAHDI_FLASH; 06730 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 */ 06731 destroy_channel(prev, tmp, 1); 06732 ast_module_unref(ast_module_info->self); 06733 return RESULT_SUCCESS; 06734 } 06735 prev = tmp; 06736 tmp = tmp->next; 06737 } 06738 return RESULT_FAILURE; 06739 }
static int dahdi_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 1058 of file chan_dahdi.c.
References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_get_index(), dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01059 { 01060 struct dahdi_pvt *pvt; 01061 int index; 01062 int dtmf = -1; 01063 01064 pvt = chan->tech_pvt; 01065 01066 ast_mutex_lock(&pvt->lock); 01067 01068 index = dahdi_get_index(chan, pvt, 0); 01069 01070 if ((index != SUB_REAL) || !pvt->owner) 01071 goto out; 01072 01073 #ifdef HAVE_PRI 01074 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) { 01075 if (pvt->setup_ack) { 01076 if (!pri_grab(pvt, pvt->pri)) { 01077 pri_information(pvt->pri->pri, pvt->call, digit); 01078 pri_rel(pvt->pri); 01079 } else 01080 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span); 01081 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) { 01082 int res; 01083 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit); 01084 res = strlen(pvt->dialdest); 01085 pvt->dialdest[res++] = digit; 01086 pvt->dialdest[res] = '\0'; 01087 } 01088 goto out; 01089 } 01090 #endif 01091 if ((dtmf = digit_to_dtmfindex(digit)) == -1) 01092 goto out; 01093 01094 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) { 01095 int res; 01096 struct dahdi_dialoperation zo = { 01097 .op = DAHDI_DIAL_OP_APPEND, 01098 .dialstr[0] = 'T', 01099 .dialstr[1] = digit, 01100 .dialstr[2] = 0, 01101 }; 01102 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo))) 01103 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno)); 01104 else 01105 pvt->dialing = 1; 01106 } else { 01107 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit); 01108 pvt->dialing = 1; 01109 pvt->begindigit = digit; 01110 } 01111 01112 out: 01113 ast_mutex_unlock(&pvt->lock); 01114 01115 return 0; 01116 }
static int dahdi_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 1118 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_pvt::dialing, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
01119 { 01120 struct dahdi_pvt *pvt; 01121 int res = 0; 01122 int index; 01123 int x; 01124 01125 pvt = chan->tech_pvt; 01126 01127 ast_mutex_lock(&pvt->lock); 01128 01129 index = dahdi_get_index(chan, pvt, 0); 01130 01131 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse) 01132 goto out; 01133 01134 #ifdef HAVE_PRI 01135 /* This means that the digit was already sent via PRI signalling */ 01136 if (pvt->sig == SIG_PRI && !pvt->begindigit) 01137 goto out; 01138 #endif 01139 01140 if (pvt->begindigit) { 01141 x = -1; 01142 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit); 01143 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x); 01144 pvt->dialing = 0; 01145 pvt->begindigit = 0; 01146 } 01147 01148 out: 01149 ast_mutex_unlock(&pvt->lock); 01150 01151 return res; 01152 }
static void dahdi_disable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1515 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().
01516 { 01517 int x; 01518 int res; 01519 if (p->echocancel) { 01520 x = 0; 01521 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01522 if (res) 01523 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno)); 01524 else if (option_debug) 01525 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel); 01526 } 01527 p->echocanon = 0; 01528 }
static void dahdi_enable_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1465 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_setoption(), handle_init_event(), and ss_thread().
01466 { 01467 int x; 01468 int res; 01469 if (!p) 01470 return; 01471 if (p->echocanon) { 01472 ast_log(LOG_DEBUG, "Echo cancellation already on\n"); 01473 return; 01474 } 01475 if (p->digital) { 01476 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n"); 01477 return; 01478 } 01479 if (p->echocancel) { 01480 if (p->sig == SIG_PRI) { 01481 x = 1; 01482 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x); 01483 if (res) 01484 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno)); 01485 } 01486 x = p->echocancel; 01487 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x); 01488 if (res) 01489 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno)); 01490 else { 01491 p->echocanon = 1; 01492 if (option_debug) 01493 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel); 01494 } 01495 } else if (option_debug) 01496 ast_log(LOG_DEBUG, "No echo cancellation requested\n"); 01497 }
static struct ast_frame * dahdi_exception | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4747 of file chan_dahdi.c.
References __dahdi_exception(), ast_mutex_lock(), ast_mutex_unlock(), f, dahdi_pvt::lock, and ast_channel::tech_pvt.
04748 { 04749 struct dahdi_pvt *p = ast->tech_pvt; 04750 struct ast_frame *f; 04751 ast_mutex_lock(&p->lock); 04752 f = __dahdi_exception(ast); 04753 ast_mutex_unlock(&p->lock); 04754 return f; 04755 }
static int dahdi_fake_event | ( | struct dahdi_pvt * | p, | |
int | mode | |||
) | [static] |
Definition at line 10586 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::fake_event, HANGUP, dahdi_pvt::owner, and TRANSFER.
Referenced by __action_transfer(), and __action_transferhangup().
10587 { 10588 if (p) { 10589 switch (mode) { 10590 case TRANSFER: 10591 p->fake_event = DAHDI_EVENT_WINKFLASH; 10592 break; 10593 case HANGUP: 10594 p->fake_event = DAHDI_EVENT_ONHOOK; 10595 break; 10596 default: 10597 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name); 10598 } 10599 } 10600 return 0; 10601 }
static int dahdi_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 3545 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.
03546 { 03547 struct dahdi_pvt *p = newchan->tech_pvt; 03548 int x; 03549 ast_mutex_lock(&p->lock); 03550 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name); 03551 if (p->owner == oldchan) { 03552 p->owner = newchan; 03553 } 03554 for (x = 0; x < 3; x++) 03555 if (p->subs[x].owner == oldchan) { 03556 if (!x) 03557 dahdi_unlink(NULL, p, 0); 03558 p->subs[x].owner = newchan; 03559 } 03560 if (newchan->_state == AST_STATE_RINGING) 03561 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0); 03562 update_conf(p); 03563 ast_mutex_unlock(&p->lock); 03564 return 0; 03565 }
static int dahdi_func_read | ( | struct ast_channel * | chan, | |
char * | function, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 3117 of file chan_dahdi.c.
References ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.
03118 { 03119 struct dahdi_pvt *p = chan->tech_pvt; 03120 03121 if (!strcasecmp(data, "rxgain")) { 03122 ast_mutex_lock(&p->lock); 03123 snprintf(buf, len, "%f", p->rxgain); 03124 ast_mutex_unlock(&p->lock); 03125 } else if (!strcasecmp(data, "txgain")) { 03126 ast_mutex_lock(&p->lock); 03127 snprintf(buf, len, "%f", p->txgain); 03128 ast_mutex_unlock(&p->lock); 03129 } else { 03130 ast_copy_string(buf, "", len); 03131 } 03132 return 0; 03133 }
static int dahdi_get_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_getevent which ignores a bunch of events.
Definition at line 256 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
00257 { 00258 int j; 00259 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00260 return -1; 00261 return j; 00262 }
static int dahdi_get_index | ( | struct ast_channel * | ast, | |
struct dahdi_pvt * | p, | |||
int | nullok | |||
) | [static] |
Definition at line 802 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, 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().
00803 { 00804 int res; 00805 if (p->subs[SUB_REAL].owner == ast) 00806 res = 0; 00807 else if (p->subs[SUB_CALLWAIT].owner == ast) 00808 res = 1; 00809 else if (p->subs[SUB_THREEWAY].owner == ast) 00810 res = 2; 00811 else { 00812 res = -1; 00813 if (!nullok) 00814 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n"); 00815 } 00816 return res; 00817 }
static void dahdi_handle_dtmfup | ( | struct ast_channel * | ast, | |
int | index, | |||
struct ast_frame ** | dest | |||
) | [static] |
Definition at line 3708 of file chan_dahdi.c.
References ast_async_goto(), AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_log(), ast_verbose(), dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxhandled, ast_frame::frametype, free, LOG_DEBUG, LOG_NOTICE, ast_channel::macrocontext, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event(), and dahdi_read().
03709 { 03710 struct dahdi_pvt *p = ast->tech_pvt; 03711 struct ast_frame *f = *dest; 03712 03713 if (option_debug) 03714 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name); 03715 03716 if (p->confirmanswer) { 03717 if (option_debug) 03718 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name); 03719 /* Upon receiving a DTMF digit, consider this an answer confirmation instead 03720 of a DTMF digit */ 03721 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03722 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 03723 *dest = &p->subs[index].f; 03724 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */ 03725 p->confirmanswer = 0; 03726 } else if (p->callwaitcas) { 03727 if ((f->subclass == 'A') || (f->subclass == 'D')) { 03728 if (option_debug) 03729 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n"); 03730 if (p->cidspill) 03731 free(p->cidspill); 03732 send_cwcidspill(p); 03733 } 03734 if ((f->subclass != 'm') && (f->subclass != 'u')) 03735 p->callwaitcas = 0; 03736 p->subs[index].f.frametype = AST_FRAME_NULL; 03737 p->subs[index].f.subclass = 0; 03738 *dest = &p->subs[index].f; 03739 } else if (f->subclass == 'f') { 03740 /* Fax tone -- Handle and return NULL */ 03741 if ((p->callprogress & 0x6) && !p->faxhandled) { 03742 p->faxhandled++; 03743 if (strcmp(ast->exten, "fax")) { 03744 const char *target_context = S_OR(ast->macrocontext, ast->context); 03745 03746 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) { 03747 if (option_verbose > 2) 03748 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name); 03749 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 03750 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten); 03751 if (ast_async_goto(ast, target_context, "fax", 1)) 03752 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context); 03753 } else 03754 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n"); 03755 } else if (option_debug) 03756 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 03757 } else if (option_debug) 03758 ast_log(LOG_DEBUG, "Fax already handled\n"); 03759 dahdi_confmute(p, 0); 03760 p->subs[index].f.frametype = AST_FRAME_NULL; 03761 p->subs[index].f.subclass = 0; 03762 *dest = &p->subs[index].f; 03763 } else if (f->subclass == 'm') { 03764 /* Confmute request */ 03765 dahdi_confmute(p, 1); 03766 p->subs[index].f.frametype = AST_FRAME_NULL; 03767 p->subs[index].f.subclass = 0; 03768 *dest = &p->subs[index].f; 03769 } else if (f->subclass == 'u') { 03770 /* Unmute */ 03771 dahdi_confmute(p, 0); 03772 p->subs[index].f.frametype = AST_FRAME_NULL; 03773 p->subs[index].f.subclass = 0; 03774 *dest = &p->subs[index].f; 03775 } else 03776 dahdi_confmute(p, 0); 03777 }
static struct ast_frame* dahdi_handle_event | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 3799 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), 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_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_pthread_create, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), 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_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_verbose(), attempt_transfer(), dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, 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::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), DAHDI_EVENT_DTMFDOWN, DAHDI_EVENT_DTMFUP, dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, 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_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, 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(), dahdi_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.
Referenced by __dahdi_exception().
03800 { 03801 int res, x; 03802 int index, mysig; 03803 char *c; 03804 struct dahdi_pvt *p = ast->tech_pvt; 03805 pthread_t threadid; 03806 pthread_attr_t attr; 03807 struct ast_channel *chan; 03808 struct ast_frame *f; 03809 03810 index = dahdi_get_index(ast, p, 0); 03811 mysig = p->sig; 03812 if (p->outsigmod > -1) 03813 mysig = p->outsigmod; 03814 p->subs[index].f.frametype = AST_FRAME_NULL; 03815 p->subs[index].f.subclass = 0; 03816 p->subs[index].f.datalen = 0; 03817 p->subs[index].f.samples = 0; 03818 p->subs[index].f.mallocd = 0; 03819 p->subs[index].f.offset = 0; 03820 p->subs[index].f.src = "dahdi_handle_event"; 03821 p->subs[index].f.data = NULL; 03822 f = &p->subs[index].f; 03823 03824 if (index < 0) 03825 return &p->subs[index].f; 03826 if (p->fake_event) { 03827 res = p->fake_event; 03828 p->fake_event = 0; 03829 } else 03830 res = dahdi_get_event(p->subs[index].dfd); 03831 03832 if (option_debug) 03833 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index); 03834 03835 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) { 03836 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0; 03837 03838 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff); 03839 #ifdef HAVE_PRI 03840 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) { 03841 /* absorb event */ 03842 } else { 03843 #endif 03844 p->subs[index].f.frametype = AST_FRAME_DTMF_END; 03845 p->subs[index].f.subclass = res & 0xff; 03846 #ifdef HAVE_PRI 03847 } 03848 #endif 03849 dahdi_handle_dtmfup(ast, index, &f); 03850 return f; 03851 } 03852 03853 if (res & DAHDI_EVENT_DTMFDOWN) { 03854 if (option_debug) 03855 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff); 03856 /* Mute conference */ 03857 dahdi_confmute(p, 1); 03858 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN; 03859 p->subs[index].f.subclass = res & 0xff; 03860 return &p->subs[index].f; 03861 } 03862 03863 switch (res) { 03864 #ifdef DAHDI_EVENT_EC_DISABLED 03865 case DAHDI_EVENT_EC_DISABLED: 03866 if (option_verbose > 2) 03867 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel); 03868 p->echocanon = 0; 03869 break; 03870 #endif 03871 case DAHDI_EVENT_BITSCHANGED: 03872 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig)); 03873 case DAHDI_EVENT_PULSE_START: 03874 /* Stop tone if there's a pulse start and the PBX isn't started */ 03875 if (!ast->pbx) 03876 tone_zone_play_tone(p->subs[index].dfd, -1); 03877 break; 03878 case DAHDI_EVENT_DIALCOMPLETE: 03879 if (p->inalarm) break; 03880 if ((p->radio || (p->oprmode < 0))) break; 03881 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) { 03882 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno)); 03883 return NULL; 03884 } 03885 if (!x) { /* if not still dialing in driver */ 03886 dahdi_enable_ec(p); 03887 if (p->echobreak) { 03888 dahdi_train_ec(p); 03889 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr)); 03890 p->dop.op = DAHDI_DIAL_OP_REPLACE; 03891 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 03892 p->echobreak = 0; 03893 } else { 03894 p->dialing = 0; 03895 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) { 03896 /* if thru with dialing after offhook */ 03897 if (ast->_state == AST_STATE_DIALING_OFFHOOK) { 03898 ast_setstate(ast, AST_STATE_UP); 03899 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03900 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 03901 break; 03902 } else { /* if to state wait for offhook to dial rest */ 03903 /* we now wait for off hook */ 03904 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK); 03905 } 03906 } 03907 if (ast->_state == AST_STATE_DIALING) { 03908 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) { 03909 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n"); 03910 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) { 03911 ast_setstate(ast, AST_STATE_RINGING); 03912 } else if (!p->answeronpolarityswitch) { 03913 ast_setstate(ast, AST_STATE_UP); 03914 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03915 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 03916 /* If aops=0 and hops=1, this is necessary */ 03917 p->polarity = POLARITY_REV; 03918 } else { 03919 /* Start clean, so we can catch the change to REV polarity when party answers */ 03920 p->polarity = POLARITY_IDLE; 03921 } 03922 } 03923 } 03924 } 03925 break; 03926 case DAHDI_EVENT_ALARM: 03927 #ifdef HAVE_PRI 03928 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) { 03929 /* T309 is not enabled : hangup calls when alarm occurs */ 03930 if (p->call) { 03931 if (p->pri && p->pri->pri) { 03932 if (!pri_grab(p, p->pri)) { 03933 pri_hangup(p->pri->pri, p->call, -1); 03934 pri_destroycall(p->pri->pri, p->call); 03935 p->call = NULL; 03936 pri_rel(p->pri); 03937 } else 03938 ast_log(LOG_WARNING, "Failed to grab PRI!\n"); 03939 } else 03940 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n"); 03941 } 03942 if (p->owner) 03943 p->owner->_softhangup |= AST_SOFTHANGUP_DEV; 03944 } 03945 if (p->bearer) 03946 p->bearer->inalarm = 1; 03947 else 03948 #endif 03949 p->inalarm = 1; 03950 res = get_alarms(p); 03951 handle_alarms(p, res); 03952 #ifdef HAVE_LIBPRI 03953 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) { 03954 /* fall through intentionally */ 03955 } else { 03956 break; 03957 } 03958 #endif 03959 case DAHDI_EVENT_ONHOOK: 03960 if (p->radio) { 03961 p->subs[index].f.frametype = AST_FRAME_CONTROL; 03962 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 03963 break; 03964 } 03965 if (p->oprmode < 0) 03966 { 03967 if (p->oprmode != -1) break; 03968 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 03969 { 03970 /* Make sure it starts ringing */ 03971 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 03972 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING); 03973 save_conference(p->oprpeer); 03974 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 03975 } 03976 break; 03977 } 03978 switch (p->sig) { 03979 case SIG_FXOLS: 03980 case SIG_FXOGS: 03981 case SIG_FXOKS: 03982 p->onhooktime = time(NULL); 03983 p->msgstate = -1; 03984 /* Check for some special conditions regarding call waiting */ 03985 if (index == SUB_REAL) { 03986 /* The normal line was hung up */ 03987 if (p->subs[SUB_CALLWAIT].owner) { 03988 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */ 03989 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 03990 if (option_verbose > 2) 03991 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel); 03992 unalloc_sub(p, SUB_CALLWAIT); 03993 #if 0 03994 p->subs[index].needanswer = 0; 03995 p->subs[index].needringing = 0; 03996 #endif 03997 p->callwaitingrepeat = 0; 03998 p->cidcwexpire = 0; 03999 p->owner = NULL; 04000 /* Don't start streaming audio yet if the incoming call isn't up yet */ 04001 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP) 04002 p->dialing = 1; 04003 dahdi_ring_phone(p); 04004 } else if (p->subs[SUB_THREEWAY].owner) { 04005 unsigned int mssinceflash; 04006 /* Here we have to retain the lock on both the main channel, the 3-way channel, and 04007 the private structure -- not especially easy or clean */ 04008 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) { 04009 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */ 04010 ast_mutex_unlock(&p->lock); 04011 DEADLOCK_AVOIDANCE(&ast->lock); 04012 /* We can grab ast and p in that order, without worry. We should make sure 04013 nothing seriously bad has happened though like some sort of bizarre double 04014 masquerade! */ 04015 ast_mutex_lock(&p->lock); 04016 if (p->owner != ast) { 04017 ast_log(LOG_WARNING, "This isn't good...\n"); 04018 return NULL; 04019 } 04020 } 04021 if (!p->subs[SUB_THREEWAY].owner) { 04022 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n"); 04023 return NULL; 04024 } 04025 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime); 04026 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash); 04027 if (mssinceflash < MIN_MS_SINCE_FLASH) { 04028 /* It hasn't been long enough since the last flashook. This is probably a bounce on 04029 hanging up. Hangup both channels now */ 04030 if (p->subs[SUB_THREEWAY].owner) 04031 ast_queue_hangup(p->subs[SUB_THREEWAY].owner); 04032 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04033 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); 04034 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04035 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) { 04036 if (p->transfer) { 04037 /* In any case this isn't a threeway call anymore */ 04038 p->subs[SUB_REAL].inthreeway = 0; 04039 p->subs[SUB_THREEWAY].inthreeway = 0; 04040 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */ 04041 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) { 04042 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04043 /* Swap subs and dis-own channel */ 04044 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04045 p->owner = NULL; 04046 /* Ring the phone */ 04047 dahdi_ring_phone(p); 04048 } else { 04049 if ((res = attempt_transfer(p)) < 0) { 04050 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04051 if (p->subs[SUB_THREEWAY].owner) 04052 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04053 } else if (res) { 04054 /* Don't actually hang up at this point */ 04055 if (p->subs[SUB_THREEWAY].owner) 04056 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04057 break; 04058 } 04059 } 04060 } else { 04061 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04062 if (p->subs[SUB_THREEWAY].owner) 04063 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04064 } 04065 } else { 04066 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock); 04067 /* Swap subs and dis-own channel */ 04068 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04069 p->owner = NULL; 04070 /* Ring the phone */ 04071 dahdi_ring_phone(p); 04072 } 04073 } 04074 } else { 04075 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index); 04076 } 04077 /* Fall through */ 04078 default: 04079 dahdi_disable_ec(p); 04080 return NULL; 04081 } 04082 break; 04083 case DAHDI_EVENT_RINGOFFHOOK: 04084 if (p->inalarm) break; 04085 if (p->oprmode < 0) 04086 { 04087 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS)) 04088 { 04089 /* Make sure it stops ringing */ 04090 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04091 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1); 04092 restore_conference(p->oprpeer); 04093 } 04094 break; 04095 } 04096 if (p->radio) 04097 { 04098 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04099 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 04100 break; 04101 } 04102 /* for E911, its supposed to wait for offhook then dial 04103 the second half of the dial string */ 04104 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) { 04105 c = strchr(p->dialdest, '/'); 04106 if (c) 04107 c++; 04108 else 04109 c = p->dialdest; 04110 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c); 04111 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr)); 04112 if (strlen(p->dop.dialstr) > 4) { 04113 memset(p->echorest, 'w', sizeof(p->echorest) - 1); 04114 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2); 04115 p->echorest[sizeof(p->echorest) - 1] = '\0'; 04116 p->echobreak = 1; 04117 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0'; 04118 } else 04119 p->echobreak = 0; 04120 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) { 04121 int saveerr = errno; 04122 04123 x = DAHDI_ONHOOK; 04124 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 04125 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr)); 04126 return NULL; 04127 } 04128 p->dialing = 1; 04129 return &p->subs[index].f; 04130 } 04131 switch (p->sig) { 04132 case SIG_FXOLS: 04133 case SIG_FXOGS: 04134 case SIG_FXOKS: 04135 switch (ast->_state) { 04136 case AST_STATE_RINGING: 04137 dahdi_enable_ec(p); 04138 dahdi_train_ec(p); 04139 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04140 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04141 /* Make sure it stops ringing */ 04142 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04143 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel); 04144 if (p->cidspill) { 04145 /* Cancel any running CallerID spill */ 04146 free(p->cidspill); 04147 p->cidspill = NULL; 04148 } 04149 p->dialing = 0; 04150 p->callwaitcas = 0; 04151 if (p->confirmanswer) { 04152 /* Ignore answer if "confirm answer" is enabled */ 04153 p->subs[index].f.frametype = AST_FRAME_NULL; 04154 p->subs[index].f.subclass = 0; 04155 } else if (!ast_strlen_zero(p->dop.dialstr)) { 04156 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */ 04157 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04158 if (res < 0) { 04159 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04160 p->dop.dialstr[0] = '\0'; 04161 return NULL; 04162 } else { 04163 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr); 04164 p->subs[index].f.frametype = AST_FRAME_NULL; 04165 p->subs[index].f.subclass = 0; 04166 p->dialing = 1; 04167 } 04168 p->dop.dialstr[0] = '\0'; 04169 ast_setstate(ast, AST_STATE_DIALING); 04170 } else 04171 ast_setstate(ast, AST_STATE_UP); 04172 return &p->subs[index].f; 04173 case AST_STATE_DOWN: 04174 ast_setstate(ast, AST_STATE_RING); 04175 ast->rings = 1; 04176 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04177 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK; 04178 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel); 04179 return &p->subs[index].f; 04180 case AST_STATE_UP: 04181 /* Make sure it stops ringing */ 04182 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 04183 /* Okay -- probably call waiting*/ 04184 if (ast_bridged_channel(p->owner)) 04185 ast_queue_control(p->owner, AST_CONTROL_UNHOLD); 04186 p->subs[index].needunhold = 1; 04187 break; 04188 case AST_STATE_RESERVED: 04189 /* Start up dialtone */ 04190 if (has_voicemail(p)) 04191 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 04192 else 04193 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 04194 break; 04195 default: 04196 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state); 04197 } 04198 break; 04199 case SIG_FXSLS: 04200 case SIG_FXSGS: 04201 case SIG_FXSKS: 04202 if (ast->_state == AST_STATE_RING) { 04203 p->ringt = p->ringt_base; 04204 } 04205 04206 /* Fall through */ 04207 case SIG_EM: 04208 case SIG_EM_E1: 04209 case SIG_EMWINK: 04210 case SIG_FEATD: 04211 case SIG_FEATDMF: 04212 case SIG_FEATDMF_TA: 04213 case SIG_E911: 04214 case SIG_FGC_CAMA: 04215 case SIG_FGC_CAMAMF: 04216 case SIG_FEATB: 04217 case SIG_SF: 04218 case SIG_SFWINK: 04219 case SIG_SF_FEATD: 04220 case SIG_SF_FEATDMF: 04221 case SIG_SF_FEATB: 04222 if (ast->_state == AST_STATE_PRERING) 04223 ast_setstate(ast, AST_STATE_RING); 04224 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) { 04225 if (option_debug) 04226 ast_log(LOG_DEBUG, "Ring detected\n"); 04227 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04228 p->subs[index].f.subclass = AST_CONTROL_RING; 04229 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) { 04230 if (option_debug) 04231 ast_log(LOG_DEBUG, "Line answered\n"); 04232 if (p->confirmanswer) { 04233 p->subs[index].f.frametype = AST_FRAME_NULL; 04234 p->subs[index].f.subclass = 0; 04235 } else { 04236 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04237 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04238 ast_setstate(ast, AST_STATE_UP); 04239 } 04240 } else if (ast->_state != AST_STATE_RING) 04241 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel); 04242 break; 04243 default: 04244 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig); 04245 } 04246 break; 04247 #ifdef DAHDI_EVENT_RINGBEGIN 04248 case DAHDI_EVENT_RINGBEGIN: 04249 switch (p->sig) { 04250 case SIG_FXSLS: 04251 case SIG_FXSGS: 04252 case SIG_FXSKS: 04253 if (ast->_state == AST_STATE_RING) { 04254 p->ringt = p->ringt_base; 04255 } 04256 break; 04257 } 04258 break; 04259 #endif 04260 case DAHDI_EVENT_RINGEROFF: 04261 if (p->inalarm) break; 04262 if ((p->radio || (p->oprmode < 0))) break; 04263 ast->rings++; 04264 if ((ast->rings > p->cidrings) && (p->cidspill)) { 04265 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n"); 04266 free(p->cidspill); 04267 p->cidspill = NULL; 04268 p->callwaitcas = 0; 04269 } 04270 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04271 p->subs[index].f.subclass = AST_CONTROL_RINGING; 04272 break; 04273 case DAHDI_EVENT_RINGERON: 04274 break; 04275 case DAHDI_EVENT_NOALARM: 04276 p->inalarm = 0; 04277 #ifdef HAVE_PRI 04278 /* Extremely unlikely but just in case */ 04279 if (p->bearer) 04280 p->bearer->inalarm = 0; 04281 #endif 04282 if (!p->unknown_alarm) { 04283 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel); 04284 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 04285 "Channel: %d\r\n", p->channel); 04286 } else { 04287 p->unknown_alarm = 0; 04288 } 04289 break; 04290 case DAHDI_EVENT_WINKFLASH: 04291 if (p->inalarm) break; 04292 if (p->radio) break; 04293 if (p->oprmode < 0) break; 04294 if (p->oprmode > 1) 04295 { 04296 struct dahdi_params par; 04297 04298 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1) 04299 { 04300 if (!par.rxisoffhook) 04301 { 04302 /* Make sure it stops ringing */ 04303 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF); 04304 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING); 04305 save_conference(p); 04306 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04307 } 04308 } 04309 break; 04310 } 04311 /* Remember last time we got a flash-hook */ 04312 gettimeofday(&p->flashtime, NULL); 04313 switch (mysig) { 04314 case SIG_FXOLS: 04315 case SIG_FXOGS: 04316 case SIG_FXOKS: 04317 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", 04318 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 04319 p->callwaitcas = 0; 04320 04321 if (index != SUB_REAL) { 04322 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel); 04323 goto winkflashdone; 04324 } 04325 04326 if (p->subs[SUB_CALLWAIT].owner) { 04327 /* Swap to call-wait */ 04328 swap_subs(p, SUB_REAL, SUB_CALLWAIT); 04329 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 04330 p->owner = p->subs[SUB_REAL].owner; 04331 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name); 04332 if (p->owner->_state == AST_STATE_RINGING) { 04333 ast_setstate(p->owner, AST_STATE_UP); 04334 p->subs[SUB_REAL].needanswer = 1; 04335 } 04336 p->callwaitingrepeat = 0; 04337 p->cidcwexpire = 0; 04338 /* Start music on hold if appropriate */ 04339 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 04340 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 04341 S_OR(p->mohsuggest, NULL), 04342 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04343 } 04344 p->subs[SUB_CALLWAIT].needhold = 1; 04345 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { 04346 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, 04347 S_OR(p->mohsuggest, NULL), 04348 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04349 } 04350 p->subs[SUB_REAL].needunhold = 1; 04351 } else if (!p->subs[SUB_THREEWAY].owner) { 04352 char cid_num[256]; 04353 char cid_name[256]; 04354 04355 if (!p->threewaycalling) { 04356 /* Just send a flash if no 3-way calling */ 04357 p->subs[SUB_REAL].needflash = 1; 04358 goto winkflashdone; 04359 } else if (!check_for_conference(p)) { 04360 if (p->dahditrcallerid && p->owner) { 04361 if (p->owner->cid.cid_num) 04362 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num)); 04363 if (p->owner->cid.cid_name) 04364 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name)); 04365 } 04366 /* XXX This section needs much more error checking!!! XXX */ 04367 /* Start a 3-way call if feasible */ 04368 if (!((ast->pbx) || 04369 (ast->_state == AST_STATE_UP) || 04370 (ast->_state == AST_STATE_RING))) { 04371 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n"); 04372 goto winkflashdone; 04373 } 04374 if (alloc_sub(p, SUB_THREEWAY)) { 04375 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n"); 04376 goto winkflashdone; 04377 } 04378 /* Make new channel */ 04379 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0); 04380 if (p->dahditrcallerid) { 04381 if (!p->origcid_num) 04382 p->origcid_num = ast_strdup(p->cid_num); 04383 if (!p->origcid_name) 04384 p->origcid_name = ast_strdup(p->cid_name); 04385 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num)); 04386 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name)); 04387 } 04388 /* Swap things around between the three-way and real call */ 04389 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04390 /* Disable echo canceller for better dialing */ 04391 dahdi_disable_ec(p); 04392 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL); 04393 if (res) 04394 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); 04395 p->owner = chan; 04396 pthread_attr_init(&attr); 04397 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 04398 if (!chan) { 04399 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel); 04400 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 04401 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); 04402 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 04403 dahdi_enable_ec(p); 04404 ast_hangup(chan); 04405 } else { 04406 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 04407 int way3bridge = 0, cdr3way = 0; 04408 04409 if (!other) { 04410 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 04411 } else 04412 way3bridge = 1; 04413 04414 if (p->subs[SUB_THREEWAY].owner->cdr) 04415 cdr3way = 1; 04416 04417 if (option_verbose > 2) 04418 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel); 04419 /* Start music on hold if appropriate */ 04420 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 04421 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 04422 S_OR(p->mohsuggest, NULL), 04423 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 04424 } 04425 p->subs[SUB_THREEWAY].needhold = 1; 04426 } 04427 pthread_attr_destroy(&attr); 04428 } 04429 } else { 04430 /* Already have a 3 way call */ 04431 if (p->subs[SUB_THREEWAY].inthreeway) { 04432 /* Call is already up, drop the last person */ 04433 if (option_debug) 04434 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel); 04435 /* If the primary call isn't answered yet, use it */ 04436 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) { 04437 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ 04438 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04439 p->owner = p->subs[SUB_REAL].owner; 04440 } 04441 /* Drop the last call and stop the conference */ 04442 if (option_verbose > 2) 04443 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name); 04444 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04445 p->subs[SUB_REAL].inthreeway = 0; 04446 p->subs[SUB_THREEWAY].inthreeway = 0; 04447 } else { 04448 /* Lets see what we're up to */ 04449 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 04450 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { 04451 int otherindex = SUB_THREEWAY; 04452 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner); 04453 int way3bridge = 0, cdr3way = 0; 04454 04455 if (!other) { 04456 other = ast_bridged_channel(p->subs[SUB_REAL].owner); 04457 } else 04458 way3bridge = 1; 04459 04460 if (p->subs[SUB_THREEWAY].owner->cdr) 04461 cdr3way = 1; 04462 04463 if (option_verbose > 2) 04464 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name); 04465 /* Put them in the threeway, and flip */ 04466 p->subs[SUB_THREEWAY].inthreeway = 1; 04467 p->subs[SUB_REAL].inthreeway = 1; 04468 if (ast->_state == AST_STATE_UP) { 04469 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04470 otherindex = SUB_REAL; 04471 } 04472 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) 04473 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); 04474 p->subs[otherindex].needunhold = 1; 04475 p->owner = p->subs[SUB_REAL].owner; 04476 if (ast->_state == AST_STATE_RINGING) { 04477 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); 04478 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 04479 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE); 04480 } 04481 } else { 04482 if (option_verbose > 2) 04483 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name); 04484 swap_subs(p, SUB_THREEWAY, SUB_REAL); 04485 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV; 04486 p->owner = p->subs[SUB_REAL].owner; 04487 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) 04488 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 04489 p->subs[SUB_REAL].needunhold = 1; 04490 dahdi_enable_ec(p); 04491 } 04492 04493 } 04494 } 04495 winkflashdone: 04496 update_conf(p); 04497 break; 04498 case SIG_EM: 04499 case SIG_EM_E1: 04500 case SIG_EMWINK: 04501 case SIG_FEATD: 04502 case SIG_SF: 04503 case SIG_SFWINK: 04504 case SIG_SF_FEATD: 04505 case SIG_FXSLS: 04506 case SIG_FXSGS: 04507 if (p->dialing) 04508 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel); 04509 else 04510 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel); 04511 break; 04512 case SIG_FEATDMF_TA: 04513 switch (p->whichwink) { 04514 case 0: 04515 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 04516 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani); 04517 break; 04518 case 1: 04519 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr)); 04520 break; 04521 case 2: 04522 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n"); 04523 return NULL; 04524 } 04525 p->whichwink++; 04526 /* Fall through */ 04527 case SIG_FEATDMF: 04528 case SIG_E911: 04529 case SIG_FGC_CAMAMF: 04530 case SIG_FGC_CAMA: 04531 case SIG_FEATB: 04532 case SIG_SF_FEATDMF: 04533 case SIG_SF_FEATB: 04534 /* FGD MF *Must* wait for wink */ 04535 if (!ast_strlen_zero(p->dop.dialstr)) { 04536 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04537 if (res < 0) { 04538 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04539 p->dop.dialstr[0] = '\0'; 04540 return NULL; 04541 } else 04542 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 04543 } 04544 p->dop.dialstr[0] = '\0'; 04545 break; 04546 default: 04547 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig); 04548 } 04549 break; 04550 case DAHDI_EVENT_HOOKCOMPLETE: 04551 if (p->inalarm) break; 04552 if ((p->radio || (p->oprmode < 0))) break; 04553 switch (mysig) { 04554 case SIG_FXSLS: /* only interesting for FXS */ 04555 case SIG_FXSGS: 04556 case SIG_FXSKS: 04557 case SIG_EM: 04558 case SIG_EM_E1: 04559 case SIG_EMWINK: 04560 case SIG_FEATD: 04561 case SIG_SF: 04562 case SIG_SFWINK: 04563 case SIG_SF_FEATD: 04564 if (!ast_strlen_zero(p->dop.dialstr)) { 04565 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop); 04566 if (res < 0) { 04567 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno)); 04568 p->dop.dialstr[0] = '\0'; 04569 return NULL; 04570 } else 04571 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr); 04572 } 04573 p->dop.dialstr[0] = '\0'; 04574 p->dop.op = DAHDI_DIAL_OP_REPLACE; 04575 break; 04576 case SIG_FEATDMF: 04577 case SIG_FEATDMF_TA: 04578 case SIG_E911: 04579 case SIG_FGC_CAMA: 04580 case SIG_FGC_CAMAMF: 04581 case SIG_FEATB: 04582 case SIG_SF_FEATDMF: 04583 case SIG_SF_FEATB: 04584 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel); 04585 break; 04586 default: 04587 break; 04588 } 04589 break; 04590 case DAHDI_EVENT_POLARITY: 04591 /* 04592 * If we get a Polarity Switch event, check to see 04593 * if we should change the polarity state and 04594 * mark the channel as UP or if this is an indication 04595 * of remote end disconnect. 04596 */ 04597 if (p->polarity == POLARITY_IDLE) { 04598 p->polarity = POLARITY_REV; 04599 if (p->answeronpolarityswitch && 04600 ((ast->_state == AST_STATE_DIALING) || 04601 (ast->_state == AST_STATE_RINGING))) { 04602 ast_log(LOG_DEBUG, "Answering on polarity switch!\n"); 04603 ast_setstate(p->owner, AST_STATE_UP); 04604 if (p->hanguponpolarityswitch) { 04605 gettimeofday(&p->polaritydelaytv, NULL); 04606 } 04607 } else 04608 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state); 04609 } 04610 /* Removed else statement from here as it was preventing hangups from ever happening*/ 04611 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */ 04612 if (p->hanguponpolarityswitch && 04613 (p->polarityonanswerdelay > 0) && 04614 (p->polarity == POLARITY_REV) && 04615 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) { 04616 /* Added log_debug information below to provide a better indication of what is going on */ 04617 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: 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) ); 04618 04619 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) { 04620 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel); 04621 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 04622 p->polarity = POLARITY_IDLE; 04623 } else { 04624 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state); 04625 } 04626 } else { 04627 p->polarity = POLARITY_IDLE; 04628 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state); 04629 } 04630 /* Added more log_debug information below to provide a better indication of what is going on */ 04631 ast_log(LOG_DEBUG, "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) ); 04632 break; 04633 default: 04634 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel); 04635 } 04636 return &p->subs[index].f; 04637 }
static int dahdi_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 2513 of file chan_dahdi.c.
References ast_channel::_state, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_dsp_digitmode(), ast_dsp_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_verbose(), dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, free, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mohsuggest, 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, option_debug, option_verbose, 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_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::rdnis, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, S_OR, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and VERBOSE_PREFIX_3.
02514 { 02515 int res; 02516 int index,x, law; 02517 /*static int restore_gains(struct dahdi_pvt *p);*/ 02518 struct dahdi_pvt *p = ast->tech_pvt; 02519 struct dahdi_pvt *tmp = NULL; 02520 struct dahdi_pvt *prev = NULL; 02521 struct dahdi_params par; 02522 02523 if (option_debug) 02524 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name); 02525 if (!ast->tech_pvt) { 02526 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 02527 return 0; 02528 } 02529 02530 ast_mutex_lock(&p->lock); 02531 02532 index = dahdi_get_index(ast, p, 1); 02533 02534 if (p->sig == SIG_PRI) { 02535 x = 1; 02536 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 02537 } 02538 02539 x = 0; 02540 dahdi_confmute(p, 0); 02541 restore_gains(p); 02542 if (p->origcid_num) { 02543 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num)); 02544 free(p->origcid_num); 02545 p->origcid_num = NULL; 02546 } 02547 if (p->origcid_name) { 02548 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name)); 02549 free(p->origcid_name); 02550 p->origcid_name = NULL; 02551 } 02552 if (p->dsp) 02553 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 02554 if (p->exten) 02555 p->exten[0] = '\0'; 02556 02557 if (option_debug) 02558 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n", 02559 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd); 02560 p->ignoredtmf = 0; 02561 02562 if (index > -1) { 02563 /* Real channel, do some fixup */ 02564 p->subs[index].owner = NULL; 02565 p->subs[index].needanswer = 0; 02566 p->subs[index].needflash = 0; 02567 p->subs[index].needringing = 0; 02568 p->subs[index].needbusy = 0; 02569 p->subs[index].needcongestion = 0; 02570 p->subs[index].linear = 0; 02571 p->subs[index].needcallerid = 0; 02572 p->polarity = POLARITY_IDLE; 02573 dahdi_setlinear(p->subs[index].dfd, 0); 02574 if (index == SUB_REAL) { 02575 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) { 02576 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n"); 02577 if (p->subs[SUB_CALLWAIT].inthreeway) { 02578 /* We had flipped over to answer a callwait and now it's gone */ 02579 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n"); 02580 /* Move to the call-wait, but un-own us until they flip back. */ 02581 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02582 unalloc_sub(p, SUB_CALLWAIT); 02583 p->owner = NULL; 02584 } else { 02585 /* The three way hung up, but we still have a call wait */ 02586 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); 02587 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02588 unalloc_sub(p, SUB_THREEWAY); 02589 if (p->subs[SUB_REAL].inthreeway) { 02590 /* This was part of a three way call. Immediately make way for 02591 another call */ 02592 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02593 p->owner = p->subs[SUB_REAL].owner; 02594 } else { 02595 /* This call hasn't been completed yet... Set owner to NULL */ 02596 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02597 p->owner = NULL; 02598 } 02599 p->subs[SUB_REAL].inthreeway = 0; 02600 } 02601 } else if (p->subs[SUB_CALLWAIT].dfd > -1) { 02602 /* Move to the call-wait and switch back to them. */ 02603 swap_subs(p, SUB_CALLWAIT, SUB_REAL); 02604 unalloc_sub(p, SUB_CALLWAIT); 02605 p->owner = p->subs[SUB_REAL].owner; 02606 if (p->owner->_state != AST_STATE_UP) 02607 p->subs[SUB_REAL].needanswer = 1; 02608 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 02609 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 02610 } else if (p->subs[SUB_THREEWAY].dfd > -1) { 02611 swap_subs(p, SUB_THREEWAY, SUB_REAL); 02612 unalloc_sub(p, SUB_THREEWAY); 02613 if (p->subs[SUB_REAL].inthreeway) { 02614 /* This was part of a three way call. Immediately make way for 02615 another call */ 02616 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n"); 02617 p->owner = p->subs[SUB_REAL].owner; 02618 } else { 02619 /* This call hasn't been completed yet... Set owner to NULL */ 02620 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n"); 02621 p->owner = NULL; 02622 } 02623 p->subs[SUB_REAL].inthreeway = 0; 02624 } 02625 } else if (index == SUB_CALLWAIT) { 02626 /* Ditch the holding callwait call, and immediately make it availabe */ 02627 if (p->subs[SUB_CALLWAIT].inthreeway) { 02628 /* This is actually part of a three way, placed on hold. Place the third part 02629 on music on hold now */ 02630 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 02631 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 02632 S_OR(p->mohsuggest, NULL), 02633 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02634 } 02635 p->subs[SUB_THREEWAY].inthreeway = 0; 02636 /* Make it the call wait now */ 02637 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 02638 unalloc_sub(p, SUB_THREEWAY); 02639 } else 02640 unalloc_sub(p, SUB_CALLWAIT); 02641 } else if (index == SUB_THREEWAY) { 02642 if (p->subs[SUB_CALLWAIT].inthreeway) { 02643 /* The other party of the three way call is currently in a call-wait state. 02644 Start music on hold for them, and take the main guy out of the third call */ 02645 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) { 02646 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 02647 S_OR(p->mohsuggest, NULL), 02648 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); 02649 } 02650 p->subs[SUB_CALLWAIT].inthreeway = 0; 02651 } 02652 p->subs[SUB_REAL].inthreeway = 0; 02653 /* If this was part of a three way call index, let us make 02654 another three way call */ 02655 unalloc_sub(p, SUB_THREEWAY); 02656 } else { 02657 /* This wasn't any sort of call, but how are we an index? */ 02658 ast_log(LOG_WARNING, "Index found but not any type of call?\n"); 02659 } 02660 } 02661 02662 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) { 02663 p->owner = NULL; 02664 p->ringt = 0; 02665 p->distinctivering = 0; 02666 p->confirmanswer = 0; 02667 p->cidrings = 1; 02668 p->outgoing = 0; 02669 p->digital = 0; 02670 p->faxhandled = 0; 02671 p->pulsedial = 0; 02672 p->onhooktime = time(NULL); 02673 #ifdef HAVE_PRI 02674 p->proceeding = 0; 02675 p->progress = 0; 02676 p->alerting = 0; 02677 p->setup_ack = 0; 02678 #endif 02679 if (p->dsp) { 02680 ast_dsp_free(p->dsp); 02681 p->dsp = NULL; 02682 } 02683 02684 law = DAHDI_LAW_DEFAULT; 02685 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law); 02686 if (res < 0) 02687 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno)); 02688 /* Perform low level hangup if no owner left */ 02689 #ifdef HAVE_PRI 02690 if (p->pri) { 02691 #ifdef SUPPORT_USERUSER 02692 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO"); 02693 #endif 02694 02695 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */ 02696 if (p->call && (!p->bearer || (p->bearer->call == p->call))) { 02697 if (!pri_grab(p, p->pri)) { 02698 if (p->alreadyhungup) { 02699 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n"); 02700 02701 #ifdef SUPPORT_USERUSER 02702 pri_call_set_useruser(p->call, useruser); 02703 #endif 02704 02705 pri_hangup(p->pri->pri, p->call, -1); 02706 p->call = NULL; 02707 if (p->bearer) 02708 p->bearer->call = NULL; 02709 } else { 02710 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE"); 02711 int icause = ast->hangupcause ? ast->hangupcause : -1; 02712 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n"); 02713 02714 #ifdef SUPPORT_USERUSER 02715 pri_call_set_useruser(p->call, useruser); 02716 #endif 02717 02718 p->alreadyhungup = 1; 02719 if (p->bearer) 02720 p->bearer->alreadyhungup = 1; 02721 if (cause) { 02722 if (atoi(cause)) 02723 icause = atoi(cause); 02724 } 02725 pri_hangup(p->pri->pri, p->call, icause); 02726 } 02727 if (res < 0) 02728 ast_log(LOG_WARNING, "pri_disconnect failed\n"); 02729 pri_rel(p->pri); 02730 } else { 02731 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 02732 res = -1; 02733 } 02734 } else { 02735 if (p->bearer) 02736 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call); 02737 p->call = NULL; 02738 res = 0; 02739 } 02740 } 02741 #endif 02742 if (p->sig && (p->sig != SIG_PRI)) 02743 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 02744 if (res < 0) { 02745 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name); 02746 } 02747 switch (p->sig) { 02748 case SIG_FXOGS: 02749 case SIG_FXOLS: 02750 case SIG_FXOKS: 02751 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); 02752 if (!res) { 02753 #if 0 02754 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); 02755 #endif 02756 /* If they're off hook, try playing congestion */ 02757 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0)))) 02758 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 02759 else 02760 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 02761 } 02762 break; 02763 case SIG_FXSGS: 02764 case SIG_FXSLS: 02765 case SIG_FXSKS: 02766 /* Make sure we're not made available for at least two seconds assuming 02767 we were actually used for an inbound or outbound call. */ 02768 if (ast->_state != AST_STATE_RESERVED) { 02769 time(&p->guardtime); 02770 p->guardtime += 2; 02771 } 02772 break; 02773 default: 02774 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); 02775 } 02776 if (p->cidspill) 02777 free(p->cidspill); 02778 if (p->sig) 02779 dahdi_disable_ec(p); 02780 x = 0; 02781 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); 02782 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0); 02783 p->didtdd = 0; 02784 p->cidspill = NULL; 02785 p->callwaitcas = 0; 02786 p->callwaiting = p->permcallwaiting; 02787 p->hidecallerid = p->permhidecallerid; 02788 p->dialing = 0; 02789 p->rdnis[0] = '\0'; 02790 update_conf(p); 02791 reset_conf(p); 02792 /* Restore data mode */ 02793 if (p->sig == SIG_PRI) { 02794 x = 0; 02795 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0); 02796 } 02797 #ifdef HAVE_PRI 02798 if (p->bearer) { 02799 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel); 02800 /* Free up the bearer channel as well, and 02801 don't use its file descriptor anymore */ 02802 update_conf(p->bearer); 02803 reset_conf(p->bearer); 02804 p->bearer->owner = NULL; 02805 p->bearer->realcall = NULL; 02806 p->bearer = NULL; 02807 p->subs[SUB_REAL].dfd = -1; 02808 p->pri = NULL; 02809 } 02810 #endif 02811 if (num_restart_pending == 0) 02812 restart_monitor(); 02813 } 02814 02815 p->callwaitingrepeat = 0; 02816 p->cidcwexpire = 0; 02817 p->oprmode = 0; 02818 ast->tech_pvt = NULL; 02819 ast_mutex_unlock(&p->lock); 02820 ast_module_unref(ast_module_info->self); 02821 if (option_verbose > 2) 02822 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 02823 02824 ast_mutex_lock(&iflock); 02825 02826 if (p->restartpending) { 02827 num_restart_pending--; 02828 } 02829 02830 tmp = iflist; 02831 prev = NULL; 02832 if (p->destroy) { 02833 while (tmp) { 02834 if (tmp == p) { 02835 destroy_channel(prev, tmp, 0); 02836 break; 02837 } else { 02838 prev = tmp; 02839 tmp = tmp->next; 02840 } 02841 } 02842 } 02843 ast_mutex_unlock(&iflock); 02844 return 0; 02845 }
static int dahdi_indicate | ( | struct ast_channel * | chan, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 5153 of file chan_dahdi.c.
References ast_channel::_softhangup, ast_channel::_state, 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_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_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dop, errno, func, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mohinterpret, option_debug, dahdi_pvt::outgoing, dahdi_pvt::priindication_oob, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.
05154 { 05155 struct dahdi_pvt *p = chan->tech_pvt; 05156 int res=-1; 05157 int index; 05158 int func = DAHDI_FLASH; 05159 ast_mutex_lock(&p->lock); 05160 index = dahdi_get_index(chan, p, 0); 05161 if (option_debug) 05162 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name); 05163 if (index == SUB_REAL) { 05164 switch (condition) { 05165 case AST_CONTROL_BUSY: 05166 #ifdef HAVE_PRI 05167 if (p->priindication_oob && p->sig == SIG_PRI) { 05168 chan->hangupcause = AST_CAUSE_USER_BUSY; 05169 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05170 res = 0; 05171 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05172 if (p->pri->pri) { 05173 if (!pri_grab(p, p->pri)) { 05174 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05175 pri_rel(p->pri); 05176 } 05177 else 05178 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05179 } 05180 p->progress = 1; 05181 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05182 } else 05183 #endif 05184 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY); 05185 break; 05186 case AST_CONTROL_RINGING: 05187 #ifdef HAVE_PRI 05188 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) { 05189 if (p->pri->pri) { 05190 if (!pri_grab(p, p->pri)) { 05191 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05192 pri_rel(p->pri); 05193 } 05194 else 05195 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05196 } 05197 p->alerting = 1; 05198 } 05199 #endif 05200 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE); 05201 if (chan->_state != AST_STATE_UP) { 05202 if ((chan->_state != AST_STATE_RING) || 05203 ((p->sig != SIG_FXSKS) && 05204 (p->sig != SIG_FXSLS) && 05205 (p->sig != SIG_FXSGS))) 05206 ast_setstate(chan, AST_STATE_RINGING); 05207 } 05208 break; 05209 case AST_CONTROL_PROCEEDING: 05210 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name); 05211 #ifdef HAVE_PRI 05212 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05213 if (p->pri->pri) { 05214 if (!pri_grab(p, p->pri)) { 05215 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05216 pri_rel(p->pri); 05217 } 05218 else 05219 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05220 } 05221 p->proceeding = 1; 05222 } 05223 #endif 05224 /* don't continue in ast_indicate */ 05225 res = 0; 05226 break; 05227 case AST_CONTROL_PROGRESS: 05228 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name); 05229 #ifdef HAVE_PRI 05230 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */ 05231 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05232 if (p->pri->pri) { 05233 if (!pri_grab(p, p->pri)) { 05234 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05235 pri_rel(p->pri); 05236 } 05237 else 05238 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05239 } 05240 p->progress = 1; 05241 } 05242 #endif 05243 /* don't continue in ast_indicate */ 05244 res = 0; 05245 break; 05246 case AST_CONTROL_CONGESTION: 05247 chan->hangupcause = AST_CAUSE_CONGESTION; 05248 #ifdef HAVE_PRI 05249 if (p->priindication_oob && p->sig == SIG_PRI) { 05250 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION; 05251 chan->_softhangup |= AST_SOFTHANGUP_DEV; 05252 res = 0; 05253 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05254 if (p->pri) { 05255 if (!pri_grab(p, p->pri)) { 05256 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1); 05257 pri_rel(p->pri); 05258 } else 05259 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05260 } 05261 p->progress = 1; 05262 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05263 } else 05264 #endif 05265 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05266 break; 05267 case AST_CONTROL_HOLD: 05268 #ifdef HAVE_PRI 05269 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05270 if (!pri_grab(p, p->pri)) { 05271 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD); 05272 pri_rel(p->pri); 05273 } else 05274 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05275 } else 05276 #endif 05277 ast_moh_start(chan, data, p->mohinterpret); 05278 break; 05279 case AST_CONTROL_UNHOLD: 05280 #ifdef HAVE_PRI 05281 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) { 05282 if (!pri_grab(p, p->pri)) { 05283 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL); 05284 pri_rel(p->pri); 05285 } else 05286 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05287 } else 05288 #endif 05289 ast_moh_stop(chan); 05290 break; 05291 case AST_CONTROL_RADIO_KEY: 05292 if (p->radio) 05293 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK); 05294 res = 0; 05295 break; 05296 case AST_CONTROL_RADIO_UNKEY: 05297 if (p->radio) 05298 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF); 05299 res = 0; 05300 break; 05301 case AST_CONTROL_FLASH: 05302 /* flash hookswitch */ 05303 if (ISTRUNK(p) && (p->sig != SIG_PRI)) { 05304 /* Clear out the dial buffer */ 05305 p->dop.dialstr[0] = '\0'; 05306 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 05307 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 05308 chan->name, strerror(errno)); 05309 } else 05310 res = 0; 05311 } else 05312 res = 0; 05313 break; 05314 case AST_CONTROL_SRCUPDATE: 05315 res = 0; 05316 break; 05317 case -1: 05318 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05319 break; 05320 } 05321 } else 05322 res = 0; 05323 ast_mutex_unlock(&p->lock); 05324 return res; 05325 }
Definition at line 3192 of file chan_dahdi.c.
References ast_log(), LOG_WARNING, and master.
Referenced by dahdi_bridge().
03192 { 03193 int x; 03194 if (!slave || !master) { 03195 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n"); 03196 return; 03197 } 03198 for (x = 0; x < MAX_SLAVES; x++) { 03199 if (!master->slaves[x]) { 03200 master->slaves[x] = slave; 03201 break; 03202 } 03203 } 03204 if (x >= MAX_SLAVES) { 03205 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel); 03206 master->slaves[MAX_SLAVES - 1] = slave; 03207 } 03208 if (slave->master) 03209 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel); 03210 slave->master = master; 03211 03212 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x); 03213 }
static struct ast_channel * dahdi_new | ( | struct dahdi_pvt * | , | |
int | , | |||
int | , | |||
int | , | |||
int | , | |||
int | ||||
) | [static] |
Definition at line 5327 of file chan_dahdi.c.
References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, 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_chan_name, dahdi_chan_name_len, 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_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::fds, free, global_jbconf, dahdi_pvt::hardwaredtmf, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, ast_channel::nativeformats, NEED_MFDETECT, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, PRI_TRANS_CAP_DIGITAL, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, dahdi_pvt::silencethreshold, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, and ast_channel::writeformat.
Referenced by dahdi_handle_event(), dahdi_request(), and handle_init_event().
05328 { 05329 struct ast_channel *tmp; 05330 int deflaw; 05331 int res; 05332 int x,y; 05333 int features; 05334 char *b2 = NULL; 05335 struct dahdi_params ps; 05336 char chanprefix[*dahdi_chan_name_len + 4]; 05337 05338 if (i->subs[index].owner) { 05339 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]); 05340 return NULL; 05341 } 05342 y = 1; 05343 do { 05344 if (b2) 05345 free(b2); 05346 #ifdef HAVE_PRI 05347 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS))) 05348 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y); 05349 else 05350 #endif 05351 if (i->channel == CHAN_PSEUDO) 05352 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random()); 05353 else 05354 b2 = ast_safe_string_alloc("%d-%d", i->channel, y); 05355 for (x = 0; x < 3; x++) { 05356 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6))) 05357 break; 05358 } 05359 y++; 05360 } while (x < 3); 05361 strcpy(chanprefix, dahdi_chan_name); 05362 strcat(chanprefix, "/%s"); 05363 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2); 05364 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */ 05365 free(b2); 05366 if (!tmp) 05367 return NULL; 05368 tmp->tech = chan_tech; 05369 ps.channo = i->channel; 05370 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps); 05371 if (res) { 05372 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno)); 05373 ps.curlaw = DAHDI_LAW_MULAW; 05374 } 05375 if (ps.curlaw == DAHDI_LAW_ALAW) 05376 deflaw = AST_FORMAT_ALAW; 05377 else 05378 deflaw = AST_FORMAT_ULAW; 05379 if (law) { 05380 if (law == DAHDI_LAW_ALAW) 05381 deflaw = AST_FORMAT_ALAW; 05382 else 05383 deflaw = AST_FORMAT_ULAW; 05384 } 05385 tmp->fds[0] = i->subs[index].dfd; 05386 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw; 05387 /* Start out assuming ulaw since it's smaller :) */ 05388 tmp->rawreadformat = deflaw; 05389 tmp->readformat = deflaw; 05390 tmp->rawwriteformat = deflaw; 05391 tmp->writeformat = deflaw; 05392 i->subs[index].linear = 0; 05393 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear); 05394 features = 0; 05395 if (index == SUB_REAL) { 05396 if (i->busydetect && CANBUSYDETECT(i)) 05397 features |= DSP_FEATURE_BUSY_DETECT; 05398 if ((i->callprogress & 1) && CANPROGRESSDETECT(i)) 05399 features |= DSP_FEATURE_CALL_PROGRESS; 05400 if ((!i->outgoing && (i->callprogress & 4)) || 05401 (i->outgoing && (i->callprogress & 2))) { 05402 features |= DSP_FEATURE_FAX_DETECT; 05403 } 05404 #ifdef DAHDI_TONEDETECT 05405 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 05406 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) { 05407 #endif 05408 i->hardwaredtmf = 0; 05409 features |= DSP_FEATURE_DTMF_DETECT; 05410 #ifdef DAHDI_TONEDETECT 05411 } else if (NEED_MFDETECT(i)) { 05412 i->hardwaredtmf = 1; 05413 features |= DSP_FEATURE_DTMF_DETECT; 05414 } 05415 #endif 05416 } 05417 if (features) { 05418 if (i->dsp) { 05419 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name); 05420 } else { 05421 if (i->channel != CHAN_PSEUDO) 05422 i->dsp = ast_dsp_new(); 05423 else 05424 i->dsp = NULL; 05425 if (i->dsp) { 05426 i->dsp_features = features; 05427 #ifdef HAVE_PRI 05428 /* We cannot do progress detection until receives PROGRESS message */ 05429 if (i->outgoing && (i->sig == SIG_PRI)) { 05430 /* Remember requested DSP features, don't treat 05431 talking as ANSWER */ 05432 i->dsp_features = features & ~DSP_PROGRESS_TALK; 05433 features = 0; 05434 } 05435 #endif 05436 ast_dsp_set_features(i->dsp, features); 05437 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax); 05438 if (!ast_strlen_zero(progzone)) 05439 ast_dsp_set_call_progress_zone(i->dsp, progzone); 05440 if (i->busydetect && CANBUSYDETECT(i)) { 05441 if(i->silencethreshold > 0) 05442 ast_dsp_set_threshold(i->dsp, i->silencethreshold); 05443 ast_dsp_set_busy_count(i->dsp, i->busycount); 05444 if(i->busytonelength > 0) 05445 ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness); 05446 if((i->busytonelength == i->busyquietlength) && i->busycompare) 05447 ast_dsp_set_busy_compare(i->dsp, i->busycompare); 05448 } 05449 } 05450 } 05451 } 05452 05453 if (state == AST_STATE_RING) 05454 tmp->rings = 1; 05455 tmp->tech_pvt = i; 05456 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) { 05457 /* Only FXO signalled stuff can be picked up */ 05458 tmp->callgroup = i->callgroup; 05459 tmp->pickupgroup = i->pickupgroup; 05460 } 05461 if (!ast_strlen_zero(i->language)) 05462 ast_string_field_set(tmp, language, i->language); 05463 if (!i->owner) 05464 i->owner = tmp; 05465 if (!ast_strlen_zero(i->accountcode)) 05466 ast_string_field_set(tmp, accountcode, i->accountcode); 05467 if (i->amaflags) 05468 tmp->amaflags = i->amaflags; 05469 i->subs[index].owner = tmp; 05470 ast_copy_string(tmp->context, i->context, sizeof(tmp->context)); 05471 ast_string_field_set(tmp, call_forward, i->call_forward); 05472 /* If we've been told "no ADSI" then enforce it */ 05473 if (!i->adsi) 05474 tmp->adsicpe = AST_ADSI_UNAVAILABLE; 05475 if (!ast_strlen_zero(i->exten)) 05476 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten)); 05477 if (!ast_strlen_zero(i->rdnis)) 05478 tmp->cid.cid_rdnis = ast_strdup(i->rdnis); 05479 if (!ast_strlen_zero(i->dnid)) 05480 tmp->cid.cid_dnid = ast_strdup(i->dnid); 05481 05482 /* Don't use ast_set_callerid() here because it will 05483 * generate a needless NewCallerID event */ 05484 #ifdef PRI_ANI 05485 if (!ast_strlen_zero(i->cid_ani)) 05486 tmp->cid.cid_ani = ast_strdup(i->cid_ani); 05487 else 05488 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05489 #else 05490 tmp->cid.cid_ani = ast_strdup(i->cid_num); 05491 #endif 05492 tmp->cid.cid_pres = i->callingpres; 05493 tmp->cid.cid_ton = i->cid_ton; 05494 #ifdef HAVE_PRI 05495 tmp->transfercapability = transfercapability; 05496 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability)); 05497 if (transfercapability & PRI_TRANS_CAP_DIGITAL) 05498 i->digital = 1; 05499 /* Assume calls are not idle calls unless we're told differently */ 05500 i->isidlecall = 0; 05501 i->alreadyhungup = 0; 05502 #endif 05503 /* clear the fake event in case we posted one before we had ast_channel */ 05504 i->fake_event = 0; 05505 /* Assure there is no confmute on this channel */ 05506 dahdi_confmute(i, 0); 05507 /* Configure the new channel jb */ 05508 ast_jb_configure(tmp, &global_jbconf); 05509 if (startpbx) { 05510 if (ast_pbx_start(tmp)) { 05511 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 05512 ast_hangup(tmp); 05513 i->owner = NULL; 05514 return NULL; 05515 } 05516 } 05517 05518 ast_module_ref(ast_module_info->self); 05519 05520 return tmp; 05521 }
static int dahdi_open | ( | char * | fn | ) | [static] |
Definition at line 906 of file chan_dahdi.c.
References ast_log(), errno, LOG_WARNING, and READ_SIZE.
Referenced by alloc_sub(), chandup(), and mkintf().
00907 { 00908 int fd; 00909 int isnum; 00910 int chan = 0; 00911 int bs; 00912 int x; 00913 isnum = 1; 00914 for (x = 0; x < strlen(fn); x++) { 00915 if (!isdigit(fn[x])) { 00916 isnum = 0; 00917 break; 00918 } 00919 } 00920 if (isnum) { 00921 chan = atoi(fn); 00922 if (chan < 1) { 00923 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn); 00924 return -1; 00925 } 00926 #ifdef HAVE_ZAPTEL 00927 fn = "/dev/zap/channel"; 00928 #else 00929 fn = "/dev/dahdi/channel"; 00930 #endif 00931 } 00932 fd = open(fn, O_RDWR | O_NONBLOCK); 00933 if (fd < 0) { 00934 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno)); 00935 return -1; 00936 } 00937 if (chan) { 00938 if (ioctl(fd, DAHDI_SPECIFY, &chan)) { 00939 x = errno; 00940 close(fd); 00941 errno = x; 00942 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno)); 00943 return -1; 00944 } 00945 } 00946 bs = READ_SIZE; 00947 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) { 00948 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno)); 00949 x = errno; 00950 close(fd); 00951 errno = x; 00952 return -1; 00953 } 00954 return fd; 00955 }
Definition at line 850 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, f, dahdi_pvt::lock, ast_channel::lock, and dahdi_pvt::owner.
Referenced by __action_dialoffhook().
00852 { 00853 /* We must unlock the PRI to avoid the possibility of a deadlock */ 00854 #ifdef HAVE_PRI 00855 if (pri) 00856 ast_mutex_unlock(&pri->lock); 00857 #endif 00858 for (;;) { 00859 if (p->owner) { 00860 if (ast_mutex_trylock(&p->owner->lock)) { 00861 DEADLOCK_AVOIDANCE(&p->lock); 00862 } else { 00863 ast_queue_frame(p->owner, f); 00864 ast_mutex_unlock(&p->owner->lock); 00865 break; 00866 } 00867 } else 00868 break; 00869 } 00870 #ifdef HAVE_PRI 00871 if (pri) 00872 ast_mutex_lock(&pri->lock); 00873 #endif 00874 }
static struct ast_frame * dahdi_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 4757 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_dsp_process(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_verbose(), dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, errno, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, ast_frame::mallocd, 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, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::overlapdial, dahdi_pvt::owner, 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_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
04758 { 04759 struct dahdi_pvt *p = ast->tech_pvt; 04760 int res; 04761 int index; 04762 void *readbuf; 04763 struct ast_frame *f; 04764 04765 while (ast_mutex_trylock(&p->lock)) { 04766 DEADLOCK_AVOIDANCE(&ast->lock); 04767 } 04768 04769 index = dahdi_get_index(ast, p, 0); 04770 04771 /* Hang up if we don't really exist */ 04772 if (index < 0) { 04773 ast_log(LOG_WARNING, "We dont exist?\n"); 04774 ast_mutex_unlock(&p->lock); 04775 return NULL; 04776 } 04777 04778 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL; 04779 04780 p->subs[index].f.frametype = AST_FRAME_NULL; 04781 p->subs[index].f.datalen = 0; 04782 p->subs[index].f.samples = 0; 04783 p->subs[index].f.mallocd = 0; 04784 p->subs[index].f.offset = 0; 04785 p->subs[index].f.subclass = 0; 04786 p->subs[index].f.delivery = ast_tv(0,0); 04787 p->subs[index].f.src = "dahdi_read"; 04788 p->subs[index].f.data = NULL; 04789 04790 /* make sure it sends initial key state as first frame */ 04791 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio)) 04792 { 04793 struct dahdi_params ps; 04794 04795 ps.channo = p->channel; 04796 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 04797 ast_mutex_unlock(&p->lock); 04798 return NULL; 04799 } 04800 p->firstradio = 1; 04801 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04802 if (ps.rxisoffhook) 04803 { 04804 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY; 04805 } 04806 else 04807 { 04808 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY; 04809 } 04810 ast_mutex_unlock(&p->lock); 04811 return &p->subs[index].f; 04812 } 04813 if (p->ringt == 1) { 04814 ast_mutex_unlock(&p->lock); 04815 return NULL; 04816 } 04817 else if (p->ringt > 0) 04818 p->ringt--; 04819 04820 if (p->subs[index].needringing) { 04821 /* Send ringing frame if requested */ 04822 p->subs[index].needringing = 0; 04823 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04824 p->subs[index].f.subclass = AST_CONTROL_RINGING; 04825 ast_setstate(ast, AST_STATE_RINGING); 04826 ast_mutex_unlock(&p->lock); 04827 return &p->subs[index].f; 04828 } 04829 04830 if (p->subs[index].needbusy) { 04831 /* Send busy frame if requested */ 04832 p->subs[index].needbusy = 0; 04833 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04834 p->subs[index].f.subclass = AST_CONTROL_BUSY; 04835 ast_mutex_unlock(&p->lock); 04836 return &p->subs[index].f; 04837 } 04838 04839 if (p->subs[index].needcongestion) { 04840 /* Send congestion frame if requested */ 04841 p->subs[index].needcongestion = 0; 04842 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04843 p->subs[index].f.subclass = AST_CONTROL_CONGESTION; 04844 ast_mutex_unlock(&p->lock); 04845 return &p->subs[index].f; 04846 } 04847 04848 if (p->subs[index].needcallerid) { 04849 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL), 04850 S_OR(p->lastcid_name, NULL), 04851 S_OR(p->lastcid_num, NULL) 04852 ); 04853 p->subs[index].needcallerid = 0; 04854 } 04855 04856 if (p->subs[index].needanswer) { 04857 /* Send answer frame if requested */ 04858 p->subs[index].needanswer = 0; 04859 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04860 p->subs[index].f.subclass = AST_CONTROL_ANSWER; 04861 ast_mutex_unlock(&p->lock); 04862 return &p->subs[index].f; 04863 } 04864 04865 if (p->subs[index].needflash) { 04866 /* Send answer frame if requested */ 04867 p->subs[index].needflash = 0; 04868 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04869 p->subs[index].f.subclass = AST_CONTROL_FLASH; 04870 ast_mutex_unlock(&p->lock); 04871 return &p->subs[index].f; 04872 } 04873 04874 if (p->subs[index].needhold) { 04875 /* Send answer frame if requested */ 04876 p->subs[index].needhold = 0; 04877 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04878 p->subs[index].f.subclass = AST_CONTROL_HOLD; 04879 ast_mutex_unlock(&p->lock); 04880 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name); 04881 return &p->subs[index].f; 04882 } 04883 04884 if (p->subs[index].needunhold) { 04885 /* Send answer frame if requested */ 04886 p->subs[index].needunhold = 0; 04887 p->subs[index].f.frametype = AST_FRAME_CONTROL; 04888 p->subs[index].f.subclass = AST_CONTROL_UNHOLD; 04889 ast_mutex_unlock(&p->lock); 04890 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name); 04891 return &p->subs[index].f; 04892 } 04893 04894 if (ast->rawreadformat == AST_FORMAT_SLINEAR) { 04895 if (!p->subs[index].linear) { 04896 p->subs[index].linear = 1; 04897 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 04898 if (res) 04899 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index); 04900 } 04901 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) || 04902 (ast->rawreadformat == AST_FORMAT_ALAW)) { 04903 if (p->subs[index].linear) { 04904 p->subs[index].linear = 0; 04905 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 04906 if (res) 04907 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index); 04908 } 04909 } else { 04910 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat)); 04911 ast_mutex_unlock(&p->lock); 04912 return NULL; 04913 } 04914 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET; 04915 CHECK_BLOCKING(ast); 04916 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 04917 ast_clear_flag(ast, AST_FLAG_BLOCKING); 04918 /* Check for hangup */ 04919 if (res < 0) { 04920 f = NULL; 04921 if (res == -1) { 04922 if (errno == EAGAIN) { 04923 /* Return "NULL" frame if there is nobody there */ 04924 ast_mutex_unlock(&p->lock); 04925 return &p->subs[index].f; 04926 } else if (errno == ELAST) { 04927 f = __dahdi_exception(ast); 04928 } else 04929 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); 04930 } 04931 ast_mutex_unlock(&p->lock); 04932 return f; 04933 } 04934 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) { 04935 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE); 04936 f = __dahdi_exception(ast); 04937 ast_mutex_unlock(&p->lock); 04938 return f; 04939 } 04940 if (p->tdd) { /* if in TDD mode, see if we receive that */ 04941 int c; 04942 04943 c = tdd_feed(p->tdd,readbuf,READ_SIZE); 04944 if (c < 0) { 04945 ast_log(LOG_DEBUG,"tdd_feed failed\n"); 04946 ast_mutex_unlock(&p->lock); 04947 return NULL; 04948 } 04949 if (c) { /* if a char to return */ 04950 p->subs[index].f.subclass = 0; 04951 p->subs[index].f.frametype = AST_FRAME_TEXT; 04952 p->subs[index].f.mallocd = 0; 04953 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 04954 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET; 04955 p->subs[index].f.datalen = 1; 04956 *((char *) p->subs[index].f.data) = c; 04957 ast_mutex_unlock(&p->lock); 04958 return &p->subs[index].f; 04959 } 04960 } 04961 /* Ensure the CW timer decrements only on a single subchannel */ 04962 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) { 04963 p->callwaitingrepeat--; 04964 } 04965 if (p->cidcwexpire) 04966 p->cidcwexpire--; 04967 /* Repeat callwaiting */ 04968 if (p->callwaitingrepeat == 1) { 04969 p->callwaitrings++; 04970 dahdi_callwait(ast); 04971 } 04972 /* Expire CID/CW */ 04973 if (p->cidcwexpire == 1) { 04974 if (option_verbose > 2) 04975 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n"); 04976 restore_conference(p); 04977 } 04978 if (p->subs[index].linear) { 04979 p->subs[index].f.datalen = READ_SIZE * 2; 04980 } else 04981 p->subs[index].f.datalen = READ_SIZE; 04982 04983 /* Handle CallerID Transmission */ 04984 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) { 04985 send_callerid(p); 04986 } 04987 04988 p->subs[index].f.frametype = AST_FRAME_VOICE; 04989 p->subs[index].f.subclass = ast->rawreadformat; 04990 p->subs[index].f.samples = READ_SIZE; 04991 p->subs[index].f.mallocd = 0; 04992 p->subs[index].f.offset = AST_FRIENDLY_OFFSET; 04993 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]); 04994 #if 0 04995 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name); 04996 #endif 04997 if (p->dialing || /* Transmitting something */ 04998 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */ 04999 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */ 05000 ) { 05001 /* Whoops, we're still dialing, or in a state where we shouldn't transmit.... 05002 don't send anything */ 05003 p->subs[index].f.frametype = AST_FRAME_NULL; 05004 p->subs[index].f.subclass = 0; 05005 p->subs[index].f.samples = 0; 05006 p->subs[index].f.mallocd = 0; 05007 p->subs[index].f.offset = 0; 05008 p->subs[index].f.data = NULL; 05009 p->subs[index].f.datalen= 0; 05010 } 05011 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) { 05012 /* Perform busy detection. etc on the dahdi line */ 05013 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f); 05014 if (f) { 05015 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) { 05016 if ((ast->_state == AST_STATE_UP) && !p->outgoing) { 05017 /* Treat this as a "hangup" instead of a "busy" on the assumption that 05018 a busy */ 05019 f = NULL; 05020 } 05021 } else if (f->frametype == AST_FRAME_DTMF) { 05022 #ifdef HAVE_PRI 05023 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) { 05024 /* Don't accept in-band DTMF when in overlap dial mode */ 05025 f->frametype = AST_FRAME_NULL; 05026 f->subclass = 0; 05027 } 05028 #endif 05029 /* DSP clears us of being pulse */ 05030 p->pulsedial = 0; 05031 } 05032 } 05033 } else 05034 f = &p->subs[index].f; 05035 05036 if (f && (f->frametype == AST_FRAME_DTMF)) 05037 dahdi_handle_dtmfup(ast, index, &f); 05038 05039 /* If we have a fake_event, trigger exception to handle it */ 05040 if (p->fake_event) 05041 ast_set_flag(ast, AST_FLAG_EXCEPTION); 05042 05043 ast_mutex_unlock(&p->lock); 05044 return f; 05045 }
static struct ast_channel * dahdi_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 7965 of file chan_dahdi.c.
References alloc_sub(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose(), available(), busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_new(), dahdi_pvt::digital, dahdi_pvt::distinctivering, iflist, dahdi_pvt::inalarm, lock, LOG_DEBUG, LOG_NOTICE, dahdi_pvt::next, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, restart_monitor(), round_robin, s, dahdi_pvt::sig, SIG_FXSKS, strsep(), SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.
07966 { 07967 ast_group_t groupmatch = 0; 07968 int channelmatch = -1; 07969 int roundrobin = 0; 07970 int callwait = 0; 07971 int busy = 0; 07972 struct dahdi_pvt *p; 07973 struct ast_channel *tmp = NULL; 07974 char *dest=NULL; 07975 int x; 07976 char *s; 07977 char opt=0; 07978 int res=0, y=0; 07979 int backwards = 0; 07980 #ifdef HAVE_PRI 07981 int crv; 07982 int bearer = -1; 07983 int trunkgroup; 07984 struct dahdi_pri *pri=NULL; 07985 #endif 07986 struct dahdi_pvt *exit, *start, *end; 07987 ast_mutex_t *lock; 07988 int channelmatched = 0; 07989 int groupmatched = 0; 07990 07991 /* Assume we're locking the iflock */ 07992 lock = &iflock; 07993 start = iflist; 07994 end = ifend; 07995 if (data) { 07996 dest = ast_strdupa((char *)data); 07997 } else { 07998 ast_log(LOG_WARNING, "Channel requested with no data\n"); 07999 return NULL; 08000 } 08001 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') { 08002 /* Retrieve the group number */ 08003 char *stringp=NULL; 08004 stringp=dest + 1; 08005 s = strsep(&stringp, "/"); 08006 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08007 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data); 08008 return NULL; 08009 } 08010 groupmatch = ((ast_group_t) 1 << x); 08011 if (toupper(dest[0]) == 'G') { 08012 if (dest[0] == 'G') { 08013 backwards = 1; 08014 p = ifend; 08015 } else 08016 p = iflist; 08017 } else { 08018 if (dest[0] == 'R') { 08019 backwards = 1; 08020 p = round_robin[x]?round_robin[x]->prev:ifend; 08021 if (!p) 08022 p = ifend; 08023 } else { 08024 p = round_robin[x]?round_robin[x]->next:iflist; 08025 if (!p) 08026 p = iflist; 08027 } 08028 roundrobin = 1; 08029 } 08030 } else { 08031 char *stringp=NULL; 08032 stringp=dest; 08033 s = strsep(&stringp, "/"); 08034 p = iflist; 08035 if (!strcasecmp(s, "pseudo")) { 08036 /* Special case for pseudo */ 08037 x = CHAN_PSEUDO; 08038 channelmatch = x; 08039 } 08040 #ifdef HAVE_PRI 08041 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) { 08042 if ((trunkgroup < 1) || (crv < 1)) { 08043 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data); 08044 return NULL; 08045 } 08046 res--; 08047 for (x = 0; x < NUM_SPANS; x++) { 08048 if (pris[x].trunkgroup == trunkgroup) { 08049 pri = pris + x; 08050 lock = &pri->lock; 08051 start = pri->crvs; 08052 end = pri->crvend; 08053 break; 08054 } 08055 } 08056 if (!pri) { 08057 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup); 08058 return NULL; 08059 } 08060 channelmatch = crv; 08061 p = pris[x].crvs; 08062 } 08063 #endif 08064 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) { 08065 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data); 08066 return NULL; 08067 } else { 08068 channelmatch = x; 08069 } 08070 } 08071 /* Search for an unowned channel */ 08072 ast_mutex_lock(lock); 08073 exit = p; 08074 while (p && !tmp) { 08075 if (roundrobin) 08076 round_robin[x] = p; 08077 #if 0 08078 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch); 08079 #endif 08080 08081 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) { 08082 if (option_debug) 08083 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); 08084 if (p->inalarm) 08085 goto next; 08086 08087 callwait = (p->owner != NULL); 08088 #ifdef HAVE_PRI 08089 if (pri && (p->subs[SUB_REAL].dfd < 0)) { 08090 if (p->sig != SIG_FXSKS) { 08091 /* Gotta find an actual channel to use for this 08092 CRV if this isn't a callwait */ 08093 bearer = pri_find_empty_chan(pri, 0); 08094 if (bearer < 0) { 08095 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv); 08096 p = NULL; 08097 break; 08098 } 08099 pri_assign_bearer(p, pri, pri->pvts[bearer]); 08100 } else { 08101 if (alloc_sub(p, 0)) { 08102 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n"); 08103 p = NULL; 08104 break; 08105 } else 08106 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n"); 08107 p->pri = pri; 08108 } 08109 } 08110 #endif 08111 if (p->channel == CHAN_PSEUDO) { 08112 p = chandup(p); 08113 if (!p) { 08114 break; 08115 } 08116 } 08117 if (p->owner) { 08118 if (alloc_sub(p, SUB_CALLWAIT)) { 08119 p = NULL; 08120 break; 08121 } 08122 } 08123 p->outgoing = 1; 08124 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0); 08125 #ifdef HAVE_PRI 08126 if (p->bearer) { 08127 /* Log owner to bearer channel, too */ 08128 p->bearer->owner = tmp; 08129 } 08130 #endif 08131 /* Make special notes */ 08132 if (res > 1) { 08133 if (opt == 'c') { 08134 /* Confirm answer */ 08135 p->confirmanswer = 1; 08136 } else if (opt == 'r') { 08137 /* Distinctive ring */ 08138 if (res < 3) 08139 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data); 08140 else 08141 p->distinctivering = y; 08142 } else if (opt == 'd') { 08143 /* If this is an ISDN call, make it digital */ 08144 p->digital = 1; 08145 if (tmp) 08146 tmp->transfercapability = AST_TRANS_CAP_DIGITAL; 08147 } else { 08148 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data); 08149 } 08150 } 08151 /* Note if the call is a call waiting call */ 08152 if (tmp && callwait) 08153 tmp->cdrflags |= AST_CDR_CALLWAIT; 08154 break; 08155 } 08156 next: 08157 if (backwards) { 08158 p = p->prev; 08159 if (!p) 08160 p = end; 08161 } else { 08162 p = p->next; 08163 if (!p) 08164 p = start; 08165 } 08166 /* stop when you roll to the one that we started from */ 08167 if (p == exit) 08168 break; 08169 } 08170 ast_mutex_unlock(lock); 08171 restart_monitor(); 08172 if (callwait) 08173 *cause = AST_CAUSE_BUSY; 08174 else if (!tmp) { 08175 if (channelmatched) { 08176 if (busy) 08177 *cause = AST_CAUSE_BUSY; 08178 } else if (groupmatched) { 08179 *cause = AST_CAUSE_CONGESTION; 08180 } 08181 } 08182 08183 return tmp; 08184 }
static int dahdi_restart | ( | void | ) | [static] |
Definition at line 10091 of file chan_dahdi.c.
References ast_active_channels(), ast_cond_wait(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verbose(), dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, lock, master, dahdi_pvt::next, option_debug, option_verbose, dahdi_pvt::owner, setup_dahdi(), and dahdi_pvt::subs.
Referenced by __action_restart(), and dahdi_restart_cmd().
10092 { 10093 #if defined(HAVE_PRI) 10094 int i, j; 10095 #endif 10096 int cancel_code; 10097 struct dahdi_pvt *p; 10098 10099 ast_mutex_lock(&restart_lock); 10100 10101 if (option_verbose) 10102 ast_verbose("Destroying channels and reloading DAHDI configuration.\n"); 10103 dahdi_softhangup_all(); 10104 if (option_verbose > 3) 10105 ast_verbose("Initial softhangup of all DAHDI channels complete.\n"); 10106 10107 #if defined(HAVE_PRI) 10108 for (i = 0; i < NUM_SPANS; i++) { 10109 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) { 10110 cancel_code = pthread_cancel(pris[i].master); 10111 pthread_kill(pris[i].master, SIGURG); 10112 if (option_debug > 3) 10113 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code); 10114 pthread_join(pris[i].master, NULL); 10115 if (option_debug > 3) 10116 ast_verbose("Joined thread of span %d\n", i); 10117 } 10118 } 10119 #endif 10120 10121 ast_mutex_lock(&monlock); 10122 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 10123 cancel_code = pthread_cancel(monitor_thread); 10124 pthread_kill(monitor_thread, SIGURG); 10125 if (option_debug > 3) 10126 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code); 10127 pthread_join(monitor_thread, NULL); 10128 if (option_debug > 3) 10129 ast_verbose("Joined monitor thread\n"); 10130 } 10131 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */ 10132 10133 ast_mutex_lock(&ss_thread_lock); 10134 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */ 10135 int x = DAHDI_FLASH; 10136 if (option_debug > 2) 10137 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count); 10138 10139 for (p = iflist; p; p = p->next) { 10140 if (p->owner) 10141 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 */ 10142 } 10143 ast_cond_wait(&ss_thread_complete, &ss_thread_lock); 10144 } 10145 10146 /* ensure any created channels before monitor threads were stopped are hungup */ 10147 dahdi_softhangup_all(); 10148 if (option_verbose > 3) 10149 ast_verbose("Final softhangup of all DAHDI channels complete.\n"); 10150 destroy_all_channels(); 10151 if (option_debug) 10152 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels()); 10153 10154 ast_mutex_unlock(&monlock); 10155 10156 #ifdef HAVE_PRI 10157 for (i = 0; i < NUM_SPANS; i++) { 10158 for (j = 0; j < NUM_DCHANS; j++) 10159 dahdi_close_pri_fd(&(pris[i]), j); 10160 } 10161 10162 memset(pris, 0, sizeof(pris)); 10163 for (i = 0; i < NUM_SPANS; i++) { 10164 ast_mutex_init(&pris[i].lock); 10165 pris[i].offset = -1; 10166 pris[i].master = AST_PTHREADT_NULL; 10167 for (j = 0; j < NUM_DCHANS; j++) 10168 pris[i].fds[j] = -1; 10169 } 10170 pri_set_error(dahdi_pri_error); 10171 pri_set_message(dahdi_pri_message); 10172 #endif 10173 10174 if (setup_dahdi(2) != 0) { 10175 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n"); 10176 ast_mutex_unlock(&ss_thread_lock); 10177 return 1; 10178 } 10179 ast_mutex_unlock(&ss_thread_lock); 10180 ast_mutex_unlock(&restart_lock); 10181 return 0; 10182 }
static int dahdi_restart_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10184 of file chan_dahdi.c.
References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10185 { 10186 if (argc != 2) { 10187 return RESULT_SHOWUSAGE; 10188 } 10189 10190 if (dahdi_restart() != 0) 10191 return RESULT_FAILURE; 10192 return RESULT_SUCCESS; 10193 }
static int dahdi_ring_phone | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3567 of file chan_dahdi.c.
References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.
Referenced by __dahdi_exception(), and dahdi_handle_event().
03568 { 03569 int x; 03570 int res; 03571 /* Make sure our transmit state is on hook */ 03572 x = 0; 03573 x = DAHDI_ONHOOK; 03574 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03575 do { 03576 x = DAHDI_RING; 03577 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); 03578 if (res) { 03579 switch (errno) { 03580 case EBUSY: 03581 case EINTR: 03582 /* Wait just in case */ 03583 usleep(10000); 03584 continue; 03585 case EINPROGRESS: 03586 res = 0; 03587 break; 03588 default: 03589 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno)); 03590 res = 0; 03591 } 03592 } 03593 } while (res); 03594 return res; 03595 }
static int dahdi_sendtext | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 11921 of file chan_dahdi.c.
References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, pollfd::events, pollfd::fd, free, HEADER_LEN, HEADER_MS, LOG_ERROR, dahdi_pvt::mate, option_debug, poll(), POLLOUT, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, pollfd::revents, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.
11922 { 11923 #define END_SILENCE_LEN 400 11924 #define HEADER_MS 50 11925 #define TRAILER_MS 5 11926 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8) 11927 #define ASCII_BYTES_PER_CHAR 80 11928 11929 unsigned char *buf,*mybuf; 11930 struct dahdi_pvt *p = c->tech_pvt; 11931 struct pollfd fds[1]; 11932 int size,res,fd,len,x; 11933 int bytes=0; 11934 /* Initial carrier (imaginary) */ 11935 float cr = 1.0; 11936 float ci = 0.0; 11937 float scont = 0.0; 11938 int index; 11939 11940 index = dahdi_get_index(c, p, 0); 11941 if (index < 0) { 11942 ast_log(LOG_WARNING, "Huh? I don't exist?\n"); 11943 return -1; 11944 } 11945 if (!text[0]) return(0); /* if nothing to send, dont */ 11946 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */ 11947 if (p->mate) 11948 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN); 11949 else 11950 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN); 11951 if (!buf) 11952 return -1; 11953 mybuf = buf; 11954 if (p->mate) { 11955 int codec = AST_LAW(p); 11956 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */ 11957 PUT_CLID_MARKMS; 11958 } 11959 /* Put actual message */ 11960 for (x = 0; text[x]; x++) { 11961 PUT_CLID(text[x]); 11962 } 11963 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */ 11964 PUT_CLID_MARKMS; 11965 } 11966 len = bytes; 11967 buf = mybuf; 11968 } else { 11969 len = tdd_generate(p->tdd, buf, text); 11970 if (len < 1) { 11971 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text)); 11972 free(mybuf); 11973 return -1; 11974 } 11975 } 11976 memset(buf + len, 0x7f, END_SILENCE_LEN); 11977 len += END_SILENCE_LEN; 11978 fd = p->subs[index].dfd; 11979 while (len) { 11980 if (ast_check_hangup(c)) { 11981 free(mybuf); 11982 return -1; 11983 } 11984 size = len; 11985 if (size > READ_SIZE) 11986 size = READ_SIZE; 11987 fds[0].fd = fd; 11988 fds[0].events = POLLOUT | POLLPRI; 11989 fds[0].revents = 0; 11990 res = poll(fds, 1, -1); 11991 if (!res) { 11992 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 11993 continue; 11994 } 11995 /* if got exception */ 11996 if (fds[0].revents & POLLPRI) { 11997 ast_free(mybuf); 11998 return -1; 11999 } 12000 if (!(fds[0].revents & POLLOUT)) { 12001 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 12002 continue; 12003 } 12004 res = write(fd, buf, size); 12005 if (res != size) { 12006 if (res == -1) { 12007 free(mybuf); 12008 return -1; 12009 } 12010 if (option_debug) 12011 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 12012 break; 12013 } 12014 len -= size; 12015 buf += size; 12016 } 12017 free(mybuf); 12018 return(0); 12019 }
static int dahdi_set_hook | ( | int | fd, | |
int | hs | |||
) | [inline, static] |
Definition at line 1667 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(), and ss_thread().
01668 { 01669 int x, res; 01670 01671 x = hs; 01672 res = ioctl(fd, DAHDI_HOOK, &x); 01673 01674 if (res < 0) { 01675 if (errno == EINPROGRESS) 01676 return 0; 01677 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno)); 01678 /* will expectedly fail if phone is off hook during operation, such as during a restart */ 01679 } 01680 01681 return res; 01682 }
static int dahdi_setlinear | ( | int | dfd, | |
int | linear | |||
) | [static] |
Definition at line 977 of file chan_dahdi.c.
Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().
00978 { 00979 int res; 00980 res = ioctl(dfd, DAHDI_SETLINEAR, &linear); 00981 if (res) 00982 return res; 00983 return 0; 00984 }
static int dahdi_setoption | ( | struct ast_channel * | chan, | |
int | option, | |||
void * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 2932 of file chan_dahdi.c.
References ast_check_hangup(), ast_dsp_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(), 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, pollfd::events, pollfd::fd, dahdi_pvt::law, len, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, poll(), POLLOUT, POLLPRI, READ_SIZE, pollfd::revents, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.
02933 { 02934 char *cp; 02935 signed char *scp; 02936 int x; 02937 int index; 02938 struct dahdi_pvt *p = chan->tech_pvt, *pp; 02939 struct oprmode *oprmode; 02940 02941 02942 /* all supported options require data */ 02943 if (!data || (datalen < 1)) { 02944 errno = EINVAL; 02945 return -1; 02946 } 02947 02948 switch (option) { 02949 case AST_OPTION_TXGAIN: 02950 scp = (signed char *) data; 02951 index = dahdi_get_index(chan, p, 0); 02952 if (index < 0) { 02953 ast_log(LOG_WARNING, "No index in TXGAIN?\n"); 02954 return -1; 02955 } 02956 if (option_debug) 02957 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp); 02958 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law); 02959 case AST_OPTION_RXGAIN: 02960 scp = (signed char *) data; 02961 index = dahdi_get_index(chan, p, 0); 02962 if (index < 0) { 02963 ast_log(LOG_WARNING, "No index in RXGAIN?\n"); 02964 return -1; 02965 } 02966 if (option_debug) 02967 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp); 02968 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law); 02969 case AST_OPTION_TONE_VERIFY: 02970 if (!p->dsp) 02971 break; 02972 cp = (char *) data; 02973 switch (*cp) { 02974 case 1: 02975 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name); 02976 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */ 02977 break; 02978 case 2: 02979 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name); 02980 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */ 02981 break; 02982 default: 02983 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name); 02984 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */ 02985 break; 02986 } 02987 break; 02988 case AST_OPTION_TDD: 02989 /* turn on or off TDD */ 02990 cp = (char *) data; 02991 p->mate = 0; 02992 if (!*cp) { /* turn it off */ 02993 if (option_debug) 02994 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name); 02995 if (p->tdd) 02996 tdd_free(p->tdd); 02997 p->tdd = 0; 02998 break; 02999 } 03000 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n", 03001 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name); 03002 dahdi_disable_ec(p); 03003 /* otherwise, turn it on */ 03004 if (!p->didtdd) { /* if havent done it yet */ 03005 unsigned char mybuf[41000], *buf; 03006 int size, res, fd, len; 03007 struct pollfd fds[1]; 03008 03009 buf = mybuf; 03010 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */ 03011 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */ 03012 len = 40000; 03013 index = dahdi_get_index(chan, p, 0); 03014 if (index < 0) { 03015 ast_log(LOG_WARNING, "No index in TDD?\n"); 03016 return -1; 03017 } 03018 fd = p->subs[index].dfd; 03019 while (len) { 03020 if (ast_check_hangup(chan)) 03021 return -1; 03022 size = len; 03023 if (size > READ_SIZE) 03024 size = READ_SIZE; 03025 fds[0].fd = fd; 03026 fds[0].events = POLLPRI | POLLOUT; 03027 fds[0].revents = 0; 03028 res = poll(fds, 1, -1); 03029 if (!res) { 03030 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel); 03031 continue; 03032 } 03033 /* if got exception */ 03034 if (fds[0].revents & POLLPRI) 03035 return -1; 03036 if (!(fds[0].revents & POLLOUT)) { 03037 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel); 03038 continue; 03039 } 03040 res = write(fd, buf, size); 03041 if (res != size) { 03042 if (res == -1) return -1; 03043 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 03044 break; 03045 } 03046 len -= size; 03047 buf += size; 03048 } 03049 p->didtdd = 1; /* set to have done it now */ 03050 } 03051 if (*cp == 2) { /* Mate mode */ 03052 if (p->tdd) 03053 tdd_free(p->tdd); 03054 p->tdd = 0; 03055 p->mate = 1; 03056 break; 03057 } 03058 if (!p->tdd) { /* if we dont have one yet */ 03059 p->tdd = tdd_new(); /* allocate one */ 03060 } 03061 break; 03062 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */ 03063 if (!p->dsp) 03064 break; 03065 cp = (char *) data; 03066 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n", 03067 *cp ? "ON" : "OFF", (int) *cp, chan->name); 03068 p->dtmfrelax = 0; 03069 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 03070 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 03071 break; 03072 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */ 03073 cp = (char *) data; 03074 if (!*cp) { 03075 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name); 03076 x = 0; 03077 dahdi_disable_ec(p); 03078 } else { 03079 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name); 03080 x = 1; 03081 } 03082 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1) 03083 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno)); 03084 break; 03085 case AST_OPTION_OPRMODE: /* Operator services mode */ 03086 oprmode = (struct oprmode *) data; 03087 pp = oprmode->peer->tech_pvt; 03088 p->oprmode = pp->oprmode = 0; 03089 /* setup peers */ 03090 p->oprpeer = pp; 03091 pp->oprpeer = p; 03092 /* setup modes, if any */ 03093 if (oprmode->mode) 03094 { 03095 pp->oprmode = oprmode->mode; 03096 p->oprmode = -oprmode->mode; 03097 } 03098 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n", 03099 oprmode->mode, chan->name,oprmode->peer->name);; 03100 break; 03101 case AST_OPTION_ECHOCAN: 03102 cp = (char *) data; 03103 if (*cp) { 03104 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name); 03105 dahdi_enable_ec(p); 03106 } else { 03107 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name); 03108 dahdi_disable_ec(p); 03109 } 03110 break; 03111 } 03112 errno = 0; 03113 03114 return 0; 03115 }
static int dahdi_show_channel | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10256 of file chan_dahdi.c.
References ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, iflist, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, lock, dahdi_pvt::master, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_THREEWAY, and dahdi_pvt::subs.
10257 { 10258 int channel; 10259 struct dahdi_pvt *tmp = NULL; 10260 struct dahdi_confinfo ci; 10261 struct dahdi_params ps; 10262 int x; 10263 ast_mutex_t *lock; 10264 struct dahdi_pvt *start; 10265 #ifdef HAVE_PRI 10266 char *c; 10267 int trunkgroup; 10268 struct dahdi_pri *pri=NULL; 10269 #endif 10270 10271 lock = &iflock; 10272 start = iflist; 10273 10274 if (argc != 4) 10275 return RESULT_SHOWUSAGE; 10276 #ifdef HAVE_PRI 10277 if ((c = strchr(argv[3], ':'))) { 10278 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2) 10279 return RESULT_SHOWUSAGE; 10280 if ((trunkgroup < 1) || (channel < 1)) 10281 return RESULT_SHOWUSAGE; 10282 for (x = 0; x < NUM_SPANS; x++) { 10283 if (pris[x].trunkgroup == trunkgroup) { 10284 pri = pris + x; 10285 break; 10286 } 10287 } 10288 if (pri) { 10289 start = pri->crvs; 10290 lock = &pri->lock; 10291 } else { 10292 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10293 return RESULT_FAILURE; 10294 } 10295 } else 10296 #endif 10297 channel = atoi(argv[3]); 10298 10299 ast_mutex_lock(lock); 10300 tmp = start; 10301 while (tmp) { 10302 if (tmp->channel == channel) { 10303 #ifdef HAVE_PRI 10304 if (pri) 10305 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel); 10306 else 10307 #endif 10308 ast_cli(fd, "Channel: %d\n", tmp->channel); 10309 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd); 10310 ast_cli(fd, "Span: %d\n", tmp->span); 10311 ast_cli(fd, "Extension: %s\n", tmp->exten); 10312 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); 10313 ast_cli(fd, "Context: %s\n", tmp->context); 10314 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); 10315 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton); 10316 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); 10317 ast_cli(fd, "Destroy: %d\n", tmp->destroy); 10318 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); 10319 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); 10320 ast_cli(fd, "Radio: %d\n", tmp->radio); 10321 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); 10322 ast_cli(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)" : ""); 10323 ast_cli(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)" : ""); 10324 ast_cli(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)" : ""); 10325 ast_cli(fd, "Confno: %d\n", tmp->confno); 10326 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno); 10327 ast_cli(fd, "Real in conference: %d\n", tmp->inconference); 10328 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no"); 10329 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no"); 10330 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas); 10331 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown"); 10332 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no"); 10333 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no"); 10334 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF"); 10335 if (tmp->master) 10336 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel); 10337 for (x = 0; x < MAX_SLAVES; x++) { 10338 if (tmp->slaves[x]) 10339 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel); 10340 } 10341 #ifdef HAVE_PRI 10342 if (tmp->pri) { 10343 ast_cli(fd, "PRI Flags: "); 10344 if (tmp->resetting) 10345 ast_cli(fd, "Resetting "); 10346 if (tmp->call) 10347 ast_cli(fd, "Call "); 10348 if (tmp->bearer) 10349 ast_cli(fd, "Bearer "); 10350 ast_cli(fd, "\n"); 10351 if (tmp->logicalspan) 10352 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan); 10353 else 10354 ast_cli(fd, "PRI Logical Span: Implicit\n"); 10355 } 10356 10357 #endif 10358 memset(&ci, 0, sizeof(ci)); 10359 ps.channo = tmp->channel; 10360 if (tmp->subs[SUB_REAL].dfd > -1) { 10361 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) { 10362 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode); 10363 } 10364 #ifdef DAHDI_GETCONFMUTE 10365 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) { 10366 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No"); 10367 } 10368 #endif 10369 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) { 10370 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno)); 10371 } else { 10372 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook"); 10373 } 10374 } 10375 if (ISTRUNK(tmp)) { 10376 ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no"); 10377 if (!ast_strlen_zero(progzone)) 10378 ast_cli(fd, "Progress Zone: %s\n", progzone); 10379 ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no"); 10380 if(tmp->busydetect) { 10381 ast_cli(fd, "Busy Count: %d\n", tmp->busycount); 10382 if(tmp->busytonelength > 0) { 10383 ast_cli(fd, "Busy Pattern:\n"); 10384 ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength); 10385 if (tmp->busyquietlength > 0) 10386 ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength); 10387 else 10388 ast_cli(fd, " -- Detect Tone Only\n"); 10389 if(tmp->busyfuzziness > 0) 10390 ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness); 10391 } 10392 } 10393 } 10394 ast_mutex_unlock(lock); 10395 return RESULT_SUCCESS; 10396 } 10397 tmp = tmp->next; 10398 } 10399 10400 ast_cli(fd, "Unable to find given channel %d\n", channel); 10401 ast_mutex_unlock(lock); 10402 return RESULT_FAILURE; 10403 }
static int dahdi_show_channels | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 10195 of file chan_dahdi.c.
References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_pvt::exten, FORMAT, FORMAT2, iflist, dahdi_pvt::language, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
10196 { 10197 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10198 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n" 10199 struct dahdi_pvt *tmp = NULL; 10200 char tmps[20] = ""; 10201 ast_mutex_t *lock; 10202 struct dahdi_pvt *start; 10203 #ifdef HAVE_PRI 10204 int trunkgroup; 10205 struct dahdi_pri *pri = NULL; 10206 int x; 10207 #endif 10208 10209 lock = &iflock; 10210 start = iflist; 10211 10212 #ifdef HAVE_PRI 10213 if (argc == 4) { 10214 if ((trunkgroup = atoi(argv[3])) < 1) 10215 return RESULT_SHOWUSAGE; 10216 for (x = 0; x < NUM_SPANS; x++) { 10217 if (pris[x].trunkgroup == trunkgroup) { 10218 pri = pris + x; 10219 break; 10220 } 10221 } 10222 if (pri) { 10223 start = pri->crvs; 10224 lock = &pri->lock; 10225 } else { 10226 ast_cli(fd, "No such trunk group %d\n", trunkgroup); 10227 return RESULT_FAILURE; 10228 } 10229 } else 10230 #endif 10231 if (argc != 3) 10232 return RESULT_SHOWUSAGE; 10233 10234 ast_mutex_lock(lock); 10235 #ifdef HAVE_PRI 10236 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10237 #else 10238 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret"); 10239 #endif 10240 10241 tmp = start; 10242 while (tmp) { 10243 if (tmp->channel > 0) { 10244 snprintf(tmps, sizeof(tmps), "%d", tmp->channel); 10245 } else 10246 ast_copy_string(tmps, "pseudo", sizeof(tmps)); 10247 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret); 10248 tmp = tmp->next; 10249 } 10250 ast_mutex_unlock(lock); 10251 return RESULT_SUCCESS; 10252 #undef FORMAT 10253 #undef FORMAT2 10254 }
static int dahdi_show_status | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10436 of file chan_dahdi.c.
References alarms, ast_cli(), ast_log(), errno, FORMAT, FORMAT2, and RESULT_FAILURE.
10436 { 10437 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n" 10438 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n" 10439 10440 int span; 10441 int res; 10442 char alarms[50]; 10443 10444 int ctl; 10445 struct dahdi_spaninfo s; 10446 10447 #ifdef HAVE_ZAPTEL 10448 if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) { 10449 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno)); 10450 ast_cli(fd, "No Zaptel interface found.\n"); 10451 return RESULT_FAILURE; 10452 } 10453 #else 10454 if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) { 10455 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno)); 10456 ast_cli(fd, "No DAHDI interface found.\n"); 10457 return RESULT_FAILURE; 10458 } 10459 #endif 10460 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"); 10461 10462 for (span = 1; span < DAHDI_MAX_SPANS; ++span) { 10463 s.spanno = span; 10464 res = ioctl(ctl, DAHDI_SPANSTAT, &s); 10465 if (res) { 10466 continue; 10467 } 10468 alarms[0] = '\0'; 10469 if (s.alarms > 0) { 10470 if (s.alarms & DAHDI_ALARM_BLUE) 10471 strcat(alarms, "BLU/"); 10472 if (s.alarms & DAHDI_ALARM_YELLOW) 10473 strcat(alarms, "YEL/"); 10474 if (s.alarms & DAHDI_ALARM_RED) 10475 strcat(alarms, "RED/"); 10476 if (s.alarms & DAHDI_ALARM_LOOPBACK) 10477 strcat(alarms, "LB/"); 10478 if (s.alarms & DAHDI_ALARM_RECOVER) 10479 strcat(alarms, "REC/"); 10480 if (s.alarms & DAHDI_ALARM_NOTOPEN) 10481 strcat(alarms, "NOP/"); 10482 if (!strlen(alarms)) 10483 strcat(alarms, "UUU/"); 10484 if (strlen(alarms)) { 10485 /* Strip trailing / */ 10486 alarms[strlen(alarms) - 1] = '\0'; 10487 } 10488 } else { 10489 if (s.numchans) 10490 strcpy(alarms, "OK"); 10491 else 10492 strcpy(alarms, "UNCONFIGURED"); 10493 } 10494 10495 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count); 10496 } 10497 close(ctl); 10498 10499 return RESULT_SUCCESS; 10500 #undef FORMAT 10501 #undef FORMAT2 10502 }
static char* dahdi_sig2str | ( | int | sig | ) | [static] |
Definition at line 1218 of file chan_dahdi.c.
References 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, and SIG_SFWINK.
01219 { 01220 static char buf[256]; 01221 switch (sig) { 01222 case SIG_EM: 01223 return "E & M Immediate"; 01224 case SIG_EMWINK: 01225 return "E & M Wink"; 01226 case SIG_EM_E1: 01227 return "E & M E1"; 01228 case SIG_FEATD: 01229 return "Feature Group D (DTMF)"; 01230 case SIG_FEATDMF: 01231 return "Feature Group D (MF)"; 01232 case SIG_FEATDMF_TA: 01233 return "Feature Groud D (MF) Tandem Access"; 01234 case SIG_FEATB: 01235 return "Feature Group B (MF)"; 01236 case SIG_E911: 01237 return "E911 (MF)"; 01238 case SIG_FGC_CAMA: 01239 return "FGC/CAMA (Dialpulse)"; 01240 case SIG_FGC_CAMAMF: 01241 return "FGC/CAMA (MF)"; 01242 case SIG_FXSLS: 01243 return "FXS Loopstart"; 01244 case SIG_FXSGS: 01245 return "FXS Groundstart"; 01246 case SIG_FXSKS: 01247 return "FXS Kewlstart"; 01248 case SIG_FXOLS: 01249 return "FXO Loopstart"; 01250 case SIG_FXOGS: 01251 return "FXO Groundstart"; 01252 case SIG_FXOKS: 01253 return "FXO Kewlstart"; 01254 case SIG_PRI: 01255 return "ISDN PRI"; 01256 case SIG_SF: 01257 return "SF (Tone) Immediate"; 01258 case SIG_SFWINK: 01259 return "SF (Tone) Wink"; 01260 case SIG_SF_FEATD: 01261 return "SF (Tone) with Feature Group D (DTMF)"; 01262 case SIG_SF_FEATDMF: 01263 return "SF (Tone) with Feature Group D (MF)"; 01264 case SIG_SF_FEATB: 01265 return "SF (Tone) with Feature Group B (MF)"; 01266 case SIG_GR303FXOKS: 01267 return "GR-303 with FXOKS"; 01268 case SIG_GR303FXSKS: 01269 return "GR-303 with FXSKS"; 01270 case 0: 01271 return "Pseudo"; 01272 default: 01273 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig); 01274 return buf; 01275 } 01276 }
static void dahdi_softhangup_all | ( | void | ) | [static] |
Definition at line 10062 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, dahdi_pvt::lock, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.
Referenced by dahdi_restart().
10063 { 10064 struct dahdi_pvt *p; 10065 retry: 10066 ast_mutex_lock(&iflock); 10067 for (p = iflist; p; p = p->next) { 10068 ast_mutex_lock(&p->lock); 10069 if (p->owner && !p->restartpending) { 10070 if (ast_channel_trylock(p->owner)) { 10071 if (option_debug > 2) 10072 ast_verbose("Avoiding deadlock\n"); 10073 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */ 10074 ast_mutex_unlock(&p->lock); 10075 ast_mutex_unlock(&iflock); 10076 goto retry; 10077 } 10078 if (option_debug > 2) 10079 ast_verbose("Softhanging up on %s\n", p->owner->name); 10080 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT); 10081 p->restartpending = 1; 10082 num_restart_pending++; 10083 ast_channel_unlock(p->owner); 10084 } 10085 ast_mutex_unlock(&p->lock); 10086 } 10087 ast_mutex_unlock(&iflock); 10088 }
static void dahdi_train_ec | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1499 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, LOG_DEBUG, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_answer(), and dahdi_handle_event().
01500 { 01501 int x; 01502 int res; 01503 if (p && p->echocancel && p->echotraining) { 01504 x = p->echotraining; 01505 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x); 01506 if (res) 01507 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno)); 01508 else { 01509 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel); 01510 } 01511 } else 01512 ast_log(LOG_DEBUG, "No echo training requested\n"); 01513 }
static void dahdi_unlink | ( | struct dahdi_pvt * | slave, | |
struct dahdi_pvt * | master, | |||
int | needlock | |||
) | [static] |
Definition at line 3136 of file chan_dahdi.c.
References ast_log(), ast_mutex_lock(), ast_mutex_trylock(), conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, LOG_DEBUG, master, and SUB_REAL.
Referenced by dahdi_bridge(), and dahdi_fixup().
03137 { 03138 /* Unlink a specific slave or all slaves/masters from a given master */ 03139 int x; 03140 int hasslaves; 03141 if (!master) 03142 return; 03143 if (needlock) { 03144 ast_mutex_lock(&master->lock); 03145 if (slave) { 03146 while (ast_mutex_trylock(&slave->lock)) { 03147 DEADLOCK_AVOIDANCE(&master->lock); 03148 } 03149 } 03150 } 03151 hasslaves = 0; 03152 for (x = 0; x < MAX_SLAVES; x++) { 03153 if (master->slaves[x]) { 03154 if (!slave || (master->slaves[x] == slave)) { 03155 /* Take slave out of the conference */ 03156 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel); 03157 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL); 03158 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL); 03159 master->slaves[x]->master = NULL; 03160 master->slaves[x] = NULL; 03161 } else 03162 hasslaves = 1; 03163 } 03164 if (!hasslaves) 03165 master->inconference = 0; 03166 } 03167 if (!slave) { 03168 if (master->master) { 03169 /* Take master out of the conference */ 03170 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL); 03171 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL); 03172 hasslaves = 0; 03173 for (x = 0; x < MAX_SLAVES; x++) { 03174 if (master->master->slaves[x] == master) 03175 master->master->slaves[x] = NULL; 03176 else if (master->master->slaves[x]) 03177 hasslaves = 1; 03178 } 03179 if (!hasslaves) 03180 master->master->inconference = 0; 03181 } 03182 master->master = NULL; 03183 } 03184 update_conf(master); 03185 if (needlock) { 03186 if (slave) 03187 ast_mutex_unlock(&slave->lock); 03188 ast_mutex_unlock(&master->lock); 03189 } 03190 }
static int dahdi_wait_event | ( | int | fd | ) | [inline, static] |
Avoid the silly dahdi_waitevent which ignores a bunch of events.
Definition at line 265 of file chan_dahdi.c.
Referenced by ss_thread().
00266 { 00267 int i, j = 0; 00268 i = DAHDI_IOMUX_SIGEVENT; 00269 if (ioctl(fd, DAHDI_IOMUX, &i) == -1) 00270 return -1; 00271 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) 00272 return -1; 00273 return j; 00274 }
static int dahdi_wink | ( | struct dahdi_pvt * | p, | |
int | index | |||
) | [static] |
Definition at line 5543 of file chan_dahdi.c.
References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.
Referenced by ss_thread().
05544 { 05545 int j; 05546 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK); 05547 for (;;) 05548 { 05549 /* set bits of interest */ 05550 j = DAHDI_IOMUX_SIGEVENT; 05551 /* wait for some happening */ 05552 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1); 05553 /* exit loop if we have it */ 05554 if (j & DAHDI_IOMUX_SIGEVENT) break; 05555 } 05556 /* get the event info */ 05557 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1); 05558 return 0; 05559 }
static int dahdi_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 5070 of file chan_dahdi.c.
References 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::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_DEBUG, my_dahdi_write(), option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.
05071 { 05072 struct dahdi_pvt *p = ast->tech_pvt; 05073 int res; 05074 int index; 05075 index = dahdi_get_index(ast, p, 0); 05076 if (index < 0) { 05077 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name); 05078 return -1; 05079 } 05080 05081 #if 0 05082 #ifdef HAVE_PRI 05083 ast_mutex_lock(&p->lock); 05084 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) { 05085 if (p->pri->pri) { 05086 if (!pri_grab(p, p->pri)) { 05087 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital); 05088 pri_rel(p->pri); 05089 } else 05090 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span); 05091 } 05092 p->proceeding=1; 05093 } 05094 ast_mutex_unlock(&p->lock); 05095 #endif 05096 #endif 05097 /* Write a frame of (presumably voice) data */ 05098 if (frame->frametype != AST_FRAME_VOICE) { 05099 if (frame->frametype != AST_FRAME_IMAGE) 05100 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 05101 return 0; 05102 } 05103 if ((frame->subclass != AST_FORMAT_SLINEAR) && 05104 (frame->subclass != AST_FORMAT_ULAW) && 05105 (frame->subclass != AST_FORMAT_ALAW)) { 05106 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 05107 return -1; 05108 } 05109 if (p->dialing) { 05110 if (option_debug) 05111 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name); 05112 return 0; 05113 } 05114 if (!p->owner) { 05115 if (option_debug) 05116 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name); 05117 return 0; 05118 } 05119 if (p->cidspill) { 05120 if (option_debug) 05121 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n"); 05122 return 0; 05123 } 05124 /* Return if it's not valid data */ 05125 if (!frame->data || !frame->datalen) 05126 return 0; 05127 05128 if (frame->subclass == AST_FORMAT_SLINEAR) { 05129 if (!p->subs[index].linear) { 05130 p->subs[index].linear = 1; 05131 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05132 if (res) 05133 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel); 05134 } 05135 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1); 05136 } else { 05137 /* x-law already */ 05138 if (p->subs[index].linear) { 05139 p->subs[index].linear = 0; 05140 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 05141 if (res) 05142 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel); 05143 } 05144 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0); 05145 } 05146 if (res < 0) { 05147 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 05148 return -1; 05149 } 05150 return 0; 05151 }
static void destroy_all_channels | ( | void | ) | [static] |
Definition at line 2339 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, dahdi_pvt::next, option_verbose, and VERBOSE_PREFIX_2.
Referenced by __unload_module(), and dahdi_restart().
02340 { 02341 int x; 02342 struct dahdi_pvt *p, *pl; 02343 02344 while (num_restart_pending) { 02345 usleep(1); 02346 } 02347 02348 ast_mutex_lock(&iflock); 02349 /* Destroy all the interfaces and free their memory */ 02350 p = iflist; 02351 while (p) { 02352 /* Free any callerid */ 02353 if (p->cidspill) 02354 ast_free(p->cidspill); 02355 pl = p; 02356 p = p->next; 02357 x = pl->channel; 02358 /* Free associated memory */ 02359 if (pl) 02360 destroy_dahdi_pvt(&pl); 02361 if (option_verbose > 2) 02362 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x); 02363 } 02364 iflist = NULL; 02365 ifcount = 0; 02366 ast_mutex_unlock(&iflock); 02367 }
Definition at line 2289 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().
02290 { 02291 int owned = 0; 02292 int i = 0; 02293 02294 if (!now) { 02295 if (cur->owner) { 02296 owned = 1; 02297 } 02298 02299 for (i = 0; i < 3; i++) { 02300 if (cur->subs[i].owner) { 02301 owned = 1; 02302 } 02303 } 02304 if (!owned) { 02305 if (prev) { 02306 prev->next = cur->next; 02307 if (prev->next) 02308 prev->next->prev = prev; 02309 else 02310 ifend = prev; 02311 } else { 02312 iflist = cur->next; 02313 if (iflist) 02314 iflist->prev = NULL; 02315 else 02316 ifend = NULL; 02317 } 02318 destroy_dahdi_pvt(&cur); 02319 } 02320 } else { 02321 if (prev) { 02322 prev->next = cur->next; 02323 if (prev->next) 02324 prev->next->prev = prev; 02325 else 02326 ifend = prev; 02327 } else { 02328 iflist = cur->next; 02329 if (iflist) 02330 iflist->prev = NULL; 02331 else 02332 ifend = NULL; 02333 } 02334 destroy_dahdi_pvt(&cur); 02335 } 02336 return 0; 02337 }
static void destroy_dahdi_pvt | ( | struct dahdi_pvt ** | pvt | ) | [static] |
Definition at line 2271 of file chan_dahdi.c.
References ast_mutex_destroy(), ast_smdi_interface_unref(), dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, and dahdi_pvt::use_smdi.
Referenced by chandup(), destroy_all_channels(), destroy_channel(), and mkintf().
02272 { 02273 struct dahdi_pvt *p = *pvt; 02274 /* Remove channel from the list */ 02275 if (p->prev) 02276 p->prev->next = p->next; 02277 if (p->next) 02278 p->next->prev = p->prev; 02279 if (p->use_smdi) 02280 ast_smdi_interface_unref(p->smdi_iface); 02281 ast_mutex_destroy(&p->lock); 02282 dahdi_close_sub(p, SUB_REAL); 02283 if (p->owner) 02284 p->owner->tech_pvt = NULL; 02285 free(p); 02286 *pvt = NULL; 02287 }
static int digit_to_dtmfindex | ( | char | digit | ) | [static] |
Definition at line 1042 of file chan_dahdi.c.
Referenced by dahdi_digit_begin().
01043 { 01044 if (isdigit(digit)) 01045 return DAHDI_TONE_DTMF_BASE + (digit - '0'); 01046 else if (digit >= 'A' && digit <= 'D') 01047 return DAHDI_TONE_DTMF_A + (digit - 'A'); 01048 else if (digit >= 'a' && digit <= 'd') 01049 return DAHDI_TONE_DTMF_A + (digit - 'a'); 01050 else if (digit == '*') 01051 return DAHDI_TONE_DTMF_s; 01052 else if (digit == '#') 01053 return DAHDI_TONE_DTMF_p; 01054 else 01055 return -1; 01056 }
static void disable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3215 of file chan_dahdi.c.
References ast_dsp_set_features(), dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
03216 { 03217 #ifdef DAHDI_TONEDETECT 03218 int val; 03219 #endif 03220 03221 p->ignoredtmf = 1; 03222 03223 #ifdef DAHDI_TONEDETECT 03224 val = 0; 03225 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03226 #endif 03227 if (!p->hardwaredtmf && p->dsp) { 03228 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT; 03229 ast_dsp_set_features(p->dsp, p->dsp_features); 03230 } 03231 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 6949 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cidspill, pollfd::events, pollfd::fd, free, iflist, last, LOG_DEBUG, dahdi_pvt::next, dahdi_pvt::owner, POLLIN, POLLPRI, dahdi_pvt::radio, pollfd::revents, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.
Referenced by restart_monitor().
06950 { 06951 int count, res, res2, spoint, pollres=0; 06952 struct dahdi_pvt *i; 06953 struct dahdi_pvt *last = NULL; 06954 time_t thispass = 0, lastpass = 0; 06955 int found; 06956 char buf[1024]; 06957 struct pollfd *pfds=NULL; 06958 int lastalloc = -1; 06959 /* This thread monitors all the frame relay interfaces which are not yet in use 06960 (and thus do not have a separate thread) indefinitely */ 06961 /* From here on out, we die whenever asked */ 06962 #if 0 06963 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 06964 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 06965 return NULL; 06966 } 06967 ast_log(LOG_DEBUG, "Monitor starting...\n"); 06968 #endif 06969 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 06970 06971 for (;;) { 06972 /* Lock the interface list */ 06973 ast_mutex_lock(&iflock); 06974 if (!pfds || (lastalloc != ifcount)) { 06975 if (pfds) { 06976 free(pfds); 06977 pfds = NULL; 06978 } 06979 if (ifcount) { 06980 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) { 06981 ast_mutex_unlock(&iflock); 06982 return NULL; 06983 } 06984 } 06985 lastalloc = ifcount; 06986 } 06987 /* Build the stuff we're going to poll on, that is the socket of every 06988 dahdi_pvt that does not have an associated owner channel */ 06989 count = 0; 06990 i = iflist; 06991 while (i) { 06992 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) { 06993 if (!i->owner && !i->subs[SUB_REAL].owner) { 06994 /* This needs to be watched, as it lacks an owner */ 06995 pfds[count].fd = i->subs[SUB_REAL].dfd; 06996 pfds[count].events = POLLPRI; 06997 pfds[count].revents = 0; 06998 /* Message waiting or r2 channels also get watched for reading */ 06999 if (i->cidspill) 07000 pfds[count].events |= POLLIN; 07001 count++; 07002 } 07003 } 07004 i = i->next; 07005 } 07006 /* Okay, now that we know what to do, release the interface lock */ 07007 ast_mutex_unlock(&iflock); 07008 07009 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 07010 pthread_testcancel(); 07011 /* Wait at least a second for something to happen */ 07012 res = poll(pfds, count, 1000); 07013 pthread_testcancel(); 07014 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 07015 07016 /* Okay, poll has finished. Let's see what happened. */ 07017 if (res < 0) { 07018 if ((errno != EAGAIN) && (errno != EINTR)) 07019 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno)); 07020 continue; 07021 } 07022 /* Alright, lock the interface list again, and let's look and see what has 07023 happened */ 07024 ast_mutex_lock(&iflock); 07025 found = 0; 07026 spoint = 0; 07027 lastpass = thispass; 07028 thispass = time(NULL); 07029 i = iflist; 07030 while (i) { 07031 if (thispass != lastpass) { 07032 if (!found && ((i == last) || ((i == iflist) && !last))) { 07033 last = i; 07034 if (last) { 07035 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) && 07036 (last->sig & __DAHDI_SIG_FXO)) { 07037 res = ast_app_has_voicemail(last->mailbox, NULL); 07038 if (last->msgstate != res) { 07039 int x; 07040 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel); 07041 x = DAHDI_FLUSH_BOTH; 07042 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x); 07043 if (res2) 07044 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno)); 07045 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) { 07046 /* Turn on on hook transfer for 4 seconds */ 07047 x = 4000; 07048 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x); 07049 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last)); 07050 last->cidpos = 0; 07051 last->msgstate = res; 07052 last->onhooktime = thispass; 07053 } 07054 found ++; 07055 } 07056 } 07057 last = last->next; 07058 } 07059 } 07060 } 07061 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) { 07062 if (i->radio && !i->owner) 07063 { 07064 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07065 if (res) 07066 { 07067 if (option_debug) 07068 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel); 07069 /* Don't hold iflock while handling init events */ 07070 ast_mutex_unlock(&iflock); 07071 handle_init_event(i, res); 07072 ast_mutex_lock(&iflock); 07073 } 07074 i = i->next; 07075 continue; 07076 } 07077 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint); 07078 if (pollres & POLLIN) { 07079 if (i->owner || i->subs[SUB_REAL].owner) { 07080 #ifdef HAVE_PRI 07081 if (!i->pri) 07082 #endif 07083 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd); 07084 i = i->next; 07085 continue; 07086 } 07087 if (!i->cidspill) { 07088 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd); 07089 i = i->next; 07090 continue; 07091 } 07092 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf)); 07093 if (res > 0) { 07094 /* We read some number of bytes. Write an equal amount of data */ 07095 if (res > i->cidlen - i->cidpos) 07096 res = i->cidlen - i->cidpos; 07097 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res); 07098 if (res2 > 0) { 07099 i->cidpos += res2; 07100 if (i->cidpos >= i->cidlen) { 07101 free(i->cidspill); 07102 i->cidspill = 0; 07103 i->cidpos = 0; 07104 i->cidlen = 0; 07105 } 07106 } else { 07107 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno)); 07108 i->msgstate = -1; 07109 } 07110 } else { 07111 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno)); 07112 } 07113 } 07114 if (pollres & POLLPRI) { 07115 if (i->owner || i->subs[SUB_REAL].owner) { 07116 #ifdef HAVE_PRI 07117 if (!i->pri) 07118 #endif 07119 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd); 07120 i = i->next; 07121 continue; 07122 } 07123 res = dahdi_get_event(i->subs[SUB_REAL].dfd); 07124 if (option_debug) 07125 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel); 07126 /* Don't hold iflock while handling init events */ 07127 ast_mutex_unlock(&iflock); 07128 handle_init_event(i, res); 07129 ast_mutex_lock(&iflock); 07130 } 07131 } 07132 i=i->next; 07133 } 07134 ast_mutex_unlock(&iflock); 07135 } 07136 /* Never reached */ 07137 return NULL; 07138 07139 }
static void enable_dtmf_detect | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3233 of file chan_dahdi.c.
References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_bridge().
03234 { 03235 #ifdef DAHDI_TONEDETECT 03236 int val; 03237 #endif 03238 03239 if (p->channel == CHAN_PSEUDO) 03240 return; 03241 03242 p->ignoredtmf = 0; 03243 03244 #ifdef DAHDI_TONEDETECT 03245 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE; 03246 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val); 03247 #endif 03248 if (!p->hardwaredtmf && p->dsp) { 03249 p->dsp_features |= DSP_FEATURE_DTMF_DETECT; 03250 ast_dsp_set_features(p->dsp, p->dsp_features); 03251 } 03252 }
static char* event2str | ( | int | event | ) | [static] |
Definition at line 1199 of file chan_dahdi.c.
Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().
01200 { 01201 static char buf[256]; 01202 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1)) 01203 return events[event]; 01204 sprintf(buf, "Event %d", event); /* safe */ 01205 return buf; 01206 }
static void fill_rxgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1564 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_rxgain().
01565 { 01566 int j; 01567 int k; 01568 float linear_gain = pow(10.0, gain / 20.0); 01569 01570 switch (law) { 01571 case DAHDI_LAW_ALAW: 01572 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01573 if (gain) { 01574 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01575 if (k > 32767) k = 32767; 01576 if (k < -32767) k = -32767; 01577 g->rxgain[j] = AST_LIN2A(k); 01578 } else { 01579 g->rxgain[j] = j; 01580 } 01581 } 01582 break; 01583 case DAHDI_LAW_MULAW: 01584 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) { 01585 if (gain) { 01586 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01587 if (k > 32767) k = 32767; 01588 if (k < -32767) k = -32767; 01589 g->rxgain[j] = AST_LIN2MU(k); 01590 } else { 01591 g->rxgain[j] = j; 01592 } 01593 } 01594 break; 01595 } 01596 }
static void fill_txgain | ( | struct dahdi_gains * | g, | |
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1530 of file chan_dahdi.c.
References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.
Referenced by set_actual_txgain().
01531 { 01532 int j; 01533 int k; 01534 float linear_gain = pow(10.0, gain / 20.0); 01535 01536 switch (law) { 01537 case DAHDI_LAW_ALAW: 01538 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01539 if (gain) { 01540 k = (int) (((float) AST_ALAW(j)) * linear_gain); 01541 if (k > 32767) k = 32767; 01542 if (k < -32767) k = -32767; 01543 g->txgain[j] = AST_LIN2A(k); 01544 } else { 01545 g->txgain[j] = j; 01546 } 01547 } 01548 break; 01549 case DAHDI_LAW_MULAW: 01550 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) { 01551 if (gain) { 01552 k = (int) (((float) AST_MULAW(j)) * linear_gain); 01553 if (k > 32767) k = 32767; 01554 if (k < -32767) k = -32767; 01555 g->txgain[j] = AST_LIN2MU(k); 01556 } else { 01557 g->txgain[j] = j; 01558 } 01559 } 01560 break; 01561 } 01562 }
static struct dahdi_pvt* find_channel | ( | int | channel | ) | [static] |
Definition at line 10602 of file chan_dahdi.c.
References dahdi_pvt::channel, iflist, and dahdi_pvt::next.
Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().
10603 { 10604 struct dahdi_pvt *p = iflist; 10605 while (p) { 10606 if (p->channel == channel) { 10607 break; 10608 } 10609 p = p->next; 10610 } 10611 return p; 10612 }
static int get_alarms | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 3675 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.
Referenced by __action_showchannels(), dahdi_handle_event(), and handle_init_event().
03676 { 03677 int res; 03678 struct dahdi_spaninfo zi; 03679 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS) 03680 /* 03681 * The conditional compilation is needed only in asterisk-1.4 for 03682 * backward compatibility with old zaptel drivers that don't have 03683 * a DAHDI_PARAMS.chan_alarms field. 03684 */ 03685 struct dahdi_params params; 03686 #endif 03687 03688 memset(&zi, 0, sizeof(zi)); 03689 zi.spanno = p->span; 03690 03691 /* First check for span alarms */ 03692 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) { 03693 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno)); 03694 return 0; 03695 } 03696 if (zi.alarms != DAHDI_ALARM_NONE) 03697 return zi.alarms; 03698 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS) 03699 /* No alarms on the span. Check for channel alarms. */ 03700 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, ¶ms)) >= 0) 03701 return params.chan_alarms; 03702 /* ioctl failed */ 03703 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel); 03704 #endif 03705 return DAHDI_ALARM_NONE; 03706 }
static void handle_alarms | ( | struct dahdi_pvt * | p, | |
int | alarms | |||
) | [static] |
Definition at line 3779 of file chan_dahdi.c.
References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event(), and dahdi_pvt::unknown_alarm.
Referenced by dahdi_handle_event(), and handle_init_event().
03780 { 03781 const char *alarm_str = alarm2str(alarms); 03782 03783 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code 03784 * doesn't know what to do with it. Don't confuse users with log messages. */ 03785 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) { 03786 p->unknown_alarm = 1; 03787 return; 03788 } else { 03789 p->unknown_alarm = 0; 03790 } 03791 03792 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str); 03793 manager_event(EVENT_FLAG_SYSTEM, "Alarm", 03794 "Alarm: %s\r\n" 03795 "Channel: %d\r\n", 03796 alarm_str, p->channel); 03797 }
static int handle_dahdi_show_cadences | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 10409 of file chan_dahdi.c.
References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().
10410 { 10411 int i, j; 10412 for (i = 0; i < num_cadence; i++) { 10413 char output[1024]; 10414 char tmp[16], tmp2[64]; 10415 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1); 10416 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output)); 10417 10418 for (j = 0; j < 16; j++) { 10419 if (cadences[i].ringcadence[j] == 0) 10420 break; 10421 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]); 10422 if (cidrings[i] * 2 - 1 == j) 10423 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1); 10424 else 10425 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1); 10426 if (j != 0) 10427 strncat(output, ",", sizeof(output) - strlen(output) - 1); 10428 strncat(output, tmp2, sizeof(output) - strlen(output) - 1); 10429 } 10430 ast_cli(fd,"%s\n",output); 10431 } 10432 return 0; 10433 }
static int handle_init_event | ( | struct dahdi_pvt * | i, | |
int | event | |||
) | [static] |
Definition at line 6741 of file chan_dahdi.c.
References ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, EVENT_FLAG_SYSTEM, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, manager_event(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, 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, ss_thread(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::unknown_alarm, and VERBOSE_PREFIX_2.
06742 { 06743 int res; 06744 pthread_t threadid; 06745 pthread_attr_t attr; 06746 struct ast_channel *chan; 06747 pthread_attr_init(&attr); 06748 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 06749 /* Handle an event on a given channel for the monitor thread. */ 06750 switch (event) { 06751 case DAHDI_EVENT_NONE: 06752 case DAHDI_EVENT_BITSCHANGED: 06753 break; 06754 case DAHDI_EVENT_WINKFLASH: 06755 case DAHDI_EVENT_RINGOFFHOOK: 06756 if (i->inalarm) break; 06757 if (i->radio) break; 06758 /* Got a ring/answer. What kind of channel are we? */ 06759 switch (i->sig) { 06760 case SIG_FXOLS: 06761 case SIG_FXOGS: 06762 case SIG_FXOKS: 06763 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06764 if (res && (errno == EBUSY)) 06765 break; 06766 if (i->cidspill) { 06767 /* Cancel VMWI spill */ 06768 free(i->cidspill); 06769 i->cidspill = NULL; 06770 } 06771 if (i->immediate) { 06772 dahdi_enable_ec(i); 06773 /* The channel is immediately up. Start right away */ 06774 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE); 06775 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0); 06776 if (!chan) { 06777 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel); 06778 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06779 if (res < 0) 06780 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06781 } 06782 } else { 06783 /* Check for callerid, digits, etc */ 06784 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0); 06785 if (chan) { 06786 if (has_voicemail(i)) 06787 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER); 06788 else 06789 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE); 06790 if (res < 0) 06791 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel); 06792 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 06793 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 06794 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06795 if (res < 0) 06796 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06797 ast_hangup(chan); 06798 } 06799 } else 06800 ast_log(LOG_WARNING, "Unable to create channel\n"); 06801 } 06802 break; 06803 case SIG_FXSLS: 06804 case SIG_FXSGS: 06805 case SIG_FXSKS: 06806 i->ringt = i->ringt_base; 06807 /* Fall through */ 06808 case SIG_EMWINK: 06809 case SIG_FEATD: 06810 case SIG_FEATDMF: 06811 case SIG_FEATDMF_TA: 06812 case SIG_E911: 06813 case SIG_FGC_CAMA: 06814 case SIG_FGC_CAMAMF: 06815 case SIG_FEATB: 06816 case SIG_EM: 06817 case SIG_EM_E1: 06818 case SIG_SFWINK: 06819 case SIG_SF_FEATD: 06820 case SIG_SF_FEATDMF: 06821 case SIG_SF_FEATB: 06822 case SIG_SF: 06823 /* Check for callerid, digits, etc */ 06824 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0); 06825 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 06826 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 06827 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06828 if (res < 0) 06829 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06830 ast_hangup(chan); 06831 } else if (!chan) { 06832 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel); 06833 } 06834 break; 06835 default: 06836 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 06837 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); 06838 if (res < 0) 06839 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel); 06840 return -1; 06841 } 06842 break; 06843 case DAHDI_EVENT_NOALARM: 06844 i->inalarm = 0; 06845 if (!i->unknown_alarm) { 06846 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel); 06847 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear", 06848 "Channel: %d\r\n", i->channel); 06849 } else { 06850 i->unknown_alarm = 0; 06851 } 06852 break; 06853 case DAHDI_EVENT_ALARM: 06854 i->inalarm = 1; 06855 res = get_alarms(i); 06856 handle_alarms(i, res); 06857 /* fall thru intentionally */ 06858 case DAHDI_EVENT_ONHOOK: 06859 if (i->radio) 06860 break; 06861 /* Back on hook. Hang up. */ 06862 switch (i->sig) { 06863 case SIG_FXOLS: 06864 case SIG_FXOGS: 06865 case SIG_FEATD: 06866 case SIG_FEATDMF: 06867 case SIG_FEATDMF_TA: 06868 case SIG_E911: 06869 case SIG_FGC_CAMA: 06870 case SIG_FGC_CAMAMF: 06871 case SIG_FEATB: 06872 case SIG_EM: 06873 case SIG_EM_E1: 06874 case SIG_EMWINK: 06875 case SIG_SF_FEATD: 06876 case SIG_SF_FEATDMF: 06877 case SIG_SF_FEATB: 06878 case SIG_SF: 06879 case SIG_SFWINK: 06880 case SIG_FXSLS: 06881 case SIG_FXSGS: 06882 case SIG_FXSKS: 06883 case SIG_GR303FXSKS: 06884 dahdi_disable_ec(i); 06885 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06886 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06887 break; 06888 case SIG_GR303FXOKS: 06889 case SIG_FXOKS: 06890 dahdi_disable_ec(i); 06891 /* Diddle the battery for the zhone */ 06892 #ifdef ZHONE_HACK 06893 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06894 usleep(1); 06895 #endif 06896 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06897 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06898 break; 06899 case SIG_PRI: 06900 dahdi_disable_ec(i); 06901 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06902 break; 06903 default: 06904 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel); 06905 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); 06906 return -1; 06907 } 06908 break; 06909 case DAHDI_EVENT_POLARITY: 06910 switch (i->sig) { 06911 case SIG_FXSLS: 06912 case SIG_FXSKS: 06913 case SIG_FXSGS: 06914 /* We have already got a PR before the channel was 06915 created, but it wasn't handled. We need polarity 06916 to be REV for remote hangup detection to work. 06917 At least in Spain */ 06918 if (i->hanguponpolarityswitch) 06919 i->polarity = POLARITY_REV; 06920 06921 if (i->cid_start == CID_START_POLARITY) { 06922 i->polarity = POLARITY_REV; 06923 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity " 06924 "CID detection on channel %d\n", 06925 i->channel); 06926 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0); 06927 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) { 06928 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel); 06929 } 06930 } 06931 break; 06932 default: 06933 ast_log(LOG_WARNING, "handle_init_event detected " 06934 "polarity reversal on non-FXO (SIG_FXS) " 06935 "interface %d\n", i->channel); 06936 } 06937 break; 06938 case DAHDI_EVENT_REMOVED: /* destroy channel */ 06939 ast_log(LOG_NOTICE, 06940 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 06941 i->channel); 06942 dahdi_destroy_channel_bynum(i->channel); 06943 break; 06944 } 06945 pthread_attr_destroy(&attr); 06946 return 0; 06947 }
static int has_voicemail | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1762 of file chan_dahdi.c.
References ast_app_has_voicemail(), and dahdi_pvt::mailbox.
Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), and vm_execmain().
01763 { 01764 01765 return ast_app_has_voicemail(p->mailbox, NULL); 01766 }
static int isourconf | ( | struct dahdi_pvt * | p, | |
struct dahdi_subchannel * | c | |||
) | [static] |
Definition at line 1318 of file chan_dahdi.c.
References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.
Referenced by conf_del().
01319 { 01320 /* If they're listening to our channel, they're ours */ 01321 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON)) 01322 return 1; 01323 /* If they're a talker on our (allocated) conference, they're ours */ 01324 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER)) 01325 return 1; 01326 return 0; 01327 }
Definition at line 1351 of file chan_dahdi.c.
References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.
Referenced by update_conf().
01352 { 01353 int x; 01354 int useslavenative; 01355 struct dahdi_pvt *slave = NULL; 01356 /* Start out optimistic */ 01357 useslavenative = 1; 01358 /* Update conference state in a stateless fashion */ 01359 for (x = 0; x < 3; x++) { 01360 /* Any three-way calling makes slave native mode *definitely* out 01361 of the question */ 01362 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) 01363 useslavenative = 0; 01364 } 01365 /* If we don't have any 3-way calls, check to see if we have 01366 precisely one slave */ 01367 if (useslavenative) { 01368 for (x = 0; x < MAX_SLAVES; x++) { 01369 if (p->slaves[x]) { 01370 if (slave) { 01371 /* Whoops already have a slave! No 01372 slave native and stop right away */ 01373 slave = NULL; 01374 useslavenative = 0; 01375 break; 01376 } else { 01377 /* We have one slave so far */ 01378 slave = p->slaves[x]; 01379 } 01380 } 01381 } 01382 } 01383 /* If no slave, slave native definitely out */ 01384 if (!slave) 01385 useslavenative = 0; 01386 else if (slave->law != p->law) { 01387 useslavenative = 0; 01388 slave = NULL; 01389 } 01390 if (out) 01391 *out = slave; 01392 return useslavenative; 01393 }
static int load_module | ( | void | ) | [static] |
Definition at line 11864 of file chan_dahdi.c.
References __unload_module(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application(), ast_string_field_init, ast_string_field_set, CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, dahdi_tech, inuse, local_astman_register, lock, LOG_ERROR, name, round_robin, setup_dahdi(), ast_channel_tech::type, and zap_tech.
11865 { 11866 int res; 11867 11868 #ifdef HAVE_PRI 11869 int y,i; 11870 memset(pris, 0, sizeof(pris)); 11871 for (y = 0; y < NUM_SPANS; y++) { 11872 ast_mutex_init(&pris[y].lock); 11873 pris[y].offset = -1; 11874 pris[y].master = AST_PTHREADT_NULL; 11875 for (i = 0; i < NUM_DCHANS; i++) 11876 pris[y].fds[i] = -1; 11877 } 11878 pri_set_error(dahdi_pri_error); 11879 pri_set_message(dahdi_pri_message); 11880 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 11881 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec, 11882 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip); 11883 } 11884 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec, 11885 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip); 11886 #endif 11887 if ((res = setup_dahdi(0))) { 11888 return AST_MODULE_LOAD_DECLINE; 11889 } 11890 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { 11891 chan_tech = &dahdi_tech; 11892 } else { 11893 chan_tech = &zap_tech; 11894 } 11895 if (ast_channel_register(chan_tech)) { 11896 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type); 11897 __unload_module(); 11898 return -1; 11899 } 11900 #ifdef HAVE_PRI 11901 ast_string_field_init(&inuse, 16); 11902 ast_string_field_set(&inuse, name, "GR-303InUse"); 11903 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry)); 11904 #endif 11905 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry)); 11906 11907 memset(round_robin, 0, sizeof(round_robin)); 11908 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel"); 11909 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel"); 11910 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook"); 11911 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON"); 11912 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF"); 11913 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels"); 11914 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)"); 11915 11916 ast_cond_init(&ss_thread_complete, NULL); 11917 11918 return res; 11919 }
static struct dahdi_pvt* mkintf | ( | int | channel, | |
const struct dahdi_chan_conf * | conf, | |||
struct dahdi_pri * | pri, | |||
int | reloading | |||
) | [static] |
Definition at line 7299 of file chan_dahdi.c.
References ast_calloc, ast_log(), ast_mutex_init(), ast_strlen_zero(), dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_open(), destroy_dahdi_pvt(), errno, free, iflist, LOG_ERROR, MAX_CHANNELS, dahdi_pvt::next, dahdi_pvt::prev, dahdi_pvt::sig, sig2str, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, and SUB_REAL.
Referenced by build_channels().
07300 { 07301 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */ 07302 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL; 07303 char fn[80]; 07304 #if 1 07305 struct dahdi_bufferinfo bi; 07306 #endif 07307 int res; 07308 int span=0; 07309 int here = 0; 07310 int x; 07311 struct dahdi_pvt **wlist; 07312 struct dahdi_pvt **wend; 07313 struct dahdi_params p; 07314 07315 wlist = &iflist; 07316 wend = &ifend; 07317 07318 #ifdef HAVE_PRI 07319 if (pri) { 07320 wlist = &pri->crvs; 07321 wend = &pri->crvend; 07322 } 07323 #endif 07324 07325 tmp2 = *wlist; 07326 prev = NULL; 07327 07328 while (tmp2) { 07329 if (!tmp2->destroy) { 07330 if (tmp2->channel == channel) { 07331 tmp = tmp2; 07332 here = 1; 07333 break; 07334 } 07335 if (tmp2->channel > channel) { 07336 break; 07337 } 07338 } 07339 prev = tmp2; 07340 tmp2 = tmp2->next; 07341 } 07342 07343 if (!here && reloading != 1) { 07344 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) { 07345 if (tmp) 07346 free(tmp); 07347 return NULL; 07348 } 07349 ast_mutex_init(&tmp->lock); 07350 ifcount++; 07351 for (x = 0; x < 3; x++) 07352 tmp->subs[x].dfd = -1; 07353 tmp->channel = channel; 07354 } 07355 07356 if (tmp) { 07357 int chan_sig = conf->chan.sig; 07358 if (!here) { 07359 if ((channel != CHAN_PSEUDO) && !pri) { 07360 int count = 0; 07361 snprintf(fn, sizeof(fn), "%d", channel); 07362 /* Open non-blocking */ 07363 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07364 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 */ 07365 usleep(1); 07366 tmp->subs[SUB_REAL].dfd = dahdi_open(fn); 07367 count++; 07368 } 07369 /* Allocate a DAHDI structure */ 07370 if (tmp->subs[SUB_REAL].dfd < 0) { 07371 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); 07372 destroy_dahdi_pvt(&tmp); 07373 return NULL; 07374 } 07375 memset(&p, 0, sizeof(p)); 07376 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07377 if (res < 0) { 07378 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno)); 07379 destroy_dahdi_pvt(&tmp); 07380 return NULL; 07381 } 07382 if (p.sigtype != (conf->chan.sig & 0x3ffff)) { 07383 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype)); 07384 destroy_dahdi_pvt(&tmp); 07385 return NULL; 07386 } 07387 tmp->law = p.curlaw; 07388 tmp->span = p.spanno; 07389 span = p.spanno - 1; 07390 } else { 07391 if (channel == CHAN_PSEUDO) 07392 chan_sig = 0; 07393 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) { 07394 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n"); 07395 return NULL; 07396 } 07397 } 07398 #ifdef HAVE_PRI 07399 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) { 07400 int offset; 07401 int myswitchtype; 07402 int matchesdchan; 07403 int x,y; 07404 offset = 0; 07405 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) { 07406 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno)); 07407 destroy_dahdi_pvt(&tmp); 07408 return NULL; 07409 } 07410 if (span >= NUM_SPANS) { 07411 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span); 07412 destroy_dahdi_pvt(&tmp); 07413 return NULL; 07414 } else { 07415 struct dahdi_spaninfo si; 07416 si.spanno = 0; 07417 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) { 07418 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno)); 07419 destroy_dahdi_pvt(&tmp); 07420 return NULL; 07421 } 07422 /* Store the logical span first based upon the real span */ 07423 tmp->logicalspan = pris[span].prilogicalspan; 07424 pri_resolve_span(&span, channel, (channel - p.chanpos), &si); 07425 if (span < 0) { 07426 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel); 07427 destroy_dahdi_pvt(&tmp); 07428 return NULL; 07429 } 07430 if (chan_sig == SIG_PRI) 07431 myswitchtype = conf->pri.switchtype; 07432 else 07433 myswitchtype = PRI_SWITCH_GR303_TMC; 07434 /* Make sure this isn't a d-channel */ 07435 matchesdchan=0; 07436 for (x = 0; x < NUM_SPANS; x++) { 07437 for (y = 0; y < NUM_DCHANS; y++) { 07438 if (pris[x].dchannels[y] == tmp->channel) { 07439 matchesdchan = 1; 07440 break; 07441 } 07442 } 07443 } 07444 offset = p.chanpos; 07445 if (!matchesdchan) { 07446 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) { 07447 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype)); 07448 destroy_dahdi_pvt(&tmp); 07449 return NULL; 07450 } 07451 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) { 07452 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype)); 07453 destroy_dahdi_pvt(&tmp); 07454 return NULL; 07455 } 07456 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) { 07457 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan)); 07458 destroy_dahdi_pvt(&tmp); 07459 return NULL; 07460 } 07461 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) { 07462 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial); 07463 destroy_dahdi_pvt(&tmp); 07464 return NULL; 07465 } 07466 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) { 07467 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext); 07468 destroy_dahdi_pvt(&tmp); 07469 return NULL; 07470 } 07471 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) { 07472 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused); 07473 destroy_dahdi_pvt(&tmp); 07474 return NULL; 07475 } 07476 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) { 07477 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle); 07478 destroy_dahdi_pvt(&tmp); 07479 return NULL; 07480 } 07481 if (pris[span].numchans >= MAX_CHANNELS) { 07482 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel, 07483 pris[span].trunkgroup); 07484 destroy_dahdi_pvt(&tmp); 07485 return NULL; 07486 } 07487 pris[span].nodetype = conf->pri.nodetype; 07488 pris[span].switchtype = myswitchtype; 07489 pris[span].nsf = conf->pri.nsf; 07490 pris[span].dialplan = conf->pri.dialplan; 07491 pris[span].localdialplan = conf->pri.localdialplan; 07492 pris[span].pvts[pris[span].numchans++] = tmp; 07493 pris[span].minunused = conf->pri.minunused; 07494 pris[span].minidle = conf->pri.minidle; 07495 pris[span].overlapdial = conf->pri.overlapdial; 07496 #ifdef HAVE_PRI_INBANDDISCONNECT 07497 pris[span].inbanddisconnect = conf->pri.inbanddisconnect; 07498 #endif 07499 pris[span].facilityenable = conf->pri.facilityenable; 07500 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial)); 07501 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext)); 07502 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix)); 07503 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix)); 07504 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix)); 07505 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix)); 07506 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix)); 07507 pris[span].resetinterval = conf->pri.resetinterval; 07508 07509 tmp->pri = &pris[span]; 07510 tmp->prioffset = offset; 07511 tmp->call = NULL; 07512 } else { 07513 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset); 07514 destroy_dahdi_pvt(&tmp); 07515 return NULL; 07516 } 07517 } 07518 } else { 07519 tmp->prioffset = 0; 07520 } 07521 #endif 07522 } else { 07523 chan_sig = tmp->sig; 07524 memset(&p, 0, sizeof(p)); 07525 if (tmp->subs[SUB_REAL].dfd > -1) 07526 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); 07527 } 07528 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */ 07529 switch (chan_sig) { 07530 case SIG_FXSKS: 07531 case SIG_FXSLS: 07532 case SIG_EM: 07533 case SIG_EM_E1: 07534 case SIG_EMWINK: 07535 case SIG_FEATD: 07536 case SIG_FEATDMF: 07537 case SIG_FEATDMF_TA: 07538 case SIG_FEATB: 07539 case SIG_E911: 07540 case SIG_SF: 07541 case SIG_SFWINK: 07542 case SIG_FGC_CAMA: 07543 case SIG_FGC_CAMAMF: 07544 case SIG_SF_FEATD: 07545 case SIG_SF_FEATDMF: 07546 case SIG_SF_FEATB: 07547 p.starttime = 250; 07548 break; 07549 } 07550 07551 if (tmp->radio) { 07552 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */ 07553 p.channo = channel; 07554 p.rxwinktime = 1; 07555 p.rxflashtime = 1; 07556 p.starttime = 1; 07557 p.debouncetime = 5; 07558 } 07559 if (!tmp->radio) { 07560 p.channo = channel; 07561 /* Override timing settings based on config file */ 07562 if (conf->timing.prewinktime >= 0) 07563 p.prewinktime = conf->timing.prewinktime; 07564 if (conf->timing.preflashtime >= 0) 07565 p.preflashtime = conf->timing.preflashtime; 07566 if (conf->timing.winktime >= 0) 07567 p.winktime = conf->timing.winktime; 07568 if (conf->timing.flashtime >= 0) 07569 p.flashtime = conf->timing.flashtime; 07570 if (conf->timing.starttime >= 0) 07571 p.starttime = conf->timing.starttime; 07572 if (conf->timing.rxwinktime >= 0) 07573 p.rxwinktime = conf->timing.rxwinktime; 07574 if (conf->timing.rxflashtime >= 0) 07575 p.rxflashtime = conf->timing.rxflashtime; 07576 if (conf->timing.debouncetime >= 0) 07577 p.debouncetime = conf->timing.debouncetime; 07578 } 07579 07580 /* dont set parms on a pseudo-channel (or CRV) */ 07581 if (tmp->subs[SUB_REAL].dfd >= 0) 07582 { 07583 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p); 07584 if (res < 0) { 07585 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno)); 07586 destroy_dahdi_pvt(&tmp); 07587 return NULL; 07588 } 07589 } 07590 #if 1 07591 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) { 07592 memset(&bi, 0, sizeof(bi)); 07593 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi); 07594 if (!res) { 07595 bi.txbufpolicy = conf->chan.buf_policy; 07596 bi.rxbufpolicy = conf->chan.buf_policy; 07597 bi.numbufs = conf->chan.buf_no; 07598 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi); 07599 if (res < 0) { 07600 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno)); 07601 } 07602 } else 07603 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno)); 07604 } 07605 #endif 07606 tmp->immediate = conf->chan.immediate; 07607 tmp->transfertobusy = conf->chan.transfertobusy; 07608 tmp->sig = chan_sig; 07609 tmp->outsigmod = conf->chan.outsigmod; 07610 tmp->ringt_base = ringt_base; 07611 tmp->firstradio = 0; 07612 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS)) 07613 tmp->permcallwaiting = conf->chan.callwaiting; 07614 else 07615 tmp->permcallwaiting = 0; 07616 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */ 07617 tmp->destroy = 0; 07618 tmp->drings = drings; 07619 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; 07620 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid; 07621 tmp->threewaycalling = conf->chan.threewaycalling; 07622 tmp->adsi = conf->chan.adsi; 07623 tmp->use_smdi = conf->chan.use_smdi; 07624 tmp->permhidecallerid = conf->chan.hidecallerid; 07625 tmp->callreturn = conf->chan.callreturn; 07626 tmp->echocancel = conf->chan.echocancel; 07627 tmp->echotraining = conf->chan.echotraining; 07628 tmp->pulse = conf->chan.pulse; 07629 if (tmp->echocancel) 07630 tmp->echocanbridged = conf->chan.echocanbridged; 07631 else { 07632 if (conf->chan.echocanbridged) 07633 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n"); 07634 tmp->echocanbridged = 0; 07635 } 07636 tmp->busydetect = conf->chan.busydetect; 07637 tmp->busycount = conf->chan.busycount; 07638 tmp->busycompare = conf->chan.busycompare; 07639 tmp->busytonelength = conf->chan.busytonelength; 07640 tmp->busyquietlength = conf->chan.busyquietlength; 07641 tmp->busyfuzziness = conf->chan.busyfuzziness; 07642 tmp->silencethreshold = conf->chan.silencethreshold; 07643 tmp->callprogress = conf->chan.callprogress; 07644 tmp->cancallforward = conf->chan.cancallforward; 07645 tmp->dtmfrelax = conf->chan.dtmfrelax; 07646 tmp->callwaiting = tmp->permcallwaiting; 07647 tmp->hidecallerid = tmp->permhidecallerid; 07648 tmp->channel = channel; 07649 tmp->stripmsd = conf->chan.stripmsd; 07650 tmp->use_callerid = conf->chan.use_callerid; 07651 tmp->cid_signalling = conf->chan.cid_signalling; 07652 tmp->cid_start = conf->chan.cid_start; 07653 tmp->dahditrcallerid = conf->chan.dahditrcallerid; 07654 tmp->restrictcid = conf->chan.restrictcid; 07655 tmp->use_callingpres = conf->chan.use_callingpres; 07656 tmp->priindication_oob = conf->chan.priindication_oob; 07657 tmp->priexclusive = conf->chan.priexclusive; 07658 if (tmp->usedistinctiveringdetection) { 07659 if (!tmp->use_callerid) { 07660 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n"); 07661 tmp->use_callerid = 1; 07662 } 07663 } 07664 07665 if (tmp->cid_signalling == CID_SIG_SMDI) { 07666 if (!tmp->use_smdi) { 07667 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n"); 07668 tmp->use_smdi = 1; 07669 } 07670 } 07671 if (tmp->use_smdi) { 07672 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port); 07673 if (!(tmp->smdi_iface)) { 07674 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); 07675 tmp->use_smdi = 0; 07676 } 07677 } 07678 07679 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode)); 07680 tmp->amaflags = conf->chan.amaflags; 07681 if (!here) { 07682 tmp->confno = -1; 07683 tmp->propconfno = -1; 07684 } 07685 tmp->canpark = conf->chan.canpark; 07686 tmp->transfer = conf->chan.transfer; 07687 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext)); 07688 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language)); 07689 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret)); 07690 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest)); 07691 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context)); 07692 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num)); 07693 tmp->cid_ton = 0; 07694 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name)); 07695 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox)); 07696 tmp->msgstate = -1; 07697 tmp->group = conf->chan.group; 07698 tmp->callgroup = conf->chan.callgroup; 07699 tmp->pickupgroup= conf->chan.pickupgroup; 07700 tmp->rxgain = conf->chan.rxgain; 07701 tmp->txgain = conf->chan.txgain; 07702 tmp->tonezone = conf->chan.tonezone; 07703 tmp->onhooktime = time(NULL); 07704 if (tmp->subs[SUB_REAL].dfd > -1) { 07705 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law); 07706 if (tmp->dsp) 07707 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax); 07708 update_conf(tmp); 07709 if (!here) { 07710 if (chan_sig != SIG_PRI) 07711 /* Hang it up to be sure it's good */ 07712 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 07713 } 07714 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone); 07715 #ifdef HAVE_PRI 07716 /* the dchannel is down so put the channel in alarm */ 07717 if (tmp->pri && !pri_is_up(tmp->pri)) { 07718 tmp->inalarm = 1; 07719 } 07720 #endif 07721 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) { 07722 tmp->inalarm = 1; 07723 handle_alarms(tmp, res); 07724 } else { 07725 /* yes, this looks strange... the unknown_alarm flag is only used to 07726 control whether an 'alarm cleared' message gets generated when we 07727 get an indication that the channel is no longer in alarm status. 07728 however, the channel *could* be in an alarm status that we aren't 07729 aware of (since get_alarms() only reports span alarms, not channel 07730 alarms). setting this flag will cause any potential 'alarm cleared' 07731 message to be suppressed, but if a real alarm occurs before that 07732 happens, this flag will get cleared by it and the situation will 07733 be normal. 07734 */ 07735 tmp->unknown_alarm = 1; 07736 } 07737 } 07738 07739 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay; 07740 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch; 07741 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; 07742 tmp->sendcalleridafter = conf->chan.sendcalleridafter; 07743 07744 } 07745 if (tmp && !here) { 07746 /* nothing on the iflist */ 07747 if (!*wlist) { 07748 *wlist = tmp; 07749 tmp->prev = NULL; 07750 tmp->next = NULL; 07751 *wend = tmp; 07752 } else { 07753 /* at least one member on the iflist */ 07754 struct dahdi_pvt *working = *wlist; 07755 07756 /* check if we maybe have to put it on the begining */ 07757 if (working->channel > tmp->channel) { 07758 tmp->next = *wlist; 07759 tmp->prev = NULL; 07760 (*wlist)->prev = tmp; 07761 *wlist = tmp; 07762 } else { 07763 /* go through all the members and put the member in the right place */ 07764 while (working) { 07765 /* in the middle */ 07766 if (working->next) { 07767 if (working->channel < tmp->channel && working->next->channel > tmp->channel) { 07768 tmp->next = working->next; 07769 tmp->prev = working; 07770 working->next->prev = tmp; 07771 working->next = tmp; 07772 break; 07773 } 07774 } else { 07775 /* the last */ 07776 if (working->channel < tmp->channel) { 07777 working->next = tmp; 07778 tmp->next = NULL; 07779 tmp->prev = working; 07780 *wend = tmp; 07781 break; 07782 } 07783 } 07784 working = working->next; 07785 } 07786 } 07787 } 07788 } 07789 return tmp; 07790 }
static int my_dahdi_write | ( | struct dahdi_pvt * | p, | |
unsigned char * | buf, | |||
int | len, | |||
int | index, | |||
int | linear | |||
) | [static] |
Definition at line 5047 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_DEBUG, option_debug, READ_SIZE, and dahdi_pvt::subs.
Referenced by dahdi_write().
05048 { 05049 int sent=0; 05050 int size; 05051 int res; 05052 int fd; 05053 fd = p->subs[index].dfd; 05054 while (len) { 05055 size = len; 05056 if (size > (linear ? READ_SIZE * 2 : READ_SIZE)) 05057 size = (linear ? READ_SIZE * 2 : READ_SIZE); 05058 res = write(fd, buf, size); 05059 if (res != size) { 05060 if (option_debug) 05061 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel); 05062 return sent; 05063 } 05064 len -= size; 05065 buf += size; 05066 } 05067 return sent; 05068 }
static int my_getsigstr | ( | struct ast_channel * | chan, | |
char * | str, | |||
const char * | term, | |||
int | ms | |||
) | [static] |
Definition at line 5524 of file chan_dahdi.c.
References ast_waitfordigit().
Referenced by ss_thread().
05525 { 05526 char c; 05527 05528 *str = 0; /* start with empty output buffer */ 05529 for (;;) 05530 { 05531 /* Wait for the first digit (up to specified ms). */ 05532 c = ast_waitfordigit(chan, ms); 05533 /* if timeout, hangup or error, return as such */ 05534 if (c < 1) 05535 return c; 05536 *str++ = c; 05537 *str = 0; 05538 if (strchr(term, c)) 05539 return 1; 05540 } 05541 }
static int process_dahdi | ( | struct dahdi_chan_conf * | confp, | |
const char * | cat, | |||
struct ast_variable * | v, | |||
int | reload, | |||
int | skipchannels | |||
) | [static] |
Definition at line 11003 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_get_group(), ast_jb_read_conf(), ast_log(), ast_strlen_zero(), ast_true(), ast_verbose(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, dahdi_pvt::cid_name, dahdi_pvt::cid_num, 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_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_pvt::dahditrcallerid, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pvt::immediate, dahdi_pvt::language, ast_variable::lineno, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, ast_variable::next, option_verbose, dahdi_pvt::outsigmod, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pvt::pulse, dahdi_pvt::radio, READ_SIZE, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, strsep(), dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, ast_variable::value, and VERBOSE_PREFIX_3.
Referenced by setup_dahdi().
11004 { 11005 struct dahdi_pvt *tmp; 11006 int y; 11007 int found_pseudo = 0; 11008 char dahdichan[MAX_CHANLIST_LEN] = {}; 11009 11010 for (; v; v = v->next) { 11011 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 11012 continue; 11013 11014 /* Create the interface list */ 11015 if (!strcasecmp(v->name, "channel") 11016 #ifdef HAVE_PRI 11017 || !strcasecmp(v->name, "crv") 11018 #endif 11019 ) { 11020 int iscrv; 11021 if (skipchannels) 11022 continue; 11023 iscrv = !strcasecmp(v->name, "crv"); 11024 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo)) 11025 return -1; 11026 } else if (!strcasecmp(v->name, "buffers")) { 11027 int res; 11028 char policy[8] = ""; 11029 res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy); 11030 if (res != 2) { 11031 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n"); 11032 confp->chan.buf_no = numbufs; 11033 continue; 11034 } 11035 if (confp->chan.buf_no < 0) 11036 confp->chan.buf_no = numbufs; 11037 if (!strcasecmp(policy, "full")) { 11038 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL; 11039 } else if (!strcasecmp(policy, "half")) { 11040 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /* TODO: change to HALF_FULL */; 11041 } else if (!strcasecmp(policy, "immediate")) { 11042 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE; 11043 } else { 11044 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy); 11045 } 11046 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) { 11047 ast_copy_string(dahdichan, v->value, sizeof(dahdichan)); 11048 if (v->name[0] == 'z' || v->name[0] == 'Z') { 11049 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat); 11050 } 11051 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) { 11052 if (ast_true(v->value)) 11053 confp->chan.usedistinctiveringdetection = 1; 11054 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) { 11055 if (ast_true(v->value)) 11056 distinctiveringaftercid = 1; 11057 } else if (!strcasecmp(v->name, "dring1context")) { 11058 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData)); 11059 } else if (!strcasecmp(v->name, "dring2context")) { 11060 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData)); 11061 } else if (!strcasecmp(v->name, "dring3context")) { 11062 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData)); 11063 } else if (!strcasecmp(v->name, "dring1")) { 11064 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]); 11065 } else if (!strcasecmp(v->name, "dring2")) { 11066 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]); 11067 } else if (!strcasecmp(v->name, "dring3")) { 11068 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]); 11069 } else if (!strcasecmp(v->name, "usecallerid")) { 11070 confp->chan.use_callerid = ast_true(v->value); 11071 } else if (!strcasecmp(v->name, "cidsignalling")) { 11072 if (!strcasecmp(v->value, "bell")) 11073 confp->chan.cid_signalling = CID_SIG_BELL; 11074 else if (!strcasecmp(v->value, "v23")) 11075 confp->chan.cid_signalling = CID_SIG_V23; 11076 else if (!strcasecmp(v->value, "dtmf")) 11077 confp->chan.cid_signalling = CID_SIG_DTMF; 11078 else if (!strcasecmp(v->value, "smdi")) 11079 confp->chan.cid_signalling = CID_SIG_SMDI; 11080 else if (!strcasecmp(v->value, "v23_jp")) 11081 confp->chan.cid_signalling = CID_SIG_V23_JP; 11082 else if (ast_true(v->value)) 11083 confp->chan.cid_signalling = CID_SIG_BELL; 11084 } else if (!strcasecmp(v->name, "cidstart")) { 11085 if (!strcasecmp(v->value, "ring")) 11086 confp->chan.cid_start = CID_START_RING; 11087 else if (!strcasecmp(v->value, "polarity")) 11088 confp->chan.cid_start = CID_START_POLARITY; 11089 else if (ast_true(v->value)) 11090 confp->chan.cid_start = CID_START_RING; 11091 } else if (!strcasecmp(v->name, "threewaycalling")) { 11092 confp->chan.threewaycalling = ast_true(v->value); 11093 } else if (!strcasecmp(v->name, "cancallforward")) { 11094 confp->chan.cancallforward = ast_true(v->value); 11095 } else if (!strcasecmp(v->name, "relaxdtmf")) { 11096 if (ast_true(v->value)) 11097 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF; 11098 else 11099 confp->chan.dtmfrelax = 0; 11100 } else if (!strcasecmp(v->name, "mailbox")) { 11101 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox)); 11102 } else if (!strcasecmp(v->name, "hasvoicemail")) { 11103 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) { 11104 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox)); 11105 } 11106 } else if (!strcasecmp(v->name, "adsi")) { 11107 confp->chan.adsi = ast_true(v->value); 11108 } else if (!strcasecmp(v->name, "usesmdi")) { 11109 confp->chan.use_smdi = ast_true(v->value); 11110 } else if (!strcasecmp(v->name, "smdiport")) { 11111 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port)); 11112 } else if (!strcasecmp(v->name, "transfer")) { 11113 confp->chan.transfer = ast_true(v->value); 11114 } else if (!strcasecmp(v->name, "canpark")) { 11115 confp->chan.canpark = ast_true(v->value); 11116 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) { 11117 confp->chan.echocanbridged = ast_true(v->value); 11118 } else if (!strcasecmp(v->name, "busydetect")) { 11119 confp->chan.busydetect = ast_true(v->value); 11120 } else if (!strcasecmp(v->name, "busycount")) { 11121 confp->chan.busycount = atoi(v->value); 11122 } else if (!strcasecmp(v->name, "silencethreshold")) { 11123 confp->chan.silencethreshold = atoi(v->value); 11124 } else if (!strcasecmp(v->name, "busycompare")) { 11125 confp->chan.busycompare = ast_true(v->value); 11126 } else if (!strcasecmp(v->name, "busypattern")) { 11127 int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength); 11128 if (count == 1) 11129 confp->chan.busyquietlength = 0; 11130 else if (count < 1) 11131 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n"); 11132 } else if (!strcasecmp(v->name, "busyfuzziness")) { 11133 confp->chan.busyfuzziness = atoi(v->value); 11134 } else if (!strcasecmp(v->name, "callprogress")) { 11135 if (ast_true(v->value)) 11136 confp->chan.callprogress |= 1; 11137 else 11138 confp->chan.callprogress &= ~1; 11139 } else if (!strcasecmp(v->name, "faxdetect")) { 11140 if (!strcasecmp(v->value, "incoming")) { 11141 confp->chan.callprogress |= 4; 11142 confp->chan.callprogress &= ~2; 11143 } else if (!strcasecmp(v->value, "outgoing")) { 11144 confp->chan.callprogress &= ~4; 11145 confp->chan.callprogress |= 2; 11146 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) 11147 confp->chan.callprogress |= 6; 11148 else 11149 confp->chan.callprogress &= ~6; 11150 } else if (!strcasecmp(v->name, "echocancel")) { 11151 if (!ast_strlen_zero(v->value)) { 11152 y = atoi(v->value); 11153 } else 11154 y = 0; 11155 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024)) 11156 confp->chan.echocancel = y; 11157 else { 11158 confp->chan.echocancel = ast_true(v->value); 11159 if (confp->chan.echocancel) 11160 confp->chan.echocancel=128; 11161 } 11162 } else if (!strcasecmp(v->name, "echotraining")) { 11163 if (sscanf(v->value, "%d", &y) == 1) { 11164 if ((y < 10) || (y > 4000)) { 11165 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno); 11166 } else { 11167 confp->chan.echotraining = y; 11168 } 11169 } else if (ast_true(v->value)) { 11170 confp->chan.echotraining = 400; 11171 } else 11172 confp->chan.echotraining = 0; 11173 } else if (!strcasecmp(v->name, "hidecallerid")) { 11174 confp->chan.hidecallerid = ast_true(v->value); 11175 } else if (!strcasecmp(v->name, "hidecalleridname")) { 11176 confp->chan.hidecalleridname = ast_true(v->value); 11177 } else if (!strcasecmp(v->name, "pulsedial")) { 11178 confp->chan.pulse = ast_true(v->value); 11179 } else if (!strcasecmp(v->name, "callreturn")) { 11180 confp->chan.callreturn = ast_true(v->value); 11181 } else if (!strcasecmp(v->name, "callwaiting")) { 11182 confp->chan.callwaiting = ast_true(v->value); 11183 } else if (!strcasecmp(v->name, "callwaitingcallerid")) { 11184 confp->chan.callwaitingcallerid = ast_true(v->value); 11185 } else if (!strcasecmp(v->name, "context")) { 11186 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context)); 11187 } else if (!strcasecmp(v->name, "language")) { 11188 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language)); 11189 } else if (!strcasecmp(v->name, "progzone")) { 11190 ast_copy_string(progzone, v->value, sizeof(progzone)); 11191 } else if (!strcasecmp(v->name, "mohinterpret") 11192 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) { 11193 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret)); 11194 } else if (!strcasecmp(v->name, "mohsuggest")) { 11195 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest)); 11196 } else if (!strcasecmp(v->name, "stripmsd")) { 11197 confp->chan.stripmsd = atoi(v->value); 11198 } else if (!strcasecmp(v->name, "jitterbuffers")) { 11199 numbufs = atoi(v->value); 11200 } else if (!strcasecmp(v->name, "group")) { 11201 confp->chan.group = ast_get_group(v->value); 11202 } else if (!strcasecmp(v->name, "callgroup")) { 11203 confp->chan.callgroup = ast_get_group(v->value); 11204 } else if (!strcasecmp(v->name, "pickupgroup")) { 11205 confp->chan.pickupgroup = ast_get_group(v->value); 11206 } else if (!strcasecmp(v->name, "immediate")) { 11207 confp->chan.immediate = ast_true(v->value); 11208 } else if (!strcasecmp(v->name, "transfertobusy")) { 11209 confp->chan.transfertobusy = ast_true(v->value); 11210 } else if (!strcasecmp(v->name, "rxgain")) { 11211 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) { 11212 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value); 11213 } 11214 } else if (!strcasecmp(v->name, "txgain")) { 11215 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) { 11216 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value); 11217 } 11218 } else if (!strcasecmp(v->name, "tonezone")) { 11219 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) { 11220 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value); 11221 } 11222 } else if (!strcasecmp(v->name, "callerid")) { 11223 if (!strcasecmp(v->value, "asreceived")) { 11224 confp->chan.cid_num[0] = '\0'; 11225 confp->chan.cid_name[0] = '\0'; 11226 } else { 11227 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num)); 11228 } 11229 } else if (!strcasecmp(v->name, "fullname")) { 11230 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name)); 11231 } else if (!strcasecmp(v->name, "cid_number")) { 11232 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num)); 11233 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) { 11234 confp->chan.dahditrcallerid = ast_true(v->value); 11235 if (strstr(v->name, "zap")) { 11236 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat); 11237 } 11238 } else if (!strcasecmp(v->name, "restrictcid")) { 11239 confp->chan.restrictcid = ast_true(v->value); 11240 } else if (!strcasecmp(v->name, "usecallingpres")) { 11241 confp->chan.use_callingpres = ast_true(v->value); 11242 } else if (!strcasecmp(v->name, "accountcode")) { 11243 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode)); 11244 } else if (!strcasecmp(v->name, "amaflags")) { 11245 y = ast_cdr_amaflags2int(v->value); 11246 if (y < 0) 11247 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno); 11248 else 11249 confp->chan.amaflags = y; 11250 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) { 11251 confp->chan.polarityonanswerdelay = atoi(v->value); 11252 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) { 11253 confp->chan.answeronpolarityswitch = ast_true(v->value); 11254 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) { 11255 confp->chan.hanguponpolarityswitch = ast_true(v->value); 11256 } else if (!strcasecmp(v->name, "sendcalleridafter")) { 11257 confp->chan.sendcalleridafter = atoi(v->value); 11258 } else if (reload != 1){ 11259 if (!strcasecmp(v->name, "signalling")) { 11260 confp->chan.outsigmod = -1; 11261 if (!strcasecmp(v->value, "em")) { 11262 confp->chan.sig = SIG_EM; 11263 } else if (!strcasecmp(v->value, "em_e1")) { 11264 confp->chan.sig = SIG_EM_E1; 11265 } else if (!strcasecmp(v->value, "em_w")) { 11266 confp->chan.sig = SIG_EMWINK; 11267 confp->chan.radio = 0; 11268 } else if (!strcasecmp(v->value, "fxs_ls")) { 11269 confp->chan.sig = SIG_FXSLS; 11270 confp->chan.radio = 0; 11271 } else if (!strcasecmp(v->value, "fxs_gs")) { 11272 confp->chan.sig = SIG_FXSGS; 11273 confp->chan.radio = 0; 11274 } else if (!strcasecmp(v->value, "fxs_ks")) { 11275 confp->chan.sig = SIG_FXSKS; 11276 confp->chan.radio = 0; 11277 } else if (!strcasecmp(v->value, "fxo_ls")) { 11278 confp->chan.sig = SIG_FXOLS; 11279 confp->chan.radio = 0; 11280 } else if (!strcasecmp(v->value, "fxo_gs")) { 11281 confp->chan.sig = SIG_FXOGS; 11282 confp->chan.radio = 0; 11283 } else if (!strcasecmp(v->value, "fxo_ks")) { 11284 confp->chan.sig = SIG_FXOKS; 11285 confp->chan.radio = 0; 11286 } else if (!strcasecmp(v->value, "fxs_rx")) { 11287 confp->chan.sig = SIG_FXSKS; 11288 confp->chan.radio = 1; 11289 } else if (!strcasecmp(v->value, "fxo_rx")) { 11290 confp->chan.sig = SIG_FXOLS; 11291 confp->chan.radio = 1; 11292 } else if (!strcasecmp(v->value, "fxs_tx")) { 11293 confp->chan.sig = SIG_FXSLS; 11294 confp->chan.radio = 1; 11295 } else if (!strcasecmp(v->value, "fxo_tx")) { 11296 confp->chan.sig = SIG_FXOGS; 11297 confp->chan.radio = 1; 11298 } else if (!strcasecmp(v->value, "em_rx")) { 11299 confp->chan.sig = SIG_EM; 11300 confp->chan.radio = 1; 11301 } else if (!strcasecmp(v->value, "em_tx")) { 11302 confp->chan.sig = SIG_EM; 11303 confp->chan.radio = 1; 11304 } else if (!strcasecmp(v->value, "em_rxtx")) { 11305 confp->chan.sig = SIG_EM; 11306 confp->chan.radio = 2; 11307 } else if (!strcasecmp(v->value, "em_txrx")) { 11308 confp->chan.sig = SIG_EM; 11309 confp->chan.radio = 2; 11310 } else if (!strcasecmp(v->value, "sf")) { 11311 confp->chan.sig = SIG_SF; 11312 confp->chan.radio = 0; 11313 } else if (!strcasecmp(v->value, "sf_w")) { 11314 confp->chan.sig = SIG_SFWINK; 11315 confp->chan.radio = 0; 11316 } else if (!strcasecmp(v->value, "sf_featd")) { 11317 confp->chan.sig = SIG_FEATD; 11318 confp->chan.radio = 0; 11319 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11320 confp->chan.sig = SIG_FEATDMF; 11321 confp->chan.radio = 0; 11322 } else if (!strcasecmp(v->value, "sf_featb")) { 11323 confp->chan.sig = SIG_SF_FEATB; 11324 confp->chan.radio = 0; 11325 } else if (!strcasecmp(v->value, "sf")) { 11326 confp->chan.sig = SIG_SF; 11327 confp->chan.radio = 0; 11328 } else if (!strcasecmp(v->value, "sf_rx")) { 11329 confp->chan.sig = SIG_SF; 11330 confp->chan.radio = 1; 11331 } else if (!strcasecmp(v->value, "sf_tx")) { 11332 confp->chan.sig = SIG_SF; 11333 confp->chan.radio = 1; 11334 } else if (!strcasecmp(v->value, "sf_rxtx")) { 11335 confp->chan.sig = SIG_SF; 11336 confp->chan.radio = 2; 11337 } else if (!strcasecmp(v->value, "sf_txrx")) { 11338 confp->chan.sig = SIG_SF; 11339 confp->chan.radio = 2; 11340 } else if (!strcasecmp(v->value, "featd")) { 11341 confp->chan.sig = SIG_FEATD; 11342 confp->chan.radio = 0; 11343 } else if (!strcasecmp(v->value, "featdmf")) { 11344 confp->chan.sig = SIG_FEATDMF; 11345 confp->chan.radio = 0; 11346 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11347 confp->chan.sig = SIG_FEATDMF_TA; 11348 confp->chan.radio = 0; 11349 } else if (!strcasecmp(v->value, "e911")) { 11350 confp->chan.sig = SIG_E911; 11351 confp->chan.radio = 0; 11352 } else if (!strcasecmp(v->value, "fgccama")) { 11353 confp->chan.sig = SIG_FGC_CAMA; 11354 confp->chan.radio = 0; 11355 } else if (!strcasecmp(v->value, "fgccamamf")) { 11356 confp->chan.sig = SIG_FGC_CAMAMF; 11357 confp->chan.radio = 0; 11358 } else if (!strcasecmp(v->value, "featb")) { 11359 confp->chan.sig = SIG_FEATB; 11360 confp->chan.radio = 0; 11361 #ifdef HAVE_PRI 11362 } else if (!strcasecmp(v->value, "pri_net")) { 11363 confp->chan.radio = 0; 11364 confp->chan.sig = SIG_PRI; 11365 confp->pri.nodetype = PRI_NETWORK; 11366 } else if (!strcasecmp(v->value, "pri_cpe")) { 11367 confp->chan.sig = SIG_PRI; 11368 confp->chan.radio = 0; 11369 confp->pri.nodetype = PRI_CPE; 11370 } else if (!strcasecmp(v->value, "gr303fxoks_net")) { 11371 confp->chan.sig = SIG_GR303FXOKS; 11372 confp->chan.radio = 0; 11373 confp->pri.nodetype = PRI_NETWORK; 11374 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) { 11375 confp->chan.sig = SIG_GR303FXSKS; 11376 confp->chan.radio = 0; 11377 confp->pri.nodetype = PRI_CPE; 11378 #endif 11379 } else { 11380 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11381 } 11382 } else if (!strcasecmp(v->name, "outsignalling")) { 11383 if (!strcasecmp(v->value, "em")) { 11384 confp->chan.outsigmod = SIG_EM; 11385 } else if (!strcasecmp(v->value, "em_e1")) { 11386 confp->chan.outsigmod = SIG_EM_E1; 11387 } else if (!strcasecmp(v->value, "em_w")) { 11388 confp->chan.outsigmod = SIG_EMWINK; 11389 } else if (!strcasecmp(v->value, "sf")) { 11390 confp->chan.outsigmod = SIG_SF; 11391 } else if (!strcasecmp(v->value, "sf_w")) { 11392 confp->chan.outsigmod = SIG_SFWINK; 11393 } else if (!strcasecmp(v->value, "sf_featd")) { 11394 confp->chan.outsigmod = SIG_FEATD; 11395 } else if (!strcasecmp(v->value, "sf_featdmf")) { 11396 confp->chan.outsigmod = SIG_FEATDMF; 11397 } else if (!strcasecmp(v->value, "sf_featb")) { 11398 confp->chan.outsigmod = SIG_SF_FEATB; 11399 } else if (!strcasecmp(v->value, "sf")) { 11400 confp->chan.outsigmod = SIG_SF; 11401 } else if (!strcasecmp(v->value, "featd")) { 11402 confp->chan.outsigmod = SIG_FEATD; 11403 } else if (!strcasecmp(v->value, "featdmf")) { 11404 confp->chan.outsigmod = SIG_FEATDMF; 11405 } else if (!strcasecmp(v->value, "featdmf_ta")) { 11406 confp->chan.outsigmod = SIG_FEATDMF_TA; 11407 } else if (!strcasecmp(v->value, "e911")) { 11408 confp->chan.outsigmod = SIG_E911; 11409 } else if (!strcasecmp(v->value, "fgccama")) { 11410 confp->chan.outsigmod = SIG_FGC_CAMA; 11411 } else if (!strcasecmp(v->value, "fgccamamf")) { 11412 confp->chan.outsigmod = SIG_FGC_CAMAMF; 11413 } else if (!strcasecmp(v->value, "featb")) { 11414 confp->chan.outsigmod = SIG_FEATB; 11415 } else { 11416 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value); 11417 } 11418 #ifdef HAVE_PRI 11419 } else if (!strcasecmp(v->name, "pridialplan")) { 11420 if (!strcasecmp(v->value, "national")) { 11421 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1; 11422 } else if (!strcasecmp(v->value, "unknown")) { 11423 confp->pri.dialplan = PRI_UNKNOWN + 1; 11424 } else if (!strcasecmp(v->value, "private")) { 11425 confp->pri.dialplan = PRI_PRIVATE + 1; 11426 } else if (!strcasecmp(v->value, "international")) { 11427 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1; 11428 } else if (!strcasecmp(v->value, "local")) { 11429 confp->pri.dialplan = PRI_LOCAL_ISDN + 1; 11430 } else if (!strcasecmp(v->value, "dynamic")) { 11431 confp->pri.dialplan = -1; 11432 } else { 11433 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11434 } 11435 } else if (!strcasecmp(v->name, "prilocaldialplan")) { 11436 if (!strcasecmp(v->value, "national")) { 11437 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1; 11438 } else if (!strcasecmp(v->value, "unknown")) { 11439 confp->pri.localdialplan = PRI_UNKNOWN + 1; 11440 } else if (!strcasecmp(v->value, "private")) { 11441 confp->pri.localdialplan = PRI_PRIVATE + 1; 11442 } else if (!strcasecmp(v->value, "international")) { 11443 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1; 11444 } else if (!strcasecmp(v->value, "local")) { 11445 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1; 11446 } else if (!strcasecmp(v->value, "dynamic")) { 11447 confp->pri.localdialplan = -1; 11448 } else { 11449 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno); 11450 } 11451 } else if (!strcasecmp(v->name, "switchtype")) { 11452 if (!strcasecmp(v->value, "national")) 11453 confp->pri.switchtype = PRI_SWITCH_NI2; 11454 else if (!strcasecmp(v->value, "ni1")) 11455 confp->pri.switchtype = PRI_SWITCH_NI1; 11456 else if (!strcasecmp(v->value, "dms100")) 11457 confp->pri.switchtype = PRI_SWITCH_DMS100; 11458 else if (!strcasecmp(v->value, "4ess")) 11459 confp->pri.switchtype = PRI_SWITCH_ATT4ESS; 11460 else if (!strcasecmp(v->value, "5ess")) 11461 confp->pri.switchtype = PRI_SWITCH_LUCENT5E; 11462 else if (!strcasecmp(v->value, "euroisdn")) 11463 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1; 11464 else if (!strcasecmp(v->value, "qsig")) 11465 confp->pri.switchtype = PRI_SWITCH_QSIG; 11466 else { 11467 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value); 11468 return -1; 11469 } 11470 } else if (!strcasecmp(v->name, "nsf")) { 11471 if (!strcasecmp(v->value, "sdn")) 11472 confp->pri.nsf = PRI_NSF_SDN; 11473 else if (!strcasecmp(v->value, "megacom")) 11474 confp->pri.nsf = PRI_NSF_MEGACOM; 11475 else if (!strcasecmp(v->value, "tollfreemegacom")) 11476 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM; 11477 else if (!strcasecmp(v->value, "accunet")) 11478 confp->pri.nsf = PRI_NSF_ACCUNET; 11479 else if (!strcasecmp(v->value, "none")) 11480 confp->pri.nsf = PRI_NSF_NONE; 11481 else { 11482 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value); 11483 confp->pri.nsf = PRI_NSF_NONE; 11484 } 11485 } else if (!strcasecmp(v->name, "priindication")) { 11486 if (!strcasecmp(v->value, "outofband")) 11487 confp->chan.priindication_oob = 1; 11488 else if (!strcasecmp(v->value, "inband")) 11489 confp->chan.priindication_oob = 0; 11490 else 11491 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", 11492 v->value, v->lineno); 11493 } else if (!strcasecmp(v->name, "priexclusive")) { 11494 confp->chan.priexclusive = ast_true(v->value); 11495 } else if (!strcasecmp(v->name, "internationalprefix")) { 11496 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix)); 11497 } else if (!strcasecmp(v->name, "nationalprefix")) { 11498 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix)); 11499 } else if (!strcasecmp(v->name, "localprefix")) { 11500 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix)); 11501 } else if (!strcasecmp(v->name, "privateprefix")) { 11502 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix)); 11503 } else if (!strcasecmp(v->name, "unknownprefix")) { 11504 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix)); 11505 } else if (!strcasecmp(v->name, "resetinterval")) { 11506 if (!strcasecmp(v->value, "never")) 11507 confp->pri.resetinterval = -1; 11508 else if (atoi(v->value) >= 60) 11509 confp->pri.resetinterval = atoi(v->value); 11510 else 11511 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n", 11512 v->value, v->lineno); 11513 } else if (!strcasecmp(v->name, "minunused")) { 11514 confp->pri.minunused = atoi(v->value); 11515 } else if (!strcasecmp(v->name, "minidle")) { 11516 confp->pri.minidle = atoi(v->value); 11517 } else if (!strcasecmp(v->name, "idleext")) { 11518 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext)); 11519 } else if (!strcasecmp(v->name, "idledial")) { 11520 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial)); 11521 } else if (!strcasecmp(v->name, "overlapdial")) { 11522 confp->pri.overlapdial = ast_true(v->value); 11523 #ifdef HAVE_PRI_INBANDDISCONNECT 11524 } else if (!strcasecmp(v->name, "inbanddisconnect")) { 11525 confp->pri.inbanddisconnect = ast_true(v->value); 11526 #endif 11527 } else if (!strcasecmp(v->name, "pritimer")) { 11528 #ifdef PRI_GETSET_TIMERS 11529 char *timerc, *c; 11530 int timer, timeridx; 11531 c = v->value; 11532 timerc = strsep(&c, ","); 11533 if (timerc) { 11534 timer = atoi(c); 11535 if (!timer) 11536 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc); 11537 else { 11538 if ((timeridx = pri_timer2idx(timerc)) >= 0) 11539 pritimers[timeridx] = timer; 11540 else 11541 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc); 11542 } 11543 } else 11544 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value); 11545 11546 } else if (!strcasecmp(v->name, "facilityenable")) { 11547 confp->pri.facilityenable = ast_true(v->value); 11548 #endif /* PRI_GETSET_TIMERS */ 11549 #endif /* HAVE_PRI */ 11550 } else if (!strcasecmp(v->name, "cadence")) { 11551 /* setup to scan our argument */ 11552 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 11553 int i; 11554 struct dahdi_ring_cadence new_cadence; 11555 int cid_location = -1; 11556 int firstcadencepos = 0; 11557 char original_args[80]; 11558 int cadence_is_ok = 1; 11559 11560 ast_copy_string(original_args, v->value, sizeof(original_args)); 11561 /* 16 cadences allowed (8 pairs) */ 11562 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &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]); 11563 11564 /* Cadence must be even (on/off) */ 11565 if (element_count % 2 == 1) { 11566 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args); 11567 cadence_is_ok = 0; 11568 } 11569 11570 /* Ring cadences cannot be negative */ 11571 for (i = 0; i < element_count; i++) { 11572 if (c[i] == 0) { 11573 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args); 11574 cadence_is_ok = 0; 11575 break; 11576 } else if (c[i] < 0) { 11577 if (i % 2 == 1) { 11578 /* Silence duration, negative possibly okay */ 11579 if (cid_location == -1) { 11580 cid_location = i; 11581 c[i] *= -1; 11582 } else { 11583 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args); 11584 cadence_is_ok = 0; 11585 break; 11586 } 11587 } else { 11588 if (firstcadencepos == 0) { 11589 firstcadencepos = i; /* only recorded to avoid duplicate specification */ 11590 /* duration will be passed negative to the DAHDI driver */ 11591 } else { 11592 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args); 11593 cadence_is_ok = 0; 11594 break; 11595 } 11596 } 11597 } 11598 } 11599 11600 /* Substitute our scanned cadence */ 11601 for (i = 0; i < 16; i++) { 11602 new_cadence.ringcadence[i] = c[i]; 11603 } 11604 11605 if (cadence_is_ok) { 11606 /* ---we scanned it without getting annoyed; now some sanity checks--- */ 11607 if (element_count < 2) { 11608 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args); 11609 } else { 11610 if (cid_location == -1) { 11611 /* user didn't say; default to first pause */ 11612 cid_location = 1; 11613 } else { 11614 /* convert element_index to cidrings value */ 11615 cid_location = (cid_location + 1) / 2; 11616 } 11617 /* ---we like their cadence; try to install it--- */ 11618 if (!user_has_defined_cadences++) 11619 /* this is the first user-defined cadence; clear the default user cadences */ 11620 num_cadence = 0; 11621 if ((num_cadence+1) >= NUM_CADENCE_MAX) 11622 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args); 11623 else { 11624 cadences[num_cadence] = new_cadence; 11625 cidrings[num_cadence++] = cid_location; 11626 if (option_verbose > 2) 11627 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args); 11628 } 11629 } 11630 } 11631 } else if (!strcasecmp(v->name, "ringtimeout")) { 11632 ringt_base = (atoi(v->value) * 8) / READ_SIZE; 11633 } else if (!strcasecmp(v->name, "prewink")) { 11634 confp->timing.prewinktime = atoi(v->value); 11635 } else if (!strcasecmp(v->name, "preflash")) { 11636 confp->timing.preflashtime = atoi(v->value); 11637 } else if (!strcasecmp(v->name, "wink")) { 11638 confp->timing.winktime = atoi(v->value); 11639 } else if (!strcasecmp(v->name, "flash")) { 11640 confp->timing.flashtime = atoi(v->value); 11641 } else if (!strcasecmp(v->name, "start")) { 11642 confp->timing.starttime = atoi(v->value); 11643 } else if (!strcasecmp(v->name, "rxwink")) { 11644 confp->timing.rxwinktime = atoi(v->value); 11645 } else if (!strcasecmp(v->name, "rxflash")) { 11646 confp->timing.rxflashtime = atoi(v->value); 11647 } else if (!strcasecmp(v->name, "debounce")) { 11648 confp->timing.debouncetime = atoi(v->value); 11649 } else if (!strcasecmp(v->name, "toneduration")) { 11650 int toneduration; 11651 int ctlfd; 11652 int res; 11653 struct dahdi_dialparams dps; 11654 11655 #ifdef HAVE_ZAPTEL 11656 ctlfd = open("/dev/zap/ctl", O_RDWR); 11657 #else 11658 ctlfd = open("/dev/dahdi/ctl", O_RDWR); 11659 #endif 11660 11661 if (ctlfd == -1) { 11662 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n"); 11663 return -1; 11664 } 11665 11666 toneduration = atoi(v->value); 11667 if (toneduration > -1) { 11668 memset(&dps, 0, sizeof(dps)); 11669 11670 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration; 11671 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps); 11672 if (res < 0) { 11673 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno)); 11674 return -1; 11675 } 11676 } 11677 close(ctlfd); 11678 } else if (!strcasecmp(v->name, "defaultcic")) { 11679 ast_copy_string(defaultcic, v->value, sizeof(defaultcic)); 11680 } else if (!strcasecmp(v->name, "defaultozz")) { 11681 ast_copy_string(defaultozz, v->value, sizeof(defaultozz)); 11682 } 11683 } else if (!skipchannels) 11684 ast_log(LOG_WARNING, "Ignoring %s\n", v->name); 11685 } 11686 if (dahdichan[0]) { 11687 /* The user has set 'dahdichan' */ 11688 /*< \todo pass proper line number instead of 0 */ 11689 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) { 11690 return -1; 11691 } 11692 } 11693 /*< \todo why check for the pseudo in the per-channel section. 11694 * Any actual use for manual setup of the pseudo channel? */ 11695 if (!found_pseudo && reload == 0) { 11696 /* Make sure pseudo isn't a member of any groups if 11697 we're automatically making it. */ 11698 11699 confp->chan.group = 0; 11700 confp->chan.callgroup = 0; 11701 confp->chan.pickupgroup = 0; 11702 11703 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload); 11704 11705 if (tmp) { 11706 if (option_verbose > 2) 11707 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n"); 11708 } else { 11709 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n"); 11710 } 11711 } 11712 return 0; 11713 }
static int reload | ( | void | ) | [static] |
Definition at line 12022 of file chan_dahdi.c.
References ast_log(), and setup_dahdi().
12023 { 12024 int res = 0; 12025 12026 res = setup_dahdi(1); 12027 if (res) { 12028 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n"); 12029 return -1; 12030 } 12031 return 0; 12032 }
static int reset_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1395 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_hangup().
01396 { 01397 struct dahdi_confinfo zi; 01398 memset(&zi, 0, sizeof(zi)); 01399 p->confno = -1; 01400 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf)); 01401 if (p->subs[SUB_REAL].dfd > -1) { 01402 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi)) 01403 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno)); 01404 } 01405 return 0; 01406 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 7141 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(), and LOG_ERROR.
Referenced by dahdi_hangup(), dahdi_request(), h323_reload(), load_module(), mgcp_reload(), mgcp_request(), oh323_request(), phone_hangup(), phone_request(), setup_dahdi(), sip_reload(), sip_request_call(), and skinny_request().
07142 { 07143 pthread_attr_t attr; 07144 pthread_attr_init(&attr); 07145 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 07146 /* If we're supposed to be stopped -- stay stopped */ 07147 if (monitor_thread == AST_PTHREADT_STOP) 07148 return 0; 07149 ast_mutex_lock(&monlock); 07150 if (monitor_thread == pthread_self()) { 07151 ast_mutex_unlock(&monlock); 07152 ast_log(LOG_WARNING, "Cannot kill myself\n"); 07153 return -1; 07154 } 07155 if (monitor_thread != AST_PTHREADT_NULL) { 07156 /* Wake up the thread */ 07157 pthread_kill(monitor_thread, SIGURG); 07158 } else { 07159 /* Start a new monitor */ 07160 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) { 07161 ast_mutex_unlock(&monlock); 07162 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 07163 pthread_attr_destroy(&attr); 07164 return -1; 07165 } 07166 } 07167 ast_mutex_unlock(&monlock); 07168 pthread_attr_destroy(&attr); 07169 return 0; 07170 }
static int restore_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1728 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_handle_event(), dahdi_read(), and send_callerid().
01729 { 01730 int res; 01731 if (p->saveconf.confmode) { 01732 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf); 01733 p->saveconf.confmode = 0; 01734 if (res) { 01735 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno)); 01736 return -1; 01737 } 01738 } 01739 if (option_debug) 01740 ast_log(LOG_DEBUG, "Restored conferencing\n"); 01741 return 0; 01742 }
static int restore_gains | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1654 of file chan_dahdi.c.
References ast_log(), 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(), and ss_thread().
01655 { 01656 int res; 01657 01658 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law); 01659 if (res) { 01660 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno)); 01661 return -1; 01662 } 01663 01664 return 0; 01665 }
static int save_conference | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1700 of file chan_dahdi.c.
References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_callwait(), and dahdi_handle_event().
01701 { 01702 struct dahdi_confinfo c; 01703 int res; 01704 if (p->saveconf.confmode) { 01705 ast_log(LOG_WARNING, "Can't save conference -- already in use\n"); 01706 return -1; 01707 } 01708 p->saveconf.chan = 0; 01709 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf); 01710 if (res) { 01711 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno)); 01712 p->saveconf.confmode = 0; 01713 return -1; 01714 } 01715 c.chan = 0; 01716 c.confno = 0; 01717 c.confmode = DAHDI_CONF_NORMAL; 01718 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c); 01719 if (res) { 01720 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno)); 01721 return -1; 01722 } 01723 if (option_debug) 01724 ast_log(LOG_DEBUG, "Disabled conferencing\n"); 01725 return 0; 01726 }
static int send_callerid | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1768 of file chan_dahdi.c.
References ast_log(), dahdi_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), errno, free, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.
Referenced by dahdi_call(), dahdi_callwait(), dahdi_read(), and send_cwcidspill().
01769 { 01770 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */ 01771 int res; 01772 /* Take out of linear mode if necessary */ 01773 if (p->subs[SUB_REAL].linear) { 01774 p->subs[SUB_REAL].linear = 0; 01775 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0); 01776 } 01777 while (p->cidpos < p->cidlen) { 01778 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos); 01779 if (res < 0) { 01780 if (errno == EAGAIN) 01781 return 0; 01782 else { 01783 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno)); 01784 return -1; 01785 } 01786 } 01787 if (!res) 01788 return 0; 01789 p->cidpos += res; 01790 } 01791 free(p->cidspill); 01792 p->cidspill = NULL; 01793 if (p->callwaitcas) { 01794 /* Wait for CID/CW to expire */ 01795 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES; 01796 } else 01797 restore_conference(p); 01798 return 0; 01799 }
static int send_cwcidspill | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1746 of file chan_dahdi.c.
References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verbose(), 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, option_verbose, READ_SIZE, send_callerid(), and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_dtmfup().
01747 { 01748 p->callwaitcas = 0; 01749 p->cidcwexpire = 0; 01750 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) 01751 return -1; 01752 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p)); 01753 /* Make sure we account for the end */ 01754 p->cidlen += READ_SIZE * 4; 01755 p->cidpos = 0; 01756 send_callerid(p); 01757 if (option_verbose > 2) 01758 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num); 01759 return 0; 01760 }
static int set_actual_gain | ( | int | fd, | |
int | chan, | |||
float | rxgain, | |||
float | txgain, | |||
int | law | |||
) | [static] |
Definition at line 1635 of file chan_dahdi.c.
References set_actual_rxgain(), and set_actual_txgain().
Referenced by bump_gains(), dahdi_call(), and restore_gains().
01636 { 01637 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law); 01638 }
static int set_actual_rxgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1617 of file chan_dahdi.c.
References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.
Referenced by dahdi_setoption(), and set_actual_gain().
01618 { 01619 struct dahdi_gains g; 01620 int res; 01621 01622 memset(&g, 0, sizeof(g)); 01623 g.chan = chan; 01624 res = ioctl(fd, DAHDI_GETGAINS, &g); 01625 if (res) { 01626 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01627 return res; 01628 } 01629 01630 fill_rxgain(&g, gain, law); 01631 01632 return ioctl(fd, DAHDI_SETGAINS, &g); 01633 }
static int set_actual_txgain | ( | int | fd, | |
int | chan, | |||
float | gain, | |||
int | law | |||
) | [static] |
Definition at line 1598 of file chan_dahdi.c.
References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.
Referenced by dahdi_setoption(), and set_actual_gain().
01599 { 01600 struct dahdi_gains g; 01601 int res; 01602 01603 memset(&g, 0, sizeof(g)); 01604 g.chan = chan; 01605 res = ioctl(fd, DAHDI_GETGAINS, &g); 01606 if (res) { 01607 if (option_debug) 01608 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno)); 01609 return res; 01610 } 01611 01612 fill_txgain(&g, gain, law); 01613 01614 return ioctl(fd, DAHDI_SETGAINS, &g); 01615 }
static int setup_dahdi | ( | int | reload | ) | [static] |
Definition at line 11715 of file chan_dahdi.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), CHAN_ZAP_MODE, dahdi_chan_conf_default(), dahdi_chan_mode, default_jbconf, global_jbconf, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, option_verbose, process_dahdi(), restart_monitor(), ast_variable::value, and VERBOSE_PREFIX_2.
Referenced by dahdi_restart(), load_module(), and reload().
11716 { 11717 struct ast_config *cfg; 11718 struct ast_variable *v; 11719 struct dahdi_chan_conf conf = dahdi_chan_conf_default(); 11720 int res; 11721 11722 #ifdef HAVE_PRI 11723 char *c; 11724 int spanno; 11725 int i, x; 11726 int logicalspan; 11727 int trunkgroup; 11728 int dchannels[NUM_DCHANS]; 11729 #endif 11730 11731 #ifdef HAVE_ZAPTEL 11732 int load_from_zapata_conf = 1; 11733 #else 11734 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE); 11735 #endif 11736 11737 if (load_from_zapata_conf) { 11738 if (!(cfg = ast_config_load("zapata.conf"))) { 11739 ast_log(LOG_ERROR, "Unable to load zapata.conf\n"); 11740 return 0; 11741 } 11742 } else { 11743 if (!(cfg = ast_config_load("chan_dahdi.conf"))) { 11744 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n"); 11745 return 0; 11746 } 11747 } 11748 11749 /* It's a little silly to lock it, but we mind as well just to be sure */ 11750 ast_mutex_lock(&iflock); 11751 #ifdef HAVE_PRI 11752 if (reload != 1) { 11753 /* Process trunkgroups first */ 11754 v = ast_variable_browse(cfg, "trunkgroups"); 11755 while (v) { 11756 if (!strcasecmp(v->name, "trunkgroup")) { 11757 trunkgroup = atoi(v->value); 11758 if (trunkgroup > 0) { 11759 if ((c = strchr(v->value, ','))) { 11760 i = 0; 11761 memset(dchannels, 0, sizeof(dchannels)); 11762 while (c && (i < NUM_DCHANS)) { 11763 dchannels[i] = atoi(c + 1); 11764 if (dchannels[i] < 0) { 11765 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); 11766 } else 11767 i++; 11768 c = strchr(c + 1, ','); 11769 } 11770 if (i) { 11771 if (pri_create_trunkgroup(trunkgroup, dchannels)) { 11772 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); 11773 } else if (option_verbose > 1) 11774 ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s"); 11775 } else 11776 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 11777 } else 11778 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno); 11779 } else 11780 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno); 11781 } else if (!strcasecmp(v->name, "spanmap")) { 11782 spanno = atoi(v->value); 11783 if (spanno > 0) { 11784 if ((c = strchr(v->value, ','))) { 11785 trunkgroup = atoi(c + 1); 11786 if (trunkgroup > 0) { 11787 if ((c = strchr(c + 1, ','))) 11788 logicalspan = atoi(c + 1); 11789 else 11790 logicalspan = 0; 11791 if (logicalspan >= 0) { 11792 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) { 11793 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 11794 } else if (option_verbose > 1) 11795 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan); 11796 } else 11797 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); 11798 } else 11799 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno); 11800 } else 11801 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno); 11802 } else 11803 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno); 11804 } else { 11805 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name); 11806 } 11807 v = v->next; 11808 } 11809 } 11810 #endif 11811 11812 /* Copy the default jb config over global_jbconf */ 11813 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 11814 11815 v = ast_variable_browse(cfg, "channels"); 11816 res = process_dahdi(&conf, "", v, reload, 0); 11817 ast_mutex_unlock(&iflock); 11818 ast_config_destroy(cfg); 11819 if (res) 11820 return res; 11821 cfg = ast_config_load("users.conf"); 11822 if (cfg) { 11823 char *cat; 11824 const char *chans; 11825 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1); 11826 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) { 11827 if (!strcasecmp(cat, "general")) 11828 continue; 11829 chans = ast_variable_retrieve(cfg, cat, "dahdichan"); 11830 if (!ast_strlen_zero(chans)) { 11831 struct dahdi_chan_conf sect_conf; 11832 memcpy(§_conf, &conf, sizeof(sect_conf)); 11833 11834 process_dahdi(§_conf, cat, ast_variable_browse(cfg, cat), reload, 0); 11835 } 11836 } 11837 ast_config_destroy(cfg); 11838 } 11839 #ifdef HAVE_PRI 11840 if (reload != 1) { 11841 for (x = 0; x < NUM_SPANS; x++) { 11842 if (pris[x].pvts[0]) { 11843 if (start_pri(pris + x)) { 11844 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1); 11845 return -1; 11846 } else if (option_verbose > 1) 11847 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1); 11848 } 11849 } 11850 } 11851 #endif 11852 /* And start the monitor for the first time */ 11853 restart_monitor(); 11854 return 0; 11855 }
static void * ss_thread | ( | void * | data | ) | [static] |
Definition at line 5561 of file chan_dahdi.c.
References ast_channel::_state, alloc_sub(), ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_db_put(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, 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_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, dahdi_pvt::cid_name, 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, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_chan_name, dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dnd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, dahdi_pvt::exten, exten, f, free, func, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, dahdi_pvt::lastcid_num, len, dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, manager_event(), my_getsigstr(), name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), quit, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, 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, strsep(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, 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, dahdi_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.
Referenced by dahdi_handle_event(), and handle_init_event().
05562 { 05563 struct ast_channel *chan = data; 05564 struct dahdi_pvt *p = chan->tech_pvt; 05565 char exten[AST_MAX_EXTENSION] = ""; 05566 char exten2[AST_MAX_EXTENSION] = ""; 05567 unsigned char buf[256]; 05568 char dtmfcid[300]; 05569 char dtmfbuf[300]; 05570 struct callerid_state *cs = NULL; 05571 char *name = NULL, *number = NULL; 05572 int distMatches; 05573 int curRingData[3]; 05574 int receivedRingT; 05575 int counter1; 05576 int counter; 05577 int samples = 0; 05578 struct ast_smdi_md_message *smdi_msg = NULL; 05579 int flags; 05580 int i; 05581 int timeout; 05582 int getforward = 0; 05583 char *s1, *s2; 05584 int len = 0; 05585 int res; 05586 int index; 05587 05588 ast_mutex_lock(&ss_thread_lock); 05589 ss_thread_count++; 05590 ast_mutex_unlock(&ss_thread_lock); 05591 /* in the bizarre case where the channel has become a zombie before we 05592 even get started here, abort safely 05593 */ 05594 if (!p) { 05595 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name); 05596 ast_hangup(chan); 05597 goto quit; 05598 } 05599 if (option_verbose > 2) 05600 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name); 05601 index = dahdi_get_index(chan, p, 1); 05602 if (index < 0) { 05603 ast_log(LOG_WARNING, "Huh?\n"); 05604 ast_hangup(chan); 05605 goto quit; 05606 } 05607 if (p->dsp) 05608 ast_dsp_digitreset(p->dsp); 05609 switch (p->sig) { 05610 #ifdef HAVE_PRI 05611 case SIG_PRI: 05612 /* Now loop looking for an extension */ 05613 ast_copy_string(exten, p->exten, sizeof(exten)); 05614 len = strlen(exten); 05615 res = 0; 05616 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 05617 if (len && !ast_ignore_pattern(chan->context, exten)) 05618 tone_zone_play_tone(p->subs[index].dfd, -1); 05619 else 05620 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05621 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) 05622 timeout = matchdigittimeout; 05623 else 05624 timeout = gendigittimeout; 05625 res = ast_waitfordigit(chan, timeout); 05626 if (res < 0) { 05627 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05628 ast_hangup(chan); 05629 goto quit; 05630 } else if (res) { 05631 exten[len++] = res; 05632 exten[len] = '\0'; 05633 } else 05634 break; 05635 } 05636 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */ 05637 if (ast_strlen_zero(exten)) { 05638 if (option_verbose > 2) 05639 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n"); 05640 exten[0] = 's'; 05641 exten[1] = '\0'; 05642 } 05643 tone_zone_play_tone(p->subs[index].dfd, -1); 05644 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) { 05645 /* Start the real PBX */ 05646 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05647 if (p->dsp) ast_dsp_digitreset(p->dsp); 05648 dahdi_enable_ec(p); 05649 ast_setstate(chan, AST_STATE_RING); 05650 res = ast_pbx_run(chan); 05651 if (res) { 05652 ast_log(LOG_WARNING, "PBX exited non-zero!\n"); 05653 } 05654 } else { 05655 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); 05656 chan->hangupcause = AST_CAUSE_UNALLOCATED; 05657 ast_hangup(chan); 05658 p->exten[0] = '\0'; 05659 /* Since we send release complete here, we won't get one */ 05660 p->call = NULL; 05661 } 05662 goto quit; 05663 break; 05664 #endif 05665 case SIG_FEATD: 05666 case SIG_FEATDMF: 05667 case SIG_FEATDMF_TA: 05668 case SIG_E911: 05669 case SIG_FGC_CAMAMF: 05670 case SIG_FEATB: 05671 case SIG_EMWINK: 05672 case SIG_SF_FEATD: 05673 case SIG_SF_FEATDMF: 05674 case SIG_SF_FEATB: 05675 case SIG_SFWINK: 05676 if (dahdi_wink(p, index)) 05677 goto quit; 05678 /* Fall through */ 05679 case SIG_EM: 05680 case SIG_EM_E1: 05681 case SIG_SF: 05682 case SIG_FGC_CAMA: 05683 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05684 if (p->dsp) 05685 ast_dsp_digitreset(p->dsp); 05686 /* set digit mode appropriately */ 05687 if (p->dsp) { 05688 if (NEED_MFDETECT(p)) 05689 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 05690 else 05691 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 05692 } 05693 memset(dtmfbuf, 0, sizeof(dtmfbuf)); 05694 /* Wait for the first digit only if immediate=no */ 05695 if (!p->immediate) 05696 /* Wait for the first digit (up to 5 seconds). */ 05697 res = ast_waitfordigit(chan, 5000); 05698 else 05699 res = 0; 05700 if (res > 0) { 05701 /* save first char */ 05702 dtmfbuf[0] = res; 05703 switch (p->sig) { 05704 case SIG_FEATD: 05705 case SIG_SF_FEATD: 05706 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 05707 if (res > 0) 05708 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 05709 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05710 break; 05711 case SIG_FEATDMF_TA: 05712 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05713 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05714 if (dahdi_wink(p, index)) goto quit; 05715 dtmfbuf[0] = 0; 05716 /* Wait for the first digit (up to 5 seconds). */ 05717 res = ast_waitfordigit(chan, 5000); 05718 if (res <= 0) break; 05719 dtmfbuf[0] = res; 05720 /* fall through intentionally */ 05721 case SIG_FEATDMF: 05722 case SIG_E911: 05723 case SIG_FGC_CAMAMF: 05724 case SIG_SF_FEATDMF: 05725 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05726 /* if international caca, do it again to get real ANO */ 05727 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14)) 05728 { 05729 if (dahdi_wink(p, index)) goto quit; 05730 dtmfbuf[0] = 0; 05731 /* Wait for the first digit (up to 5 seconds). */ 05732 res = ast_waitfordigit(chan, 5000); 05733 if (res <= 0) break; 05734 dtmfbuf[0] = res; 05735 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05736 } 05737 if (res > 0) { 05738 /* if E911, take off hook */ 05739 if (p->sig == SIG_E911) 05740 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05741 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000); 05742 } 05743 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05744 break; 05745 case SIG_FEATB: 05746 case SIG_SF_FEATB: 05747 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000); 05748 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05749 break; 05750 case SIG_EMWINK: 05751 /* if we received a '*', we are actually receiving Feature Group D 05752 dial syntax, so use that mode; otherwise, fall through to normal 05753 mode 05754 */ 05755 if (res == '*') { 05756 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000); 05757 if (res > 0) 05758 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000); 05759 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp); 05760 break; 05761 } 05762 default: 05763 /* If we got the first digit, get the rest */ 05764 len = 1; 05765 dtmfbuf[len] = '\0'; 05766 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 05767 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) { 05768 timeout = matchdigittimeout; 05769 } else { 05770 timeout = gendigittimeout; 05771 } 05772 res = ast_waitfordigit(chan, timeout); 05773 if (res < 0) { 05774 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05775 ast_hangup(chan); 05776 goto quit; 05777 } else if (res) { 05778 dtmfbuf[len++] = res; 05779 dtmfbuf[len] = '\0'; 05780 } else { 05781 break; 05782 } 05783 } 05784 break; 05785 } 05786 } 05787 if (res == -1) { 05788 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno)); 05789 ast_hangup(chan); 05790 goto quit; 05791 } else if (res < 0) { 05792 ast_log(LOG_DEBUG, "Got hung up before digits finished\n"); 05793 ast_hangup(chan); 05794 goto quit; 05795 } 05796 05797 if (p->sig == SIG_FGC_CAMA) { 05798 char anibuf[100]; 05799 05800 if (ast_safe_sleep(chan,1000) == -1) { 05801 ast_hangup(chan); 05802 goto quit; 05803 } 05804 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 05805 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 05806 res = my_getsigstr(chan, anibuf, "#", 10000); 05807 if ((res > 0) && (strlen(anibuf) > 2)) { 05808 if (anibuf[strlen(anibuf) - 1] == '#') 05809 anibuf[strlen(anibuf) - 1] = 0; 05810 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2); 05811 } 05812 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 05813 } 05814 05815 ast_copy_string(exten, dtmfbuf, sizeof(exten)); 05816 if (ast_strlen_zero(exten)) 05817 ast_copy_string(exten, "s", sizeof(exten)); 05818 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) { 05819 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */ 05820 if (exten[0] == '*') { 05821 char *stringp=NULL; 05822 ast_copy_string(exten2, exten, sizeof(exten2)); 05823 /* Parse out extension and callerid */ 05824 stringp=exten2 +1; 05825 s1 = strsep(&stringp, "*"); 05826 s2 = strsep(&stringp, "*"); 05827 if (s2) { 05828 if (!ast_strlen_zero(p->cid_num)) 05829 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 05830 else 05831 ast_set_callerid(chan, s1, NULL, s1); 05832 ast_copy_string(exten, s2, sizeof(exten)); 05833 } else 05834 ast_copy_string(exten, s1, sizeof(exten)); 05835 } else if (p->sig == SIG_FEATD) 05836 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 05837 } 05838 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 05839 if (exten[0] == '*') { 05840 char *stringp=NULL; 05841 ast_copy_string(exten2, exten, sizeof(exten2)); 05842 /* Parse out extension and callerid */ 05843 stringp=exten2 +1; 05844 s1 = strsep(&stringp, "#"); 05845 s2 = strsep(&stringp, "#"); 05846 if (s2) { 05847 if (!ast_strlen_zero(p->cid_num)) 05848 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 05849 else 05850 if (*(s1 + 2)) 05851 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2); 05852 ast_copy_string(exten, s2 + 1, sizeof(exten)); 05853 } else 05854 ast_copy_string(exten, s1 + 2, sizeof(exten)); 05855 } else 05856 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel); 05857 } 05858 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) { 05859 if (exten[0] == '*') { 05860 char *stringp=NULL; 05861 ast_copy_string(exten2, exten, sizeof(exten2)); 05862 /* Parse out extension and callerid */ 05863 stringp=exten2 +1; 05864 s1 = strsep(&stringp, "#"); 05865 s2 = strsep(&stringp, "#"); 05866 if (s2 && (*(s2 + 1) == '0')) { 05867 if (*(s2 + 2)) 05868 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2); 05869 } 05870 if (s1) ast_copy_string(exten, s1, sizeof(exten)); 05871 else ast_copy_string(exten, "911", sizeof(exten)); 05872 } else 05873 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel); 05874 } 05875 if (p->sig == SIG_FEATB) { 05876 if (exten[0] == '*') { 05877 char *stringp=NULL; 05878 ast_copy_string(exten2, exten, sizeof(exten2)); 05879 /* Parse out extension and callerid */ 05880 stringp=exten2 +1; 05881 s1 = strsep(&stringp, "#"); 05882 ast_copy_string(exten, exten2 + 1, sizeof(exten)); 05883 } else 05884 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel); 05885 } 05886 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) { 05887 dahdi_wink(p, index); 05888 /* some switches require a minimum guard time between 05889 the last FGD wink and something that answers 05890 immediately. This ensures it */ 05891 if (ast_safe_sleep(chan,100)) goto quit; 05892 } 05893 dahdi_enable_ec(p); 05894 if (NEED_MFDETECT(p)) { 05895 if (p->dsp) { 05896 if (!p->hardwaredtmf) 05897 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 05898 else { 05899 ast_dsp_free(p->dsp); 05900 p->dsp = NULL; 05901 } 05902 } 05903 } 05904 05905 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) { 05906 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05907 if (p->dsp) ast_dsp_digitreset(p->dsp); 05908 res = ast_pbx_run(chan); 05909 if (res) { 05910 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 05911 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05912 } 05913 goto quit; 05914 } else { 05915 if (option_verbose > 2) 05916 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context); 05917 sleep(2); 05918 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO); 05919 if (res < 0) 05920 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel); 05921 else 05922 sleep(1); 05923 res = ast_streamfile(chan, "ss-noservice", chan->language); 05924 if (res >= 0) 05925 ast_waitstream(chan, ""); 05926 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05927 ast_hangup(chan); 05928 goto quit; 05929 } 05930 break; 05931 case SIG_FXOLS: 05932 case SIG_FXOGS: 05933 case SIG_FXOKS: 05934 /* Read the first digit */ 05935 timeout = firstdigittimeout; 05936 /* If starting a threeway call, never timeout on the first digit so someone 05937 can use flash-hook as a "hold" feature */ 05938 if (p->subs[SUB_THREEWAY].owner) 05939 timeout = 999999; 05940 while (len < AST_MAX_EXTENSION-1) { 05941 /* Read digit unless it's supposed to be immediate, in which case the 05942 only answer is 's' */ 05943 if (p->immediate) 05944 res = 's'; 05945 else 05946 res = ast_waitfordigit(chan, timeout); 05947 timeout = 0; 05948 if (res < 0) { 05949 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); 05950 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05951 ast_hangup(chan); 05952 goto quit; 05953 } else if (res) { 05954 exten[len++]=res; 05955 exten[len] = '\0'; 05956 } 05957 if (!ast_ignore_pattern(chan->context, exten)) 05958 tone_zone_play_tone(p->subs[index].dfd, -1); 05959 else 05960 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05961 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) { 05962 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) { 05963 if (getforward) { 05964 /* Record this as the forwarding extension */ 05965 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 05966 if (option_verbose > 2) 05967 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel); 05968 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 05969 if (res) 05970 break; 05971 usleep(500000); 05972 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05973 sleep(1); 05974 memset(exten, 0, sizeof(exten)); 05975 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE); 05976 len = 0; 05977 getforward = 0; 05978 } else { 05979 res = tone_zone_play_tone(p->subs[index].dfd, -1); 05980 ast_copy_string(chan->exten, exten, sizeof(chan->exten)); 05981 if (!ast_strlen_zero(p->cid_num)) { 05982 if (!p->hidecallerid) 05983 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 05984 else 05985 ast_set_callerid(chan, NULL, NULL, p->cid_num); 05986 } 05987 if (!ast_strlen_zero(p->cid_name)) { 05988 if (!p->hidecallerid) 05989 ast_set_callerid(chan, NULL, p->cid_name, NULL); 05990 } 05991 ast_setstate(chan, AST_STATE_RING); 05992 dahdi_enable_ec(p); 05993 res = ast_pbx_run(chan); 05994 if (res) { 05995 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 05996 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 05997 } 05998 goto quit; 05999 } 06000 } else { 06001 /* It's a match, but they just typed a digit, and there is an ambiguous match, 06002 so just set the timeout to matchdigittimeout and wait some more */ 06003 timeout = matchdigittimeout; 06004 } 06005 } else if (res == 0) { 06006 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n"); 06007 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06008 dahdi_wait_event(p->subs[index].dfd); 06009 ast_hangup(chan); 06010 goto quit; 06011 } else if (p->callwaiting && !strcmp(exten, "*70")) { 06012 if (option_verbose > 2) 06013 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name); 06014 /* Disable call waiting if enabled */ 06015 p->callwaiting = 0; 06016 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06017 if (res) { 06018 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06019 chan->name, strerror(errno)); 06020 } 06021 len = 0; 06022 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len); 06023 memset(exten, 0, sizeof(exten)); 06024 timeout = firstdigittimeout; 06025 06026 } else if (!strcmp(exten,ast_pickup_ext())) { 06027 /* Scan all channels and see if there are any 06028 * ringing channels that have call groups 06029 * that equal this channels pickup group 06030 */ 06031 if (index == SUB_REAL) { 06032 /* Switch us from Third call to Call Wait */ 06033 if (p->subs[SUB_THREEWAY].owner) { 06034 /* If you make a threeway call and the *8# a call, it should actually 06035 look like a callwait */ 06036 alloc_sub(p, SUB_CALLWAIT); 06037 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY); 06038 unalloc_sub(p, SUB_THREEWAY); 06039 } 06040 dahdi_enable_ec(p); 06041 if (ast_pickup_call(chan)) { 06042 ast_log(LOG_DEBUG, "No call pickup possible...\n"); 06043 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06044 dahdi_wait_event(p->subs[index].dfd); 06045 } 06046 ast_hangup(chan); 06047 goto quit; 06048 } else { 06049 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n"); 06050 ast_hangup(chan); 06051 goto quit; 06052 } 06053 06054 } else if (!p->hidecallerid && !strcmp(exten, "*67")) { 06055 if (option_verbose > 2) 06056 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name); 06057 /* Disable Caller*ID if enabled */ 06058 p->hidecallerid = 1; 06059 if (chan->cid.cid_num) 06060 free(chan->cid.cid_num); 06061 chan->cid.cid_num = NULL; 06062 if (chan->cid.cid_name) 06063 free(chan->cid.cid_name); 06064 chan->cid.cid_name = NULL; 06065 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06066 if (res) { 06067 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06068 chan->name, strerror(errno)); 06069 } 06070 len = 0; 06071 memset(exten, 0, sizeof(exten)); 06072 timeout = firstdigittimeout; 06073 } else if (p->callreturn && !strcmp(exten, "*69")) { 06074 res = 0; 06075 if (!ast_strlen_zero(p->lastcid_num)) { 06076 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language); 06077 } 06078 if (!res) 06079 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06080 break; 06081 } else if (!strcmp(exten, "*78")) { 06082 /* Do not disturb */ 06083 if (option_verbose > 2) 06084 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel); 06085 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06086 "Channel: %s/%d\r\n" 06087 "Status: enabled\r\n", dahdi_chan_name, p->channel); 06088 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06089 p->dnd = 1; 06090 getforward = 0; 06091 memset(exten, 0, sizeof(exten)); 06092 len = 0; 06093 } else if (!strcmp(exten, "*79")) { 06094 /* Do not disturb */ 06095 if (option_verbose > 2) 06096 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel); 06097 manager_event(EVENT_FLAG_SYSTEM, "DNDState", 06098 "Channel: %s/%d\r\n" 06099 "Status: disabled\r\n", dahdi_chan_name, p->channel); 06100 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06101 p->dnd = 0; 06102 getforward = 0; 06103 memset(exten, 0, sizeof(exten)); 06104 len = 0; 06105 } else if (p->cancallforward && !strcmp(exten, "*72")) { 06106 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06107 getforward = 1; 06108 memset(exten, 0, sizeof(exten)); 06109 len = 0; 06110 } else if (p->cancallforward && !strcmp(exten, "*73")) { 06111 if (option_verbose > 2) 06112 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel); 06113 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06114 memset(p->call_forward, 0, sizeof(p->call_forward)); 06115 getforward = 0; 06116 memset(exten, 0, sizeof(exten)); 06117 len = 0; 06118 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 06119 p->subs[SUB_THREEWAY].owner && 06120 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { 06121 /* This is a three way call, the main call being a real channel, 06122 and we're parking the first call. */ 06123 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL); 06124 if (option_verbose > 2) 06125 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name); 06126 break; 06127 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) { 06128 if (option_verbose > 2) 06129 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num); 06130 res = ast_db_put("blacklist", p->lastcid_num, "1"); 06131 if (!res) { 06132 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06133 memset(exten, 0, sizeof(exten)); 06134 len = 0; 06135 } 06136 } else if (p->hidecallerid && !strcmp(exten, "*82")) { 06137 if (option_verbose > 2) 06138 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name); 06139 /* Enable Caller*ID if enabled */ 06140 p->hidecallerid = 0; 06141 if (chan->cid.cid_num) 06142 free(chan->cid.cid_num); 06143 chan->cid.cid_num = NULL; 06144 if (chan->cid.cid_name) 06145 free(chan->cid.cid_name); 06146 chan->cid.cid_name = NULL; 06147 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL); 06148 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL); 06149 if (res) { 06150 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 06151 chan->name, strerror(errno)); 06152 } 06153 len = 0; 06154 memset(exten, 0, sizeof(exten)); 06155 timeout = firstdigittimeout; 06156 } else if (!strcmp(exten, "*0")) { 06157 struct ast_channel *nbridge = 06158 p->subs[SUB_THREEWAY].owner; 06159 struct dahdi_pvt *pbridge = NULL; 06160 /* set up the private struct of the bridged one, if any */ 06161 if (nbridge && ast_bridged_channel(nbridge)) 06162 pbridge = ast_bridged_channel(nbridge)->tech_pvt; 06163 if (nbridge && pbridge && 06164 (nbridge->tech == chan_tech) && 06165 (ast_bridged_channel(nbridge)->tech == chan_tech) && 06166 ISTRUNK(pbridge)) { 06167 int func = DAHDI_FLASH; 06168 /* Clear out the dial buffer */ 06169 p->dop.dialstr[0] = '\0'; 06170 /* flash hookswitch */ 06171 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { 06172 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 06173 nbridge->name, strerror(errno)); 06174 } 06175 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06176 unalloc_sub(p, SUB_THREEWAY); 06177 p->owner = p->subs[SUB_REAL].owner; 06178 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) 06179 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); 06180 ast_hangup(chan); 06181 goto quit; 06182 } else { 06183 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06184 dahdi_wait_event(p->subs[index].dfd); 06185 tone_zone_play_tone(p->subs[index].dfd, -1); 06186 swap_subs(p, SUB_REAL, SUB_THREEWAY); 06187 unalloc_sub(p, SUB_THREEWAY); 06188 p->owner = p->subs[SUB_REAL].owner; 06189 ast_hangup(chan); 06190 goto quit; 06191 } 06192 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && 06193 ((exten[0] != '*') || (strlen(exten) > 2))) { 06194 if (option_debug) 06195 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context); 06196 break; 06197 } 06198 if (!timeout) 06199 timeout = gendigittimeout; 06200 if (len && !ast_ignore_pattern(chan->context, exten)) 06201 tone_zone_play_tone(p->subs[index].dfd, -1); 06202 } 06203 break; 06204 case SIG_FXSLS: 06205 case SIG_FXSGS: 06206 case SIG_FXSKS: 06207 #ifdef HAVE_PRI 06208 if (p->pri) { 06209 /* This is a GR-303 trunk actually. Wait for the first ring... */ 06210 struct ast_frame *f; 06211 int res; 06212 time_t start; 06213 06214 time(&start); 06215 ast_setstate(chan, AST_STATE_RING); 06216 while (time(NULL) < start + 3) { 06217 res = ast_waitfor(chan, 1000); 06218 if (res) { 06219 f = ast_read(chan); 06220 if (!f) { 06221 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n"); 06222 ast_hangup(chan); 06223 goto quit; 06224 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) { 06225 res = 1; 06226 } else 06227 res = 0; 06228 ast_frfree(f); 06229 if (res) { 06230 ast_log(LOG_DEBUG, "Got ring!\n"); 06231 res = 0; 06232 break; 06233 } 06234 } 06235 } 06236 } 06237 #endif 06238 /* check for SMDI messages */ 06239 if (p->use_smdi && p->smdi_iface) { 06240 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); 06241 06242 if (smdi_msg != NULL) { 06243 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten)); 06244 06245 if (smdi_msg->type == 'B') 06246 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b"); 06247 else if (smdi_msg->type == 'N') 06248 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u"); 06249 06250 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name); 06251 } else { 06252 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); 06253 } 06254 } 06255 06256 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) { 06257 number = smdi_msg->calling_st; 06258 06259 /* If we want caller id, we're in a prering state due to a polarity reversal 06260 * and we're set to use a polarity reversal to trigger the start of caller id, 06261 * grab the caller id and wait for ringing to start... */ 06262 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) { 06263 /* If set to use DTMF CID signalling, listen for DTMF */ 06264 if (p->cid_signalling == CID_SIG_DTMF) { 06265 int i = 0; 06266 cs = NULL; 06267 ast_log(LOG_DEBUG, "Receiving DTMF cid on " 06268 "channel %s\n", chan->name); 06269 dahdi_setlinear(p->subs[index].dfd, 0); 06270 res = 2000; 06271 for (;;) { 06272 struct ast_frame *f; 06273 res = ast_waitfor(chan, res); 06274 if (res <= 0) { 06275 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. " 06276 "Exiting simple switch\n"); 06277 ast_hangup(chan); 06278 goto quit; 06279 } 06280 f = ast_read(chan); 06281 if (!f) 06282 break; 06283 if (f->frametype == AST_FRAME_DTMF) { 06284 dtmfbuf[i++] = f->subclass; 06285 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass); 06286 res = 2000; 06287 } 06288 ast_frfree(f); 06289 if (chan->_state == AST_STATE_RING || 06290 chan->_state == AST_STATE_RINGING) 06291 break; /* Got ring */ 06292 } 06293 dtmfbuf[i] = '\0'; 06294 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06295 /* Got cid and ring. */ 06296 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf); 06297 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); 06298 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 06299 dtmfcid, flags); 06300 /* If first byte is NULL, we have no cid */ 06301 if (!ast_strlen_zero(dtmfcid)) 06302 number = dtmfcid; 06303 else 06304 number = NULL; 06305 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ 06306 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { 06307 cs = callerid_new(p->cid_signalling); 06308 if (cs) { 06309 samples = 0; 06310 #if 1 06311 bump_gains(p); 06312 #endif 06313 /* Take out of linear mode for Caller*ID processing */ 06314 dahdi_setlinear(p->subs[index].dfd, 0); 06315 06316 /* First we wait and listen for the Caller*ID */ 06317 for (;;) { 06318 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06319 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06320 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06321 callerid_free(cs); 06322 ast_hangup(chan); 06323 goto quit; 06324 } 06325 if (i & DAHDI_IOMUX_SIGEVENT) { 06326 res = dahdi_get_event(p->subs[index].dfd); 06327 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06328 06329 if (p->cid_signalling == CID_SIG_V23_JP) { 06330 #ifdef DAHDI_EVENT_RINGBEGIN 06331 if (res == DAHDI_EVENT_RINGBEGIN) { 06332 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); 06333 usleep(1); 06334 } 06335 #endif 06336 } else { 06337 res = 0; 06338 break; 06339 } 06340 } else if (i & DAHDI_IOMUX_READ) { 06341 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06342 if (res < 0) { 06343 if (errno != ELAST) { 06344 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06345 callerid_free(cs); 06346 ast_hangup(chan); 06347 goto quit; 06348 } 06349 break; 06350 } 06351 samples += res; 06352 06353 if (p->cid_signalling == CID_SIG_V23_JP) { 06354 res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); 06355 } else { 06356 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06357 } 06358 06359 if (res < 0) { 06360 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); 06361 break; 06362 } else if (res) 06363 break; 06364 else if (samples > (8000 * 10)) 06365 break; 06366 } 06367 } 06368 if (res == 1) { 06369 callerid_get(cs, &name, &number, &flags); 06370 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06371 } 06372 06373 if (p->cid_signalling == CID_SIG_V23_JP) { 06374 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK); 06375 usleep(1); 06376 res = 4000; 06377 } else { 06378 06379 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 06380 res = 2000; 06381 } 06382 06383 for (;;) { 06384 struct ast_frame *f; 06385 res = ast_waitfor(chan, res); 06386 if (res <= 0) { 06387 ast_log(LOG_WARNING, "CID timed out waiting for ring. " 06388 "Exiting simple switch\n"); 06389 ast_hangup(chan); 06390 goto quit; 06391 } 06392 if (!(f = ast_read(chan))) { 06393 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); 06394 ast_hangup(chan); 06395 goto quit; 06396 } 06397 ast_frfree(f); 06398 if (chan->_state == AST_STATE_RING || 06399 chan->_state == AST_STATE_RINGING) 06400 break; /* Got ring */ 06401 } 06402 06403 /* We must have a ring by now, so, if configured, lets try to listen for 06404 * distinctive ringing */ 06405 if (p->usedistinctiveringdetection == 1) { 06406 len = 0; 06407 distMatches = 0; 06408 /* Clear the current ring data array so we dont have old data in it. */ 06409 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06410 curRingData[receivedRingT] = 0; 06411 receivedRingT = 0; 06412 counter = 0; 06413 counter1 = 0; 06414 /* Check to see if context is what it should be, if not set to be. */ 06415 if (strcmp(p->context,p->defcontext) != 0) { 06416 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06417 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06418 } 06419 06420 for (;;) { 06421 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06422 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06423 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06424 callerid_free(cs); 06425 ast_hangup(chan); 06426 goto quit; 06427 } 06428 if (i & DAHDI_IOMUX_SIGEVENT) { 06429 res = dahdi_get_event(p->subs[index].dfd); 06430 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06431 res = 0; 06432 /* Let us detect distinctive ring */ 06433 06434 curRingData[receivedRingT] = p->ringt; 06435 06436 if (p->ringt < p->ringt_base/2) 06437 break; 06438 /* Increment the ringT counter so we can match it against 06439 values in chan_dahdi.conf for distinctive ring */ 06440 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06441 break; 06442 } else if (i & DAHDI_IOMUX_READ) { 06443 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06444 if (res < 0) { 06445 if (errno != ELAST) { 06446 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06447 callerid_free(cs); 06448 ast_hangup(chan); 06449 goto quit; 06450 } 06451 break; 06452 } 06453 if (p->ringt) 06454 p->ringt--; 06455 if (p->ringt == 1) { 06456 res = -1; 06457 break; 06458 } 06459 } 06460 } 06461 if (option_verbose > 2) 06462 /* this only shows up if you have n of the dring patterns filled in */ 06463 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06464 06465 for (counter = 0; counter < 3; counter++) { 06466 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06467 channel */ 06468 distMatches = 0; 06469 for (counter1 = 0; counter1 < 3; counter1++) { 06470 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06471 (p->drings.ringnum[counter].ring[counter1]-10)) { 06472 distMatches++; 06473 } 06474 } 06475 if (distMatches == 3) { 06476 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06477 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06478 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06479 if (option_verbose > 2) 06480 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06481 break; 06482 } 06483 } 06484 } 06485 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06486 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06487 #if 1 06488 restore_gains(p); 06489 #endif 06490 } else 06491 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 06492 } else { 06493 ast_log(LOG_WARNING, "Channel %s in prering " 06494 "state, but I have nothing to do. " 06495 "Terminating simple switch, should be " 06496 "restarted by the actual ring.\n", 06497 chan->name); 06498 ast_hangup(chan); 06499 goto quit; 06500 } 06501 } else if (p->use_callerid && p->cid_start == CID_START_RING) { 06502 /* FSK Bell202 callerID */ 06503 cs = callerid_new(p->cid_signalling); 06504 if (cs) { 06505 #if 1 06506 bump_gains(p); 06507 #endif 06508 samples = 0; 06509 len = 0; 06510 distMatches = 0; 06511 /* Clear the current ring data array so we dont have old data in it. */ 06512 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) 06513 curRingData[receivedRingT] = 0; 06514 receivedRingT = 0; 06515 counter = 0; 06516 counter1 = 0; 06517 /* Check to see if context is what it should be, if not set to be. */ 06518 if (strcmp(p->context,p->defcontext) != 0) { 06519 ast_copy_string(p->context, p->defcontext, sizeof(p->context)); 06520 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); 06521 } 06522 06523 /* Take out of linear mode for Caller*ID processing */ 06524 dahdi_setlinear(p->subs[index].dfd, 0); 06525 for (;;) { 06526 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06527 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06528 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06529 callerid_free(cs); 06530 ast_hangup(chan); 06531 goto quit; 06532 } 06533 if (i & DAHDI_IOMUX_SIGEVENT) { 06534 res = dahdi_get_event(p->subs[index].dfd); 06535 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06536 /* If we get a PR event, they hung up while processing calerid */ 06537 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { 06538 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); 06539 p->polarity = POLARITY_IDLE; 06540 callerid_free(cs); 06541 ast_hangup(chan); 06542 goto quit; 06543 } 06544 res = 0; 06545 /* Let us detect callerid when the telco uses distinctive ring */ 06546 06547 curRingData[receivedRingT] = p->ringt; 06548 06549 if (p->ringt < p->ringt_base/2) 06550 break; 06551 /* Increment the ringT counter so we can match it against 06552 values in chan_dahdi.conf for distinctive ring */ 06553 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06554 break; 06555 } else if (i & DAHDI_IOMUX_READ) { 06556 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06557 if (res < 0) { 06558 if (errno != ELAST) { 06559 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06560 callerid_free(cs); 06561 ast_hangup(chan); 06562 goto quit; 06563 } 06564 break; 06565 } 06566 if (p->ringt) 06567 p->ringt--; 06568 if (p->ringt == 1) { 06569 res = -1; 06570 break; 06571 } 06572 samples += res; 06573 res = callerid_feed(cs, buf, res, AST_LAW(p)); 06574 if (res < 0) { 06575 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); 06576 break; 06577 } else if (res) 06578 break; 06579 else if (samples > (8000 * 10)) 06580 break; 06581 } 06582 } 06583 if (res == 1) { 06584 callerid_get(cs, &name, &number, &flags); 06585 if (option_debug) 06586 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); 06587 } 06588 if (distinctiveringaftercid == 1) { 06589 /* Clear the current ring data array so we dont have old data in it. */ 06590 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) { 06591 curRingData[receivedRingT] = 0; 06592 } 06593 receivedRingT = 0; 06594 if (option_verbose > 2) 06595 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n"); 06596 for (;;) { 06597 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; 06598 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { 06599 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); 06600 callerid_free(cs); 06601 ast_hangup(chan); 06602 goto quit; 06603 } 06604 if (i & DAHDI_IOMUX_SIGEVENT) { 06605 res = dahdi_get_event(p->subs[index].dfd); 06606 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); 06607 res = 0; 06608 /* Let us detect callerid when the telco uses distinctive ring */ 06609 06610 curRingData[receivedRingT] = p->ringt; 06611 06612 if (p->ringt < p->ringt_base/2) 06613 break; 06614 /* Increment the ringT counter so we can match it against 06615 values in chan_dahdi.conf for distinctive ring */ 06616 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) 06617 break; 06618 } else if (i & DAHDI_IOMUX_READ) { 06619 res = read(p->subs[index].dfd, buf, sizeof(buf)); 06620 if (res < 0) { 06621 if (errno != ELAST) { 06622 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); 06623 callerid_free(cs); 06624 ast_hangup(chan); 06625 goto quit; 06626 } 06627 break; 06628 } 06629 if (p->ringt) 06630 p->ringt--; 06631 if (p->ringt == 1) { 06632 res = -1; 06633 break; 06634 } 06635 } 06636 } 06637 } 06638 if (p->usedistinctiveringdetection == 1) { 06639 if (option_verbose > 2) 06640 /* this only shows up if you have n of the dring patterns filled in */ 06641 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]); 06642 06643 for (counter = 0; counter < 3; counter++) { 06644 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this 06645 channel */ 06646 if (option_verbose > 2) 06647 /* this only shows up if you have n of the dring patterns filled in */ 06648 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n", 06649 p->drings.ringnum[counter].ring[0], 06650 p->drings.ringnum[counter].ring[1], 06651 p->drings.ringnum[counter].ring[2]); 06652 distMatches = 0; 06653 for (counter1 = 0; counter1 < 3; counter1++) { 06654 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >= 06655 (p->drings.ringnum[counter].ring[counter1]-10)) { 06656 distMatches++; 06657 } 06658 } 06659 if (distMatches == 3) { 06660 /* The ring matches, set the context to whatever is for distinctive ring.. */ 06661 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); 06662 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); 06663 if (option_verbose > 2) 06664 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context); 06665 break; 06666 } 06667 } 06668 } 06669 /* Restore linear mode (if appropriate) for Caller*ID processing */ 06670 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); 06671 #if 1 06672 restore_gains(p); 06673 #endif 06674 if (res < 0) { 06675 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); 06676 } 06677 } else 06678 ast_log(LOG_WARNING, "Unable to get caller ID space\n"); 06679 } 06680 else 06681 cs = NULL; 06682 06683 if (number) 06684 ast_shrink_phone_number(number); 06685 ast_set_callerid(chan, number, name, number); 06686 06687 if (smdi_msg) 06688 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy); 06689 06690 if (cs) 06691 callerid_free(cs); 06692 06693 ast_setstate(chan, AST_STATE_RING); 06694 chan->rings = 1; 06695 p->ringt = p->ringt_base; 06696 res = ast_pbx_run(chan); 06697 if (res) { 06698 ast_hangup(chan); 06699 ast_log(LOG_WARNING, "PBX exited non-zero\n"); 06700 } 06701 goto quit; 06702 default: 06703 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel); 06704 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06705 if (res < 0) 06706 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 06707 } 06708 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION); 06709 if (res < 0) 06710 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel); 06711 ast_hangup(chan); 06712 quit: 06713 ast_mutex_lock(&ss_thread_lock); 06714 ss_thread_count--; 06715 ast_cond_signal(&ss_thread_complete); 06716 ast_mutex_unlock(&ss_thread_lock); 06717 return NULL; 06718 }
static void swap_subs | ( | struct dahdi_pvt * | p, | |
int | a, | |||
int | b | |||
) | [static] |
Definition at line 878 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::chan, dahdi_subchannel::dfd, ast_channel::fds, dahdi_subchannel::inthreeway, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().
Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().
00879 { 00880 int tchan; 00881 int tinthreeway; 00882 struct ast_channel *towner; 00883 00884 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b); 00885 00886 tchan = p->subs[a].chan; 00887 towner = p->subs[a].owner; 00888 tinthreeway = p->subs[a].inthreeway; 00889 00890 p->subs[a].chan = p->subs[b].chan; 00891 p->subs[a].owner = p->subs[b].owner; 00892 p->subs[a].inthreeway = p->subs[b].inthreeway; 00893 00894 p->subs[b].chan = tchan; 00895 p->subs[b].owner = towner; 00896 p->subs[b].inthreeway = tinthreeway; 00897 00898 if (p->subs[a].owner) 00899 p->subs[a].owner->fds[0] = p->subs[a].dfd; 00900 if (p->subs[b].owner) 00901 p->subs[b].owner->fds[0] = p->subs[b].dfd; 00902 wakeup_sub(p, a, NULL); 00903 wakeup_sub(p, b, NULL); 00904 }
static int unalloc_sub | ( | struct dahdi_pvt * | p, | |
int | x | |||
) | [static] |
Definition at line 1025 of file chan_dahdi.c.
References ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_DEBUG, 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().
01026 { 01027 if (!x) { 01028 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel); 01029 return -1; 01030 } 01031 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel); 01032 dahdi_close_sub(p, x); 01033 p->subs[x].linear = 0; 01034 p->subs[x].chan = 0; 01035 p->subs[x].owner = NULL; 01036 p->subs[x].inthreeway = 0; 01037 p->polarity = POLARITY_IDLE; 01038 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf)); 01039 return 0; 01040 }
static int unload_module | ( | void | ) | [static] |
Definition at line 10900 of file chan_dahdi.c.
References __unload_module(), ast_mutex_destroy(), and lock.
10901 { 10902 #ifdef HAVE_PRI 10903 int y; 10904 for (y = 0; y < NUM_SPANS; y++) 10905 ast_mutex_destroy(&pris[y].lock); 10906 #endif 10907 return __unload_module(); 10908 }
static int update_conf | ( | struct dahdi_pvt * | p | ) | [static] |
Definition at line 1408 of file chan_dahdi.c.
References conf_add(), conf_del(), dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, isslavenative(), and dahdi_pvt::subs.
Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), and dahdi_hangup().
01409 { 01410 int needconf = 0; 01411 int x; 01412 int useslavenative; 01413 struct dahdi_pvt *slave = NULL; 01414 01415 useslavenative = isslavenative(p, &slave); 01416 /* Start with the obvious, general stuff */ 01417 for (x = 0; x < 3; x++) { 01418 /* Look for three way calls */ 01419 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) { 01420 conf_add(p, &p->subs[x], x, 0); 01421 needconf++; 01422 } else { 01423 conf_del(p, &p->subs[x], x); 01424 } 01425 } 01426 /* If we have a slave, add him to our conference now. or DAX 01427 if this is slave native */ 01428 for (x = 0; x < MAX_SLAVES; x++) { 01429 if (p->slaves[x]) { 01430 if (useslavenative) 01431 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p)); 01432 else { 01433 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0); 01434 needconf++; 01435 } 01436 } 01437 } 01438 /* If we're supposed to be in there, do so now */ 01439 if (p->inconference && !p->subs[SUB_REAL].inthreeway) { 01440 if (useslavenative) 01441 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave)); 01442 else { 01443 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0); 01444 needconf++; 01445 } 01446 } 01447 /* If we have a master, add ourselves to his conference */ 01448 if (p->master) { 01449 if (isslavenative(p->master, NULL)) { 01450 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master)); 01451 } else { 01452 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0); 01453 } 01454 } 01455 if (!needconf) { 01456 /* Nobody is left (or should be left) in our conference. 01457 Kill it. */ 01458 p->confno = -1; 01459 } 01460 if (option_debug) 01461 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf); 01462 return 0; 01463 }
static void wakeup_sub | ( | struct dahdi_pvt * | p, | |
int | a, | |||
void * | pri | |||
) | [static] |
Definition at line 822 of file chan_dahdi.c.
References ast_mutex_trylock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, ast_channel::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.
Referenced by swap_subs().
00824 { 00825 #ifdef HAVE_PRI 00826 if (pri) 00827 ast_mutex_unlock(&pri->lock); 00828 #endif 00829 for (;;) { 00830 if (p->subs[a].owner) { 00831 if (ast_mutex_trylock(&p->subs[a].owner->lock)) { 00832 DEADLOCK_AVOIDANCE(&p->lock); 00833 } else { 00834 ast_queue_frame(p->subs[a].owner, &ast_null_frame); 00835 ast_mutex_unlock(&p->subs[a].owner->lock); 00836 break; 00837 } 00838 } else 00839 break; 00840 } 00841 #ifdef HAVE_PRI 00842 if (pri) 00843 ast_mutex_lock(&pri->lock); 00844 #endif 00845 }
static int zap_action_dialoffhook | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10746 of file chan_dahdi.c.
References __action_dialoffhook(), and s.
10747 { 10748 return __action_dialoffhook(s, m, 1); 10749 }
static int zap_action_dndoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10646 of file chan_dahdi.c.
References __action_dnd(), and s.
10647 { 10648 return __action_dnd(s, m, 1, 0); 10649 }
static int zap_action_dndon | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10636 of file chan_dahdi.c.
References __action_dnd(), and s.
10637 { 10638 return __action_dnd(s, m, 1, 1); 10639 }
static int zap_action_restart | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10825 of file chan_dahdi.c.
References __action_restart(), and s.
10826 { 10827 return __action_restart(s, m, 1); 10828 }
static int zap_action_showchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10801 of file chan_dahdi.c.
References __action_showchannels(), and s.
10802 { 10803 return __action_showchannels(s, m, 1); 10804 }
static int zap_action_transfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10675 of file chan_dahdi.c.
References __action_transfer(), and s.
10676 { 10677 return __action_transfer(s, m, 1); 10678 }
static int zap_action_transferhangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 10703 of file chan_dahdi.c.
References __action_transferhangup(), and s.
10704 { 10705 return __action_transferhangup(s, m, 1); 10706 }
int alarm |
struct { ... } alarms[] [static] |
Referenced by alarm2str(), and dahdi_show_status().
struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static] |
Definition at line 778 of file chan_dahdi.c.
struct ast_channel_tech* chan_tech [static] |
Definition at line 746 of file chan_dahdi.c.
Referenced by __unload_module(), ast_device_state(), dahdi_new(), load_module(), and ss_thread().
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 789 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_destroy_channel_deprecated [static] |
Initial value:
{ { "zap", "destroy", "channel", NULL }, dahdi_destroy_channel, NULL, NULL }
Definition at line 10542 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_restart_deprecated [static] |
Initial value:
{ { "zap", "restart", NULL }, dahdi_restart_cmd, NULL, NULL }
Definition at line 10547 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_cadences_deprecated [static] |
Initial value:
{ { "zap", "show", "cadences", NULL }, handle_dahdi_show_cadences, NULL, NULL }
Definition at line 10527 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_channel_deprecated [static] |
Initial value:
{ { "zap", "show", "channel", NULL }, dahdi_show_channel, NULL, NULL }
Definition at line 10537 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_channels_deprecated [static] |
Initial value:
{ { "zap", "show", "channels", NULL }, dahdi_show_channels, NULL, NULL }
Definition at line 10532 of file chan_dahdi.c.
struct ast_cli_entry cli_zap_show_status_deprecated [static] |
Initial value:
{ { "zap", "show", "status", NULL }, dahdi_show_status, NULL, NULL }
Definition at line 10552 of file chan_dahdi.c.
struct ast_cli_entry dahdi_cli[] [static] |
char dahdi_restart_usage[] [static] |
Definition at line 10520 of file chan_dahdi.c.
char dahdi_show_cadences_usage[] [static] |
Initial value:
"Usage: dahdi show cadences\n" " Shows all cadences currently defined\n"
Definition at line 10405 of file chan_dahdi.c.
char dahdi_show_status_usage[] [static] |
Initial value:
"Usage: dahdi show status\n" " Shows a list of DAHDI cards with status\n"
Definition at line 10512 of file chan_dahdi.c.
struct ast_channel_tech dahdi_tech [static] |
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 110 of file chan_dahdi.c.
char defaultcic[64] = "" [static] |
Definition at line 199 of file chan_dahdi.c.
char defaultozz[64] = "" [static] |
Definition at line 200 of file chan_dahdi.c.
char destroy_channel_usage[] [static] |
Initial value:
"Usage: dahdi destroy channel <chan num>\n" " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n"
Definition at line 10516 of file chan_dahdi.c.
int distinctiveringaftercid = 0 [static] |
Definition at line 204 of file chan_dahdi.c.
struct dahdi_distRings drings [static] |
char* events[] [static] |
int firstdigittimeout = 16000 [static] |
Wait up to 16 seconds for first digit (FXO logic).
Definition at line 218 of file chan_dahdi.c.
Referenced by disa_exec(), mgcp_ss(), and skinny_ss().
int gendigittimeout = 8000 [static] |
How long to wait for following digits (FXO logic).
Definition at line 221 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
struct ast_jb_conf global_jbconf [static] |
Definition at line 117 of file chan_dahdi.c.
int ifcount = 0 [static] |
Definition at line 230 of file chan_dahdi.c.
Referenced by __action_showchannels(), __oh323_destroy(), __sip_destroy(), __sip_show_channels(), __unload_module(), chandup(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call(), find_call_locked(), find_channel(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), mkintf(), oh323_alloc(), phone_request(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().
int matchdigittimeout = 3000 [static] |
How long to wait for an extra digit, if there is an ambiguous match.
Definition at line 224 of file chan_dahdi.c.
Referenced by mgcp_ss(), and skinny_ss().
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 242 of file chan_dahdi.c.
Referenced by reload_config(), restart_monitor(), and unload_module().
char* name |
Definition at line 1178 of file chan_dahdi.c.
int num_cadence = 4 [static] |
Definition at line 775 of file chan_dahdi.c.
int num_restart_pending = 0 [static] |
Definition at line 247 of file chan_dahdi.c.
int numbufs = 4 [static] |
Definition at line 206 of file chan_dahdi.c.
char progzone[10] = "" [static] |
Definition at line 202 of file chan_dahdi.c.
int ringt_base = DEFAULT_RINGT [static] |
Definition at line 290 of file chan_dahdi.c.
struct dahdi_pvt* round_robin[32] |
char show_channel_usage[] [static] |
Initial value:
"Usage: dahdi show channel <chan num>\n" " Detailed information about a given channel\n"
Definition at line 10508 of file chan_dahdi.c.
char show_channels_usage[] [static] |
Initial value:
"Usage: dahdi show channels\n" " Shows a list of available channels\n"
Definition at line 10504 of file chan_dahdi.c.
ast_cond_t ss_thread_complete [static] |
Definition at line 243 of file chan_dahdi.c.
int ss_thread_count = 0 [static] |
Definition at line 246 of file chan_dahdi.c.
char* subnames[] [static] |
const char tdesc[] = "DAHDI Telephony Driver" [static] |
Definition at line 156 of file chan_dahdi.c.
int user_has_defined_cadences = 0 [static] |
Definition at line 776 of file chan_dahdi.c.
struct ast_channel_tech zap_tech [static] |