Check if polarityonanswerdelay has elapsed before setting a channel as answered
authorJeff Peeler <jpeeler@digium.com>
Fri, 26 Jun 2009 19:03:25 +0000 (19:03 +0000)
committerJeff Peeler <jpeeler@digium.com>
Fri, 26 Jun 2009 19:03:25 +0000 (19:03 +0000)
after a polarity reversal.

Previously on a polarity switch event chan_dahdi would set the channel
immediately as answered. This would cause problems if a polarity reversal
occurred when the line was picked up as the dial would not have yet occurred.
Now if the polarity reversal occurs before delay has elapsed after coming off
hook or an answer, it is ignored. Also, some refactoring was done in
_handle_event.

(closes issue #13917)
Reported by: alecdavis
Patches:
      chan_dahdi.bug13917.feb09.diff2.txt uploaded by alecdavis (license 585)
Tested by: alecdavis

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@203672 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/sig_analog.c

index 79fc276..223d921 100644 (file)
@@ -788,6 +788,11 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
        case ANALOG_SIG_FXSLS:
        case ANALOG_SIG_FXSGS:
        case ANALOG_SIG_FXSKS:
+               if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
+                       ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
+                       p->polaritydelaytv = ast_tvnow();
+               }
+               /* fall through */
        case ANALOG_SIG_EMWINK:
        case ANALOG_SIG_EM:
        case ANALOG_SIG_EM_E1:
@@ -2826,44 +2831,80 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                break;
        case ANALOG_EVENT_POLARITY:
                /*
-                * If we get a Polarity Switch event, check to see
-                * if we should change the polarity state and
+                * If we get a Polarity Switch event, this could be
+                * due to line seizure, remote end connect or remote end disconnect.
+                *
+                * Check to see if we should change the polarity state and
                 * mark the channel as UP or if this is an indication
                 * of remote end disconnect.
                 */
-               if (p->polarity == POLARITY_IDLE) {
-                       p->polarity = POLARITY_REV;
-                       if (p->answeronpolarityswitch &&
-                           ((ast->_state == AST_STATE_DIALING) ||
-                                (ast->_state == AST_STATE_RINGING))) {
-                               ast_debug(1, "Answering on polarity switch!\n");
-                               ast_setstate(p->owner, AST_STATE_UP);
-                               if (p->hanguponpolarityswitch) {
-                                       gettimeofday(&p->polaritydelaytv, NULL);
-                               }
-                       } else
-                               ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
-               }
-               /* Removed else statement from here as it was preventing hangups from ever happening*/
-               /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
-               if (p->hanguponpolarityswitch &&
-                       (p->polarityonanswerdelay > 0) &&
-                      (p->polarity == POLARITY_REV) &&
-                       ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
-                               /* Added log_debug information below to provide a better indication of what is going on */
-                       ast_debug(1, "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) );
+               
+               if (p->polarityonanswerdelay > 0) {
+                       /* check if event is not too soon after OffHook or Answer */
 
                        if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
-                               ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
-                               ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
-                               p->polarity = POLARITY_IDLE;
+                               switch (ast->_state) {
+                               case AST_STATE_DIALING:                 /*!< Digits (or equivalent) have been dialed */
+                               case AST_STATE_RINGING:                 /*!< Remote end is ringing */
+                                       if (p->answeronpolarityswitch) {
+                                               ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
+                                               ast_setstate(p->owner, AST_STATE_UP);
+                                               p->polarity = POLARITY_REV;
+                                               if (p->hanguponpolarityswitch) {
+                                                       p->polaritydelaytv = ast_tvnow();
+                                               }
+                                       } else {
+                                               ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
+                                       }
+                                       break;
+                               case AST_STATE_UP:                              /*!< Line is up */
+                               case AST_STATE_RING:                    /*!< Line is ringing */
+                                       if (p->hanguponpolarityswitch) {
+                                               ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
+                                               ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
+                                               p->polarity = POLARITY_IDLE;
+                                       } else {
+                                               ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
+                                       }
+                                       break;
+
+                               case AST_STATE_DOWN:                            /*!< Channel is down and available */
+                               case AST_STATE_RESERVED:                        /*!< Channel is down, but reserved */
+                               case AST_STATE_OFFHOOK:                         /*!< Channel is off hook */
+                               case AST_STATE_BUSY:                            /*!< Line is busy */
+                               case AST_STATE_DIALING_OFFHOOK:         /*!< Digits (or equivalent) have been dialed while offhook */
+                               case AST_STATE_PRERING:                         /*!< Channel has detected an incoming call and is waiting for ring */
+                               default:
+                                       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
+                                               ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                               }
+
                        } else {
-                               ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
+                               /* event is too soon after OffHook or Answer */
+                               switch (ast->_state) {
+                               case AST_STATE_DIALING:         /*!< Digits (or equivalent) have been dialed */
+                               case AST_STATE_RINGING:         /*!< Remote end is ringing */
+                                       if (p->answeronpolarityswitch) {
+                                               ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                                       break;
+
+                               case AST_STATE_UP:                      /*!< Line is up */
+                               case AST_STATE_RING:            /*!< Line is ringing */
+                                       if (p->hanguponpolarityswitch) {
+                                               ast_debug(1, "Polarity switch detected but NOT hanging up (too close to Answer event) on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                                       break;
+
+                               default:        
+                                       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
+                                               ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
+                                       }
+                               }
                        }
-               } else {
-                       p->polarity = POLARITY_IDLE;
-                       ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
                }
+
                /* Added more log_debug information below to provide a better indication of what is going on */
                ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
                break;