Index: channels/chan_skinny.c
===================================================================
--- channels/chan_skinny.c	(revision 249687)
+++ channels/chan_skinny.c	(working copy)
@@ -2422,7 +2422,7 @@
 	transmit_response(d, req);
 }
 
-static void transmit_callstateonly(struct skinny_device *d, struct skinny_subchannel *sub, int state)
+static void transmit_callstate(struct skinny_device *d, int buttonInstance, unsigned callid, int state)
 {
 	struct skinny_req *req;
 
@@ -2430,57 +2430,11 @@
 		return;
 
 	req->data.callstate.callState = htolel(state);
-	req->data.callstate.lineInstance = htolel(sub->parent->instance);
-	req->data.callstate.callReference = htolel(sub->callid);
-	transmit_response(d, req);
-}
-
-static void transmit_callstate(struct skinny_device *d, int instance, int state, unsigned callid)
-{
-	struct skinny_req *req;
-
-	if (state == SKINNY_ONHOOK) {
-		if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
-			return;
-
-		req->data.closereceivechannel.conferenceId = htolel(callid);
-		req->data.closereceivechannel.partyId = htolel(callid);
-		transmit_response(d, req);
-
-		if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
-			return;
-
-		req->data.stopmedia.conferenceId = htolel(callid);
-		req->data.stopmedia.passThruPartyId = htolel(callid);
-		transmit_response(d, req);
-
-		transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-
-		transmit_clearpromptmessage(d, instance, callid);
-	}
-
-	if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
-		return;
-
-	req->data.callstate.callState = htolel(state);
-	req->data.callstate.lineInstance = htolel(instance);
+	req->data.callstate.lineInstance = htolel(buttonInstance);
 	req->data.callstate.callReference = htolel(callid);
 	transmit_response(d, req);
-
-	if (state == SKINNY_ONHOOK) {
-		transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
-	}
-
-	if (state == SKINNY_OFFHOOK || state == SKINNY_ONHOOK) {
-		if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
-			return;
-
-		req->data.activatecallplane.lineInstance = htolel(instance);
-		transmit_response(d, req);
-	}
 }
 
-
 static void transmit_cfwdstate(struct skinny_device *d, struct skinny_line *l)
 {
 	struct skinny_req *req;
@@ -2530,48 +2484,44 @@
 	struct skinny_speeddial *sd = data;
 	struct skinny_device *d = sd->parent;
 	char hint[AST_MAX_EXTENSION];
-	int callstate = SKINNY_CALLREMOTEMULTILINE;
-	int lamp = SKINNY_LAMP_OFF;
 
-	switch (state) {
-	case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
-	case AST_EXTENSION_REMOVED:     /* Extension is gone */
-		ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
-		sd->stateid = -1;
-		callstate = SKINNY_ONHOOK;
-		lamp = SKINNY_LAMP_OFF;
-		break;
-	case AST_EXTENSION_RINGING:
-	case AST_EXTENSION_UNAVAILABLE:
-		callstate = SKINNY_RINGIN;
-		lamp = SKINNY_LAMP_BLINK;
-		break;
-	case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
-	case AST_EXTENSION_INUSE:
-		callstate = SKINNY_CALLREMOTEMULTILINE;
-		lamp = SKINNY_LAMP_ON;
-		break;
-	case AST_EXTENSION_ONHOLD:
-		callstate = SKINNY_HOLD;
-		lamp = SKINNY_LAMP_WINK;
-		break;
-	case AST_EXTENSION_NOT_INUSE:
-	default:
-		callstate = SKINNY_ONHOOK;
-		lamp = SKINNY_LAMP_OFF;
-		break;
-	}
-
 	if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
 		/* If they are not registered, we will override notification and show no availability */
 		if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
-			callstate = SKINNY_ONHOOK;
-			lamp = SKINNY_LAMP_FLASH;
+			transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_FLASH);
+			transmit_callstate(d, sd->instance, SKINNY_ONHOOK, 0);
 		}
+	} else {
+		switch (state) {
+		case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
+		case AST_EXTENSION_REMOVED:     /* Extension is gone */
+			ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
+			sd->stateid = -1;
+			transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
+			transmit_callstate(d, sd->instance, SKINNY_ONHOOK, 0);
+			break;
+		case AST_EXTENSION_RINGING:
+		case AST_EXTENSION_UNAVAILABLE:
+			transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_BLINK);
+			transmit_callstate(d, sd->instance, SKINNY_RINGIN, 0);
+			break;
+		case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
+		case AST_EXTENSION_INUSE:
+			transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_ON);
+			transmit_callstate(d, sd->instance, SKINNY_CALLREMOTEMULTILINE, 0);
+			break;
+		case AST_EXTENSION_ONHOLD:
+			transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_WINK);
+			transmit_callstate(d, sd->instance, SKINNY_HOLD, 0);
+			break;
+		case AST_EXTENSION_NOT_INUSE:
+		default:
+			transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
+			transmit_callstate(d, sd->instance, SKINNY_ONHOOK, 0);
+			break;
+		}
 	}
 
-	transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, lamp);
-	transmit_callstate(d, sd->instance, callstate, 0);
 	sd->laststate = state;
 
 	return 0;
@@ -2587,7 +2537,7 @@
 		return;
 
 	if (sub->owner->_state == AST_STATE_UP) {
-		transmit_callstate(d, l->instance, SKINNY_CONNECTED, sub->callid);
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
 		transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
 		if (sub->outgoing)
 			transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
@@ -2595,16 +2545,16 @@
 			transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
 	} else {
 		if (sub->outgoing) {
-			transmit_callstate(d, l->instance, SKINNY_RINGIN, sub->callid);
+			transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
 			transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
 			transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
 		} else {
 			if (!sub->ringing) {
-				transmit_callstate(d, l->instance, SKINNY_RINGOUT, sub->callid);
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGOUT);
 				transmit_displaypromptstatus(d, "Ring-Out", 0, l->instance, sub->callid);
 				sub->ringing = 1;
 			} else {
-				transmit_callstate(d, l->instance, SKINNY_PROGRESS, sub->callid);
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_PROGRESS);
 				transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
 				sub->progress = 1;
 			}
@@ -3846,7 +3796,7 @@
 		break;
 	}
 
-	transmit_callstateonly(d, sub, SKINNY_RINGIN);
+	transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_RINGIN);
 	transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
 	transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
 	transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
@@ -3916,7 +3866,13 @@
 		} else {                                                /* no more subs on line so make idle */
 			ast_verb(4,"Killing only sub %d\n", sub->callid);
 			l->hookstate = SKINNY_ONHOOK;
-			transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
+			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->parent == d->activeline) {
@@ -3977,7 +3933,7 @@
 	   for some reason, transmit_callinfo must be before transmit_callstate,
 	   or you won't get keypad messages in some situations. */
 	transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
-	transmit_callstateonly(d, sub, SKINNY_CONNECTED);
+	transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
 	transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
 	transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
 	transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
@@ -4283,7 +4239,7 @@
 				if (!d->earlyrtp) {
 					transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid);
 				}
-				transmit_callstateonly(d, sub, SKINNY_RINGOUT);
+				transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_RINGOUT);
 				transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
 				transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
 				transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
@@ -4299,7 +4255,7 @@
 			if (!d->earlyrtp) {
 				transmit_start_tone(d, SKINNY_BUSYTONE, l->instance, sub->callid);
 			}
-			transmit_callstateonly(d, sub, SKINNY_BUSY);
+			transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_BUSY);
 			sub->alreadygone = 1;
 			ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
 			if (!d->earlyrtp) {
@@ -4312,7 +4268,7 @@
 			if (!d->earlyrtp) {
 				transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
 			}
-			transmit_callstateonly(d, sub, SKINNY_CONGESTION);
+			transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONGESTION);
 			sub->alreadygone = 1;
 			ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
 			if (!d->earlyrtp) {
@@ -4325,7 +4281,7 @@
 			if (!d->earlyrtp) {
 				transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid);
 			}
-			transmit_callstateonly(d, sub, SKINNY_PROGRESS);
+			transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_PROGRESS);
 			transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
 			transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
 			sub->progress = 1;
@@ -4492,7 +4448,7 @@
 	transmit_closereceivechannel(d, sub);
 	transmit_stopmediatransmission(d, sub);
 
-	transmit_callstateonly(d, sub, SKINNY_HOLD);
+	transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_HOLD);
 	transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
 	sub->onhold = 1;
 	return 1;
@@ -4516,7 +4472,7 @@
 	transmit_activatecallplane(d, l);
 
 	transmit_connect(d, sub);
-	transmit_callstateonly(d, sub, SKINNY_CONNECTED);
+	transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
 	transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
 	l->hookstate = SKINNY_OFFHOOK;
 	sub->onhold = 0;
@@ -4572,7 +4528,8 @@
 			sub->related = newsub;
 			newsub->xferor = 1;
 			l->activesub = newsub;
-			transmit_callstate(d, l->instance, SKINNY_OFFHOOK, newsub->callid);
+			transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+			transmit_activatecallplane(d, l);
 			transmit_clear_display_message(d, l->instance, newsub->callid);
 			transmit_start_tone(d, SKINNY_DIALTONE, l->instance, newsub->callid);
 			transmit_selectsoftkeys(d, l->instance, newsub->callid, KEYDEF_OFFHOOKWITHFEAT);
@@ -4690,7 +4647,8 @@
 	if (l->hookstate == SKINNY_ONHOOK) {
 		l->hookstate = SKINNY_OFFHOOK;
 		transmit_speaker_mode(d, SKINNY_SPEAKERON);
-		transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+		transmit_activatecallplane(d, l);
 	}
 	transmit_clear_display_message(d, l->instance, sub->callid);
 
@@ -4698,7 +4656,13 @@
 		set_callforwards(l, NULL, cfwdtype);
 		ast_safe_sleep(c, 500);
 		transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-		transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
+		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);
 		transmit_displaynotify(d, "CFwd disabled", 10);
 		if (sub->owner && sub->owner->_state != AST_STATE_UP) {
 			ast_indicate(c, -1);
@@ -4834,7 +4798,13 @@
 			ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
 			l->hookstate = SKINNY_ONHOOK;
 			transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-			transmit_callstate(d, l->instance, SKINNY_ONHOOK, instance);
+			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);
 			break;
 		}
 
@@ -4847,7 +4817,8 @@
 			l->activesub = sub;
 			if (l->hookstate == SKINNY_ONHOOK) {
 				l->hookstate = SKINNY_OFFHOOK;
-				transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+				transmit_activatecallplane(d, l);
 			}
 			transmit_clear_display_message(d, l->instance, sub->callid);
 			transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
@@ -4887,7 +4858,8 @@
 			if (l->hookstate == SKINNY_ONHOOK) {
 				l->hookstate = SKINNY_OFFHOOK;
 				transmit_speaker_mode(d, SKINNY_SPEAKERON);
-				transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+				transmit_activatecallplane(d, l);
 			}
 			transmit_clear_display_message(d, l->instance, sub->callid);
 			transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
@@ -4949,7 +4921,8 @@
 			if (l->hookstate == SKINNY_ONHOOK){
 				l->hookstate = SKINNY_OFFHOOK;
 				transmit_speaker_mode(d, SKINNY_SPEAKERON);
-				transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+				transmit_activatecallplane(d, l);
 			}
 
 			transmit_clear_display_message(d, l->instance, sub->callid);
@@ -5089,9 +5062,10 @@
 		if (sub && sub->outgoing) {
 			/* We're answering a ringing call */
 			ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
-			transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+			transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+			transmit_activatecallplane(d, l);
 			transmit_stop_tone(d, l->instance, sub->callid);
-			transmit_callstateonly(d, sub, SKINNY_CONNECTED);
+			transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
 			transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
 			transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
 			start_rtp(sub);
@@ -5104,7 +5078,8 @@
 				if (c) {
 					sub = c->tech_pvt;
 					l->activesub = sub;
-					transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+					transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+					transmit_activatecallplane(d, l);
 					transmit_clear_display_message(d, l->instance, sub->callid);
 					transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
 					transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
@@ -5189,9 +5164,10 @@
 	if (sub && sub->outgoing) {
 		/* We're answering a ringing call */
 		ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
-		transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+		transmit_activatecallplane(d, l);
 		transmit_stop_tone(d, l->instance, sub->callid);
-		transmit_callstateonly(d, sub, SKINNY_CONNECTED);
+		transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
 		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
 		start_rtp(sub);
 		ast_setstate(sub->owner, AST_STATE_UP);
@@ -5203,7 +5179,8 @@
 			if (c) {
 				sub = c->tech_pvt;
 				l->activesub = sub;
-				transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+				transmit_activatecallplane(d, l);
 				transmit_clear_display_message(d, l->instance, sub->callid);
 				transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
 				transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
@@ -5271,7 +5248,21 @@
 			ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, reference);
 	}
 
-	transmit_callstate(d, l->instance, l->hookstate, sub->callid);
+	if (l->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 (l->hookstate == SKINNY_OFFHOOK) {
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+		transmit_activatecallplane(d, l);
+	} else {
+		transmit_callstate(d, l->instance, sub->callid, l->hookstate);
+	}
+
 	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 */
@@ -5698,7 +5689,8 @@
 
 		sub = c->tech_pvt;
 		l->activesub = sub;
-		transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+		transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+		transmit_activatecallplane(d, l);
 		transmit_clear_display_message(d, l->instance, sub->callid);
 		transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
 
@@ -5798,7 +5790,13 @@
 			ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
 			l->hookstate = SKINNY_ONHOOK;
 			transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
-			transmit_callstate(d, l->instance, SKINNY_ONHOOK, instance);
+			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);
 			break;
 		}
 
@@ -5816,7 +5814,8 @@
 			if (l->hookstate == SKINNY_ONHOOK) {
 				l->hookstate = SKINNY_OFFHOOK;
 				transmit_speaker_mode(d, SKINNY_SPEAKERON);
-				transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+				transmit_activatecallplane(d, l);
 			}
 			transmit_clear_display_message(d, l->instance, sub->callid);
 			transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
@@ -5856,7 +5855,8 @@
 			}
 			ast_verb(1, "Call-id: %d\n", sub->callid);
 
-			transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+			transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+			transmit_activatecallplane(d, l);
 
 			transmit_clear_display_message(d, l->instance, sub->callid);
 			transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
@@ -5984,7 +5984,21 @@
 					ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, callreference);
 			}
 
-			transmit_callstate(d, l->instance, l->hookstate, sub->callid);
+			if (l->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 (l->hookstate == SKINNY_OFFHOOK) {
+				transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+				transmit_activatecallplane(d, l);
+			} else {
+				transmit_callstate(d, l->instance, sub->callid, l->hookstate);
+			}
+
 			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);
@@ -6042,9 +6056,10 @@
 		if (sub && sub->outgoing) {
 			/* We're answering a ringing call */
 			ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
-			transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
+			transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
+			transmit_activatecallplane(d, l);
 			transmit_stop_tone(d, l->instance, sub->callid);
-			transmit_callstateonly(d, sub, SKINNY_CONNECTED);
+			transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
 			transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
 			start_rtp(sub);
 			ast_setstate(sub->owner, AST_STATE_UP);
