[asterisk-commits] wedhorn: trunk r318600 - /trunk/channels/chan_skinny.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 12 02:25:57 CDT 2011


Author: wedhorn
Date: Thu May 12 02:25:52 2011
New Revision: 318600

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=318600
Log:
Add setsubstate_onhook.

Add the setsubstate_onhook to complete the initial substate handling
procedures. Added dumpsub(sub, forcehangup) which is the common way of
calling setsubstate_onhook. Dumpsub attempts to activate another sub
after setting the current one onhook.

Modified:
    trunk/channels/chan_skinny.c

Modified: trunk/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_skinny.c?view=diff&rev=318600&r1=318599&r2=318600
==============================================================================
--- trunk/channels/chan_skinny.c (original)
+++ trunk/channels/chan_skinny.c Thu May 12 02:25:52 2011
@@ -1211,7 +1211,6 @@
 	int cxmode;
 	int nat;
 	int calldirection;
-	int alreadygone;
 	int blindxfer;
 	int xferor;
 	int substate;
@@ -1417,6 +1416,7 @@
 static void setsubstate_congestion(struct skinny_subchannel *sub);
 static void setsubstate_progress(struct skinny_subchannel *sub);
 static void setsubstate_hold(struct skinny_subchannel *sub);
+static void dumpsub(struct skinny_subchannel *sub, int forcehangup);
 
 static struct ast_channel_tech skinny_tech = {
 	.type = "Skinny",
@@ -4084,88 +4084,20 @@
 static int skinny_hangup(struct ast_channel *ast)
 {
 	struct skinny_subchannel *sub = ast->tech_pvt;
-	struct skinny_line *l;
-	struct skinny_device *d;
 
 	if (!sub) {
 		ast_debug(1, "Asked to hangup channel not connected\n");
 		return 0;
 	}
-
-	l = sub->line;
-	d = l->device;
+	
+	dumpsub(sub, 1);
 
 	if (skinnydebug)
-		ast_verb(3,"Hanging up %s/%d\n",d->name,sub->callid);
-
-	AST_LIST_REMOVE(&l->sub, sub, list);
-
-	if (d->registered) {
-		/* Ignoring l->type, doesn't seem relevant and previous code 
-		   assigned rather than tested, ie always true */
-		if (!AST_LIST_EMPTY(&l->sub)) {
-			if (sub->related) {
-				sub->related->related = NULL;
-
-			}
-			if (sub == l->activesub) {      /* we are killing the active sub, but there are other subs on the line*/
-				ast_verb(4,"Killing active sub %d\n", sub->callid);
-				if (sub->related) {
-					l->activesub = sub->related;
-				} else {
-					if (AST_LIST_NEXT(sub, list)) {
-						l->activesub = AST_LIST_NEXT(sub, list);
-					} else {
-						l->activesub = AST_LIST_FIRST(&l->sub);
-					}
-				}
-				if (l->activesub) {
-					transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOLD);
-				}
-				transmit_closereceivechannel(d, sub);
-				transmit_stopmediatransmission(d, sub);
-				transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
-				transmit_stop_tone(d, l->instance, sub->callid);
-				transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
-				transmit_activatecallplane(d, l);
-			} else {    /* we are killing a background sub on the line with other subs*/
-				ast_verb(4,"Killing inactive sub %d\n", sub->callid);
-				if (AST_LIST_NEXT(sub, list)) {
-					transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
-				} else {
-					transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
-				}
-				transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
-				transmit_activatecallplane(d, l);
-			}
-		} else {                                                /* no more subs on line so make idle */
-			ast_verb(4,"Killing only sub %d\n", sub->callid);
-			d->hookstate = SKINNY_ONHOOK;
-			transmit_closereceivechannel(d, sub);
-			transmit_stopmediatransmission(d, sub);
-			transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-			transmit_clearpromptmessage(d, l->instance, sub->callid);
-			transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
-			transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
-			transmit_activatecallplane(d, l);
-			l->activesub = NULL;
-			transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
-			if (sub->line == d->activeline) {
-				transmit_activatecallplane(d, l);
-				transmit_closereceivechannel(d, sub);
-				transmit_stopmediatransmission(d, sub);
-				transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-				transmit_ringer_mode(d, SKINNY_RING_OFF);
-				transmit_clear_display_message(d, l->instance, sub->callid);
-				transmit_stop_tone(d, l->instance, sub->callid);
-				/* we should check to see if we can start the ringer if another line is ringing */
-			}
-		}
-	}
+		ast_verb(3,"Destroying subchannel %d\n", sub->callid);
+
 	ast_mutex_lock(&sub->lock);
 	sub->owner = NULL;
 	ast->tech_pvt = NULL;
-	sub->alreadygone = 0;
 	if (sub->rtp) {
 		ast_rtp_instance_destroy(sub->rtp);
 		sub->rtp = NULL;
@@ -4720,6 +4652,45 @@
 	}
 }
 
+static void setsubstate_onhook(struct skinny_subchannel *sub)
+{
+	struct skinny_line *l = sub->line;
+	struct skinny_device *d = l->device;
+
+	AST_LIST_REMOVE(&l->sub, sub, list);
+	if (sub->related) {
+		sub->related->related = NULL;
+	}
+	
+	if (sub == l->activesub) {
+		l->activesub = NULL;
+		transmit_closereceivechannel(d, sub);
+		transmit_stopmediatransmission(d, sub);
+		transmit_stop_tone(d, l->instance, sub->callid);
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
+		transmit_clearpromptmessage(d, l->instance, sub->callid);
+		transmit_ringer_mode(d, SKINNY_RING_OFF);
+		d->hookstate = SKINNY_ONHOOK;
+		transmit_speaker_mode(d, SKINNY_SPEAKEROFF); 
+		transmit_definetimedate(d); 
+		transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
+	} else {
+		transmit_stop_tone(d, l->instance, sub->callid);
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
+		transmit_clearpromptmessage(d, l->instance, sub->callid);
+	}
+
+	sub->cxmode = SKINNY_CX_RECVONLY;	
+	sub->substate = SUBSTATE_ONHOOK;
+	if (sub->rtp) {
+		ast_rtp_instance_destroy(sub->rtp);
+		sub->rtp = NULL;
+	}
+	if (sub->owner) {
+		ast_queue_hangup(sub->owner);
+	}
+}
+
 static void setsubstate_dialing(struct skinny_subchannel *sub, char exten[AST_MAX_EXTENSION])
 {
 	struct skinny_line *l = sub->line;
@@ -4914,11 +4885,16 @@
 	struct skinny_line *l = sub->line;
 	struct skinny_device *d = l->device;
 
-	if (sub->substate != SUBSTATE_CONNECTED) {
+	if (!(sub->substate == SUBSTATE_CONNECTED || sub->substate == SUBSTATE_HOLD)) {
 		ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
 		return;
 	}
 	
+	if (sub->substate == SUBSTATE_HOLD) {
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_HOLD);
+		return;
+	}
+
 	ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
 		S_OR(l->mohsuggest, NULL),
 		!ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
@@ -4931,6 +4907,57 @@
 	transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
 	transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD);
 	sub->substate = SUBSTATE_HOLD;
+}
+
+static void dumpsub(struct skinny_subchannel *sub, int forcehangup)
+{
+	struct skinny_line *l = sub->line;
+	struct skinny_subchannel *activatesub = NULL;
+	struct skinny_subchannel *tsub;
+
+	if (skinnydebug) {
+		ast_verb(3, "Dumping sub %d - state = %s\n", sub->callid, substate2str(sub->substate));
+	}
+	
+	if (!forcehangup && sub->substate == SUBSTATE_HOLD) {
+		l->activesub = NULL;
+		return;
+	}
+	
+	if (sub == l->activesub) {
+		if (sub->related) {
+			activatesub = sub->related;
+			setsubstate_onhook(sub);
+			l->activesub = activatesub;
+			if (l->activesub->substate != SUBSTATE_HOLD) {
+				ast_log(LOG_WARNING, "Sub-%d was related but not at SUBSTATE_HOLD\n", sub->callid);
+				return;
+			}
+			setsubstate_hold(l->activesub);
+		} else {
+			setsubstate_onhook(sub);
+			AST_LIST_TRAVERSE(&l->sub, tsub, list) {
+				if (tsub->substate == SUBSTATE_CALLWAIT) {
+					activatesub = tsub;
+				}
+			}
+			if (activatesub) {
+				setsubstate_ringin(activatesub);
+				return;
+			}
+			AST_LIST_TRAVERSE(&l->sub, tsub, list) {
+				if (tsub->substate == SUBSTATE_HOLD) {
+					activatesub = tsub;
+				}
+			}
+			if (activatesub) {
+				setsubstate_hold(activatesub);
+				return;
+			}
+		}
+	} else {
+		setsubstate_onhook(sub);
+	}
 }
 
 static int handle_hold_button(struct skinny_subchannel *sub)
@@ -5453,7 +5480,6 @@
 	struct skinny_subchannel *sub;
 	int instance;
 	int reference;
-	int onlysub = 0;
 
 	instance = letohl(req->data.onhook.instance);
 	reference = letohl(req->data.onhook.reference);
@@ -5479,62 +5505,22 @@
 		return 0;
 	}
 
-	ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
-
-	if (sub->substate == SUBSTATE_HOLD) {
-		return 0;
-	}
-
-	if (!AST_LIST_NEXT(sub, list)) {
-		onlysub = 1;
-	} else {
-		AST_LIST_REMOVE(&l->sub, sub, list);
-	}
-
-	sub->cxmode = SKINNY_CX_RECVONLY;
-	if (onlysub || sub->xferor){  /* is this the only call to this device? */
-		d->hookstate = SKINNY_ONHOOK;
-		if (skinnydebug)
-			ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, reference);
-	}
-
-	if (d->hookstate == SKINNY_ONHOOK) {
-		transmit_closereceivechannel(d, sub);
-		transmit_stopmediatransmission(d, sub);
-		transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-		transmit_clearpromptmessage(d, instance, sub->callid);
-		transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
-		transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
-		transmit_activatecallplane(d, l);
-	} else if (d->hookstate == SKINNY_OFFHOOK) {
-		transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
-		transmit_activatecallplane(d, l);
-	} else {
-		transmit_callstate(d, l->instance, sub->callid, d->hookstate); /* wedhorn: this seems wrong!!! */
-	}
-
 	if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
 		/* We're allowed to transfer, we have two active calls and
 		   we made at least one of the calls.  Let's try and transfer */
 		handle_transfer_button(sub);
-	} else {
-		/* Hangup the current call */
-		/* If there is another active call, skinny_hangup will ring the phone with the other call */
-		if (sub->xferor && sub->related){
-			sub->related->related = NULL;
-			sub->related->blindxfer = 0;
-		}
-
-		if (sub->owner) {
-			sub->alreadygone = 1;
-			ast_queue_hangup(sub->owner);
-		} else {
-			ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
-				l->name, d->name, sub->callid);
-		}
-		/* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
-		transmit_definetimedate(d);
-	}
+		return 0;
+	}
+	
+	ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
+	
+	dumpsub(sub, 0);
+
+	d->hookstate = SKINNY_ONHOOK;
+	
+	/* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
+	transmit_definetimedate(d);
+
 	return 1;
 }
 
@@ -5998,66 +5984,27 @@
 
 		if (d->hookstate == SKINNY_ONHOOK) {
 			/* Something else already put us back on hook */
-			break;
-		}
-		if (sub) {
-			int onlysub = 0;
-
-			if (!AST_LIST_NEXT(sub, list)) {
-				onlysub = 1;
-			} else {
-				AST_LIST_REMOVE(&l->sub, sub, list);
-			}
-
-			sub->cxmode = SKINNY_CX_RECVONLY;
-			if (onlysub || sub->xferor){    /*Are there other calls to this device */
-				d->hookstate = SKINNY_ONHOOK;
-				if (skinnydebug)
-					ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, callreference);
-			}
-
-			if (d->hookstate == SKINNY_ONHOOK) {
-				transmit_closereceivechannel(d, sub);
-				transmit_stopmediatransmission(d, sub);
-				transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-				transmit_clearpromptmessage(d, instance, sub->callid);
-				transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
-				transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
-				transmit_activatecallplane(d, l);
-			} else if (d->hookstate == SKINNY_OFFHOOK) {
-				transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
-				transmit_activatecallplane(d, l);
-			} else {
-				transmit_callstate(d, l->instance, sub->callid, d->hookstate); /* wedhorn - this seems wrong */
-			}
-
-			ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
-			if (skinnydebug)
-				ast_verb(1, "Skinny %s@%s went on hook\n", l->name, d->name);
-			if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
-				/* We're allowed to transfer, we have two active calls and
-				   we made at least one of the calls.  Let's try and transfer */
-				handle_transfer_button(sub);
-			} else {
-				/* Hangup the current call */
-				/* If there is another active call, skinny_hangup will ring the phone with the other call */
-				if (sub->xferor && sub->related){
-					sub->related->related = NULL;
-					sub->related->blindxfer = 0;
-				}
-
-				if (sub->owner) {
-					sub->alreadygone = 1;
-					ast_queue_hangup(sub->owner);
-				} else {
-					ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
-						l->name, d->name, sub->callid);
-				}
-			}
-			if ((d->hookstate == SKINNY_ONHOOK) && (AST_LIST_NEXT(sub, list) && !AST_LIST_NEXT(sub, list)->rtp)) {
-				ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
-			}
-		}
+			/* Not ideal, but let's send updated time anyway, as it clears the display */
+			transmit_definetimedate(d);
+			return 0;
+		}
+
+		if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
+			/* We're allowed to transfer, we have two active calls and
+			    we made at least one of the calls.  Let's try and transfer */
+			handle_transfer_button(sub);
+			return 0;
+		}
+	
+		ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
+	
+		dumpsub(sub, 1);
+
+		d->hookstate = SKINNY_ONHOOK;
+	
+		/* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
+		transmit_definetimedate(d);
+
 		break;
 	case SOFTKEY_RESUME:
 		if (skinnydebug)
@@ -7531,7 +7478,6 @@
 			AST_LIST_TRAVERSE(&l->sub, sub, list) {
 				ast_mutex_lock(&sub->lock);
 				if (sub->owner) {
-					sub->alreadygone = 1;
 					ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
 				}
 				ast_mutex_unlock(&sub->lock);




More information about the asterisk-commits mailing list