mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-14 16:33:34 +00:00
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: https://origsvn.digium.com/svn/asterisk/trunk@22128 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -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);
|
||||
{
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user