@@ -805,6 +805,11 @@ int analog_available(struct analog_pvt *p)
805
805
return 0 ;
806
806
}
807
807
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
+
808
813
/* If no owner definitely available */
809
814
if (!p -> owner ) {
810
815
offhook = analog_is_off_hook (p );
@@ -1300,6 +1305,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
1300
1305
p -> channel , idx , p -> subs [ANALOG_SUB_REAL ].allocd , p -> subs [ANALOG_SUB_CALLWAIT ].allocd , p -> subs [ANALOG_SUB_THREEWAY ].allocd );
1301
1306
if (idx > -1 ) {
1302
1307
/* Real channel, do some fixup */
1308
+ p -> cshactive = 0 ;
1303
1309
p -> subs [idx ].owner = NULL ;
1304
1310
p -> polarity = POLARITY_IDLE ;
1305
1311
analog_set_linear_mode (p , idx , 0 );
@@ -2933,6 +2939,34 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
2933
2939
analog_get_and_handle_alarms (p );
2934
2940
cause_code -> ast_cause = AST_CAUSE_NETWORK_OUT_OF_ORDER ;
2935
2941
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
+ }
2936
2970
ast_queue_control_data (ast , AST_CONTROL_PVT_CAUSE_CODE , cause_code , data_size );
2937
2971
ast_channel_hangupcause_hash_set (ast , cause_code , data_size );
2938
2972
switch (p -> sig ) {
@@ -3809,6 +3843,7 @@ void *analog_handle_init_event(struct analog_pvt *i, int event)
3809
3843
case ANALOG_SIG_FXOKS :
3810
3844
res = analog_off_hook (i );
3811
3845
i -> fxsoffhookstate = 1 ;
3846
+ i -> cshactive = 0 ;
3812
3847
if (res && (errno == EBUSY )) {
3813
3848
break ;
3814
3849
}
0 commit comments