aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdixon <jdixon@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-22 11:30:06 +0000
committerjdixon <jdixon@f38db490-d61c-443f-a65b-d21fe96a405b>2006-04-22 11:30:06 +0000
commitc4e93002d617efd3568354cd4020191cfd79de52 (patch)
tree7ae4c12bf61dba4c0d883eda9942c18b6f356ab3
parenta139aad1f4ed15064e16e31605b65f8f995d01d3 (diff)
Added "Operator Services" connection mode for Zap channels, and the 'O' option
in app_dial to support the use of this mode. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@22128 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--apps/app_dial.c33
-rw-r--r--channels/chan_zap.c92
-rw-r--r--include/asterisk/frame.h8
3 files changed, 119 insertions, 14 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index f4bdd112e..bdf7f7f82 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -154,6 +154,16 @@ static char *descrip =
" o - Specify that the CallerID that was present on the *calling* channel\n"
" be set as the CallerID on the *called* channel. This was the\n"
" behavior of Asterisk 1.0 and earlier.\n"
+" O([x]) - \"Operator Services\" mode (Zaptel channel to Zaptel channel\n"
+" only, if specified on non-Zaptel interface, it will be ignored).\n"
+" When the destination answers (presumably an operator services\n"
+" station), the originator no longer has control of their line.\n"
+" They may hang up, but the switch will not release their line\n"
+" until the destination party hangs up (the operator). Specified\n"
+" without an arg, or with 1 as an arg, the originator hanging up\n"
+" will cause the phone to ring back immediately. With a 2 specified,\n"
+" when the \"operator\" flashes the trunk, it will ring their phone\n"
+" back.\n"
" p - This option enables screening mode. This is basically Privacy mode\n"
" without memory.\n"
" P([x]) - Enable privacy mode. Use 'x' as the family/key in the database if\n"
@@ -213,6 +223,7 @@ enum {
OPT_CALLEE_MONITOR = (1 << 21),
OPT_CALLER_MONITOR = (1 << 22),
OPT_GOTO = (1 << 23),
+ OPT_OPERMODE = (1 << 24),
} dial_exec_option_flags;
#define DIAL_STILLGOING (1 << 30)
@@ -227,6 +238,7 @@ enum {
OPT_ARG_CALLEE_MACRO,
OPT_ARG_PRIVACY,
OPT_ARG_DURATION_STOP,
+ OPT_ARG_OPERMODE,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE,
} dial_exec_option_args;
@@ -247,6 +259,7 @@ AST_APP_OPTIONS(dial_exec_options, {
AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
+ AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
AST_APP_OPTION('p', OPT_SCREENING),
AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
@@ -744,6 +757,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
char privintro[1024];
char privcid[256];
char *parse;
+ int opermode = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(peers);
AST_APP_ARG(timeout);
@@ -774,6 +788,14 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
goto done;
}
+ if (ast_test_flag(&opts, OPT_OPERMODE)) {
+ if (ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]))
+ opermode = 1;
+ else opermode = atoi(opt_args[OPT_ARG_OPERMODE]);
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
+ }
+
if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]);
if (!calldurationlimit) {
@@ -1483,6 +1505,17 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
res = -1;
goto done;
}
+ if (opermode && (!strncmp(chan->name,"Zap",3)) &&
+ (!strncmp(peer->name,"Zap",3)))
+ {
+ struct oprmode oprmode;
+
+ oprmode.peer = peer;
+ oprmode.mode = opermode;
+
+ ast_channel_setoption(chan,
+ AST_OPTION_OPRMODE,&oprmode,sizeof(struct oprmode),0);
+ }
res = ast_bridge_call(chan,peer,&config);
time(&end_time);
{
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index c7341d29c..13d26e545 100644
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -543,6 +543,8 @@ static struct zt_pvt {
int sig; /*!< Signalling style */
int radio; /*!< radio type */
int outsigmod; /*!< Outbound Signalling style (modifier) */
+ int oprmode; /*!< "Operator Services" mode */
+ struct zt_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
float rxgain;
float txgain;
int tonezone; /*!< tone zone for this chan, or -1 for default */
@@ -1771,7 +1773,7 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
return -1;
}
p->dialednone = 0;
- if (p->radio) /* if a radio channel, up immediately */
+ if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
{
/* Special pseudo -- automatically up */
ast_setstate(ast, AST_STATE_UP);
@@ -2616,7 +2618,7 @@ static int zt_hangup(struct ast_channel *ast)
ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
#endif
/* If they're off hook, try playing congestion */
- if ((par.rxisoffhook) && (!p->radio))
+ if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
else
tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
@@ -2676,6 +2678,7 @@ static int zt_hangup(struct ast_channel *ast)
p->callwaitingrepeat = 0;
p->cidcwexpire = 0;
+ p->oprmode = 0;
ast->tech_pvt = NULL;
ast_mutex_unlock(&p->lock);
ast_mutex_lock(&usecnt_lock);
@@ -2717,7 +2720,7 @@ static int zt_answer(struct ast_channel *ast)
if (index < 0)
index = SUB_REAL;
/* nothing to do if a radio channel */
- if (p->radio) {
+ if ((p->radio || (p->oprmode < 0))) {
ast_mutex_unlock(&p->lock);
return 0;
}
@@ -2803,7 +2806,9 @@ static int zt_setoption(struct ast_channel *chan, int option, void *data, int da
signed char *scp;
int x;
int index;
- struct zt_pvt *p = chan->tech_pvt;
+ struct zt_pvt *p = chan->tech_pvt,*pp;
+ struct oprmode *oprmode;
+
/* all supported options require data */
if (!data || (datalen < 1)) {
@@ -2939,6 +2944,22 @@ static int zt_setoption(struct ast_channel *chan, int option, void *data, int da
if (ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x) == -1)
ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", p->channel, x);
break;
+ case AST_OPTION_OPRMODE: /* Operator services mode */
+ oprmode = (struct oprmode *) data;
+ pp = oprmode->peer->tech_pvt;
+ p->oprmode = pp->oprmode = 0;
+ /* setup peers */
+ p->oprpeer = pp;
+ pp->oprpeer = p;
+ /* setup modes, if any */
+ if (oprmode->mode)
+ {
+ pp->oprmode = oprmode->mode;
+ p->oprmode = -oprmode->mode;
+ }
+ ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
+ oprmode->mode, chan->name,oprmode->peer->name);;
+ break;
}
errno = 0;
@@ -3685,7 +3706,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
break;
case ZT_EVENT_DIALCOMPLETE:
if (p->inalarm) break;
- if (p->radio) break;
+ if ((p->radio || (p->oprmode < 0))) break;
if (ioctl(p->subs[index].zfd,ZT_DIALING,&x) == -1) {
ast_log(LOG_DEBUG, "ZT_DIALING ioctl failed on %s\n",ast->name);
return NULL;
@@ -3760,6 +3781,19 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
break;
}
+ if (p->oprmode < 0)
+ {
+ if (p->oprmode != -1) break;
+ if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
+ {
+ /* Make sure it starts ringing */
+ zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RINGOFF);
+ zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RING);
+ save_conference(p->oprpeer);
+ tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
+ }
+ break;
+ }
switch(p->sig) {
case SIG_FXOLS:
case SIG_FXOGS:
@@ -3869,11 +3903,23 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
break;
case ZT_EVENT_RINGOFFHOOK:
if (p->inalarm) break;
- if (p->radio) {
+ if (p->oprmode < 0)
+ {
+ if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
+ {
+ /* Make sure it stops ringing */
+ zt_set_hook(p->subs[SUB_REAL].zfd, ZT_RINGOFF);
+ tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, -1);
+ restore_conference(p->oprpeer);
+ }
+ break;
+ }
+ if (p->radio)
+ {
p->subs[index].f.frametype = AST_FRAME_CONTROL;
p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
break;
- }
+ }
/* for E911, its supposed to wait for offhook then dial
the second half of the dial string */
if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
@@ -4038,7 +4084,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
#endif
case ZT_EVENT_RINGEROFF:
if (p->inalarm) break;
- if (p->radio) break;
+ if ((p->radio || (p->oprmode < 0))) break;
ast->rings++;
if ((ast->rings > p->cidrings) && (p->cidspill)) {
ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
@@ -4065,6 +4111,24 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
case ZT_EVENT_WINKFLASH:
if (p->inalarm) break;
if (p->radio) break;
+ if (p->oprmode < 0) break;
+ if (p->oprmode > 1)
+ {
+ struct zt_params par;
+
+ if (ioctl(p->oprpeer->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par) != -1)
+ {
+ if (!par.rxisoffhook)
+ {
+ /* Make sure it stops ringing */
+ zt_set_hook(p->oprpeer->subs[SUB_REAL].zfd, ZT_RINGOFF);
+ zt_set_hook(p->oprpeer->subs[SUB_REAL].zfd, ZT_RING);
+ save_conference(p);
+ tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
+ }
+ }
+ break;
+ }
/* Remember last time we got a flash-hook */
gettimeofday(&p->flashtime, NULL);
switch(mysig) {
@@ -4267,7 +4331,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
break;
case ZT_EVENT_HOOKCOMPLETE:
if (p->inalarm) break;
- if (p->radio) break;
+ if ((p->radio || (p->oprmode < 0))) break;
switch(mysig) {
case SIG_FXSLS: /* only interesting for FXS */
case SIG_FXSGS:
@@ -4375,7 +4439,7 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast)
p->subs[index].f.data = NULL;
- if ((!p->owner) && (!p->radio)) {
+ if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
/* If nobody owns us, absorb the event appropriately, otherwise
we loop indefinitely. This occurs when, during call waiting, the
other end hangs up our channel so that it no longer exists, but we
@@ -4446,7 +4510,7 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast)
f = &p->subs[index].f;
return f;
}
- if (!p->radio) ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
+ if (!(p->radio || (p->oprmode < 0))) ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
/* If it's not us, return NULL immediately */
if (ast != p->owner) {
ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
@@ -4487,7 +4551,7 @@ struct ast_frame *zt_read(struct ast_channel *ast)
return NULL;
}
- if (p->radio && p->inalarm) return NULL;
+ if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
p->subs[index].f.frametype = AST_FRAME_NULL;
p->subs[index].f.datalen = 0;
@@ -4500,7 +4564,7 @@ struct ast_frame *zt_read(struct ast_channel *ast)
p->subs[index].f.data = NULL;
/* make sure it sends initial key state as first frame */
- if (p->radio && (!p->firstradio))
+ if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
{
ZT_PARAMS ps;
@@ -7539,7 +7603,7 @@ static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch,
return 1;
}
#endif
- if (!p->radio)
+ if (!(p->radio || (p->oprmode < 0)))
{
if (!p->sig || (p->sig == SIG_FXSLS))
return 1;
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 099e20080..dd1a41732 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -321,6 +321,14 @@ extern struct ast_frame ast_null_frame;
*/
#define AST_OPTION_RXGAIN 6
+/* set channel into "Operator Services" mode */
+#define AST_OPTION_OPRMODE 7
+
+struct oprmode {
+ struct ast_channel *peer;
+ int mode;
+} ;
+
struct ast_option_header {
/* Always keep in network byte order */
#if __BYTE_ORDER == __BIG_ENDIAN