diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 64bfd3295a..e44d0d9758 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -2068,19 +2068,26 @@ static void my_deadlock_avoidance_private(void *pvt) /* linear_mode = 0 - turn linear mode off, >0 - turn linear mode on * returns the last value of the linear setting */ -static int my_set_linear_mode(void *pvt, int idx, int linear_mode) +static int my_set_linear_mode(void *pvt, enum analog_sub sub, int linear_mode) { struct dahdi_pvt *p = pvt; int oldval; + int idx = analogsub_to_dahdisub(sub); - if (0 > linear_mode || !dahdi_setlinear(p->subs[idx].dfd, linear_mode)) { - return -1; - } + dahdi_setlinear(p->subs[idx].dfd, linear_mode); oldval = p->subs[idx].linear; - p->subs[idx].linear = linear_mode; + p->subs[idx].linear = linear_mode ? 1 : 0; return oldval; } +static void my_set_inthreeway(void *pvt, enum analog_sub sub, int inthreeway) +{ + struct dahdi_pvt *p = pvt; + int idx = analogsub_to_dahdisub(sub); + + p->subs[idx].inthreeway = inthreeway; +} + static int get_alarms(struct dahdi_pvt *p); static void handle_alarms(struct dahdi_pvt *p, int alms); static void my_get_and_handle_alarms(void *pvt) @@ -2382,24 +2389,27 @@ static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel struct dahdi_pvt *p = pvt; int da, db; int tchan; + int tinthreeway; da = analogsub_to_dahdisub(a); db = analogsub_to_dahdisub(b); tchan = p->subs[da].chan; - p->subs[da].chan = p->subs[db].chan; - p->subs[db].chan = tchan; + tinthreeway = p->subs[da].inthreeway; + p->subs[da].inthreeway = p->subs[db].inthreeway; + p->subs[db].inthreeway = tinthreeway; + + p->subs[da].owner = ast_a; + p->subs[db].owner = ast_b; + if (ast_a) ast_channel_set_fd(ast_a, 0, p->subs[da].dfd); if (ast_b) ast_channel_set_fd(ast_b, 0, p->subs[db].dfd); - p->subs[da].owner = ast_a; - p->subs[db].owner = ast_b; - wakeup_sub(p, a); wakeup_sub(p, b); @@ -3503,6 +3513,7 @@ static struct analog_callback dahdi_analog_callbacks = .decrease_ss_count = my_decrease_ss_count, .distinctive_ring = my_distinctive_ring, .set_linear_mode = my_set_linear_mode, + .set_inthreeway = my_set_inthreeway, .get_and_handle_alarms = my_get_and_handle_alarms, .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel, .get_sub_fd = my_get_sub_fd, diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 1d68889be0..546a560696 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -322,12 +322,11 @@ static void analog_swap_subs(struct analog_pvt *p, enum analog_sub a, enum analo ast_debug(1, "Swapping %d and %d\n", a, b); towner = p->subs[a].owner; - tinthreeway = p->subs[a].inthreeway; - p->subs[a].owner = p->subs[b].owner; - p->subs[a].inthreeway = p->subs[b].inthreeway; - p->subs[b].owner = towner; + + tinthreeway = p->subs[a].inthreeway; + p->subs[a].inthreeway = p->subs[b].inthreeway; p->subs[b].inthreeway = tinthreeway; if (p->calls->swap_subs) { @@ -954,15 +953,23 @@ static void analog_set_pulsedial(struct analog_pvt *p, int flag) p->calls->set_pulsedial(p->chan_pvt, flag); } -static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode) +static int analog_set_linear_mode(struct analog_pvt *p, enum analog_sub sub, int linear_mode) { if (p->calls->set_linear_mode) { /* Return provides old linear_mode setting or error indication */ - return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode); + return p->calls->set_linear_mode(p->chan_pvt, sub, linear_mode); } return -1; } +static void analog_set_inthreeway(struct analog_pvt *p, enum analog_sub sub, int inthreeway) +{ + p->subs[sub].inthreeway = inthreeway; + if (p->calls->set_inthreeway) { + p->calls->set_inthreeway(p->chan_pvt, sub, inthreeway); + } +} + int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout) { int res, index,mysig; @@ -1283,7 +1290,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) /* This was part of a three way call. Immediately make way for another call */ ast_debug(1, "Call was complete, setting owner to former third call\n"); - p->subs[ANALOG_SUB_REAL].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); p->owner = p->subs[ANALOG_SUB_REAL].owner; } else { /* This call hasn't been completed yet... Set owner to NULL */ @@ -1319,7 +1326,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) /* This was part of a three way call. Immediately make way for another call */ ast_debug(1, "Call was complete, setting owner to former third call\n"); - p->subs[ANALOG_SUB_REAL].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); p->owner = p->subs[ANALOG_SUB_REAL].owner; } else { /* This call hasn't been completed yet... Set owner to NULL */ @@ -1341,7 +1348,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) S_OR(p->mohsuggest, NULL), !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); } - p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 0); /* Make it the call wait now */ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_THREEWAY); analog_unalloc_sub(p, ANALOG_SUB_THREEWAY); @@ -1359,7 +1366,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) if (p->subs[ANALOG_SUB_CALLWAIT].inthreeway) { /* The other party of the three way call is currently in a call-wait state. Start music on hold for them, and take the main guy out of the third call */ - p->subs[ANALOG_SUB_CALLWAIT].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_CALLWAIT, 0); if (p->subs[ANALOG_SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[ANALOG_SUB_CALLWAIT].owner)) { ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD, S_OR(p->mohsuggest, NULL), @@ -1369,7 +1376,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) if (p->subs[ANALOG_SUB_CALLWAIT].owner) { ast_channel_unlock(p->subs[ANALOG_SUB_CALLWAIT].owner); } - p->subs[ANALOG_SUB_REAL].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); /* If this was part of a three way call index, let us make another three way call */ analog_unalloc_sub(p, ANALOG_SUB_THREEWAY); @@ -2748,16 +2755,16 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner); } else if (res) { /* this isn't a threeway call anymore */ - p->subs[ANALOG_SUB_REAL].inthreeway = 0; - p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); + analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 0); /* Don't actually hang up at this point */ break; } } /* this isn't a threeway call anymore */ - p->subs[ANALOG_SUB_REAL].inthreeway = 0; - p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); + analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 0); } else { ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV); ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner); @@ -3154,16 +3161,16 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ /* Drop the last call and stop the conference */ ast_verb(3, "Dropping three-way call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name); ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV); - p->subs[ANALOG_SUB_REAL].inthreeway = 0; - p->subs[ANALOG_SUB_THREEWAY].inthreeway = 0; + analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); + analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 0); } else { /* Lets see what we're up to */ if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) { ast_verb(3, "Building conference on call on %s and %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name, p->subs[ANALOG_SUB_REAL].owner->name); /* Put them in the threeway, and flip */ - p->subs[ANALOG_SUB_THREEWAY].inthreeway = 1; - p->subs[ANALOG_SUB_REAL].inthreeway = 1; + analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 1); + analog_set_inthreeway(p, ANALOG_SUB_REAL, 1); if (ast->_state == AST_STATE_UP) { analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); orig_3way_sub = ANALOG_SUB_REAL; diff --git a/channels/sig_analog.h b/channels/sig_analog.h index c1b611527f..b58b0985ae 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -213,7 +213,8 @@ struct analog_callback { int (* const distinctive_ring)(struct ast_channel *chan, void *pvt, int idx, int *ringdata); /* Sets the specified sub-channel in and out of signed linear mode, returns the value that was overwritten */ - int (* const set_linear_mode)(void *pvt, int idx, int linear_mode); + int (* const set_linear_mode)(void *pvt, enum analog_sub sub, int linear_mode); + void (* const set_inthreeway)(void *pvt, enum analog_sub sub, int inthreeway); void (* const get_and_handle_alarms)(void *pvt); void * (* const get_sigpvt_bridged_channel)(struct ast_channel *chan); int (* const get_sub_fd)(void *pvt, enum analog_sub sub);