@@ -805,6 +805,11 @@ int analog_available(struct analog_pvt *p)
805805 return 0 ;
806806 }
807807
808+ /* If line is being held, definitely not (don't allow call waitings to an on-hook phone) */
809+ if (p -> cshactive ) {
810+ return 0 ;
811+ }
812+
808813 /* If no owner definitely available */
809814 if (!p -> owner ) {
810815 offhook = analog_is_off_hook (p );
@@ -1300,6 +1305,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
13001305 p -> channel , idx , p -> subs [ANALOG_SUB_REAL ].allocd , p -> subs [ANALOG_SUB_CALLWAIT ].allocd , p -> subs [ANALOG_SUB_THREEWAY ].allocd );
13011306 if (idx > -1 ) {
13021307 /* Real channel, do some fixup */
1308+ p -> cshactive = 0 ;
13031309 p -> subs [idx ].owner = NULL ;
13041310 p -> polarity = POLARITY_IDLE ;
13051311 analog_set_linear_mode (p , idx , 0 );
@@ -2933,6 +2939,34 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
29332939 analog_get_and_handle_alarms (p );
29342940 cause_code -> ast_cause = AST_CAUSE_NETWORK_OUT_OF_ORDER ;
29352941 case ANALOG_EVENT_ONHOOK :
2942+ if (p -> calledsubscriberheld && (p -> sig == ANALOG_SIG_FXOLS || p -> sig == ANALOG_SIG_FXOGS || p -> sig == ANALOG_SIG_FXOKS ) && idx == ANALOG_SUB_REAL ) {
2943+ ast_debug (4 , "Channel state on %s is %d\n" , ast_channel_name (ast ), ast_channel_state (ast ));
2944+ /* Called Subscriber Held: don't let the called party hang up on an incoming call immediately (if it's the only call). */
2945+ if (p -> subs [ANALOG_SUB_CALLWAIT ].owner || p -> subs [ANALOG_SUB_THREEWAY ].owner ) {
2946+ ast_debug (2 , "Letting this call hang up normally, since it's not the only call\n" );
2947+ } else if (!p -> owner || !p -> subs [ANALOG_SUB_REAL ].owner || ast_channel_state (ast ) != AST_STATE_UP ) {
2948+ ast_debug (2 , "Called Subscriber Held does not apply: channel state is %d\n" , ast_channel_state (ast ));
2949+ } else if (!p -> owner || !p -> subs [ANALOG_SUB_REAL ].owner || strcmp (ast_channel_appl (p -> subs [ANALOG_SUB_REAL ].owner ), "AppDial" )) {
2950+ /* Called Subscriber held only applies to incoming calls, not outgoing calls.
2951+ * We can't use p->outgoing because that is always true, for both incoming and outgoing calls, so it's not accurate.
2952+ * We can check the channel application/data instead.
2953+ * For incoming calls to the channel, it will look like: AppDial / (Outgoing Line)
2954+ * We only want this behavior for regular calls anyways (and not, say, Queue),
2955+ * so this would actually work great. But accessing ast_channel_appl can cause a crash if there are no calls left,
2956+ * so this check must occur AFTER we confirm the channel state *is* still UP.
2957+ */
2958+ ast_debug (2 , "Called Subscriber Held does not apply: not an incoming call\n" );
2959+ } else if (analog_is_off_hook (p )) {
2960+ ast_log (LOG_WARNING , "Got ONHOOK but channel %d is off hook?\n" , p -> channel ); /* Shouldn't happen */
2961+ } else {
2962+ ast_verb (3 , "Holding incoming call %s for channel %d\n" , ast_channel_name (ast ), p -> channel );
2963+ /* Inhibit dahdi_hangup from getting called, and do nothing else now.
2964+ * When the DAHDI channel goes off hook again, it'll just get reconnected with the incoming call,
2965+ * to which, as far as its concerned, nothing has happened. */
2966+ p -> cshactive = 1 ; /* Keep track that this DAHDI channel is currently being held by an incoming call. */
2967+ break ;
2968+ }
2969+ }
29362970 ast_queue_control_data (ast , AST_CONTROL_PVT_CAUSE_CODE , cause_code , data_size );
29372971 ast_channel_hangupcause_hash_set (ast , cause_code , data_size );
29382972 switch (p -> sig ) {
@@ -3809,6 +3843,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
38093843 case ANALOG_SIG_FXOKS :
38103844 res = analog_off_hook (i );
38113845 i -> fxsoffhookstate = 1 ;
3846+ i -> cshactive = 0 ;
38123847 if (res && (errno == EBUSY )) {
38133848 break ;
38143849 }
0 commit comments