Index: channels/chan_skinny.c
===================================================================
--- channels/chan_skinny.c	(revision 382285)
+++ channels/chan_skinny.c	(working copy)
@@ -1425,6 +1425,7 @@
 	int mwiblink;					\
 	int cancallforward;				\
 	int getforward;					\
+	int keymask;					\
 	int dnd;					\
 	int hidecallerid;				\
 	int amaflags;					\
@@ -1469,6 +1470,7 @@
 	.nat = 0,
 	.getforward = 0,
 	.prune = 0,
+	.keymask = KEYMASK_ALL,
 };
 static struct skinny_line_options *default_line = &default_line_struct;
 
@@ -1540,8 +1542,8 @@
 	char version_id[16];					\
 	char vmexten[AST_MAX_EXTENSION];			\
 	int type;						\
-	int protocolversion;				\
-	int hookstate;					\
+	int protocolversion;					\
+	int hookstate;						\
 	int lastlineinstance;					\
 	int lastcallreference;					\
 	struct ast_codec_pref confprefs;			\
@@ -3445,11 +3447,11 @@
 		case AST_EXTENSION_INUSE:
 			if (subline->sub && (subline->sub->substate == SKINNY_CONNECTED)) { /* Device has a real call */
 				transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
-				transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED, KEYMASK_ALL);
+				transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED, l->keymask);
 				send_displaypromptstatus(d, OCTAL_CONNECTED, "", 0, l->instance, subline->callid);
 			} else { /* Some other device has active call */
 				transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
-				transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, KEYMASK_ALL);
+				transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, l->keymask);
 				send_displaypromptstatus(d, "In Use", "", 0, l->instance, subline->callid);
 			}
 			transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
@@ -3458,14 +3460,14 @@
 			break;
 		case AST_EXTENSION_ONHOLD:
 			transmit_callstate(d, l->instance, subline->callid, SKINNY_HOLD);
-			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLAHOLD, KEYMASK_ALL);
+			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLAHOLD, l->keymask);
 			send_displaypromptstatus(d, "Hold", "", 0, l->instance, subline->callid);
 			transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
 			transmit_activatecallplane(d, l);
 			break;
 		case AST_EXTENSION_NOT_INUSE:
 			transmit_callstate(d, l->instance, subline->callid, SKINNY_ONHOOK);
-			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_ONHOOK, KEYMASK_ALL);
+			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_ONHOOK, l->keymask);
 			transmit_clearpromptmessage(d, l->instance, subline->callid);
 			transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
 			transmit_activatecallplane(d, l);
@@ -4880,7 +4882,7 @@
 	} else {
 		SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Wait for more digits\n", sub->callid);
 		if (ast_exists_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
-			transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD, KEYMASK_ALL);
+			transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD, l->keymask);
 			sub->dialer_sched = skinny_sched_add(matchdigittimeout, skinny_dialer_cb, sub);
 		} else {
 			sub->dialer_sched = skinny_sched_add(gendigittimeout, skinny_dialer_cb, sub);
@@ -5451,12 +5453,16 @@
 			ast_channel_amaflags_set(tmp, l->amaflags);
 
 		ast_module_ref(ast_module_info->self);
-		ast_channel_callgroup_set(tmp, l->callgroup);
+		ast_channel_callgroup_set(tmp, (l->callgroup ? l->callgroup : l->pickupgroup));
 		ast_channel_pickupgroup_set(tmp, l->pickupgroup);
 
-		ast_channel_named_callgroups_set(tmp, l->named_callgroups);
+		ast_channel_named_callgroups_set(tmp, (l->named_callgroups ? l->named_callgroups : l->named_pickupgroups));
 		ast_channel_named_pickupgroups_set(tmp, l->named_pickupgroups);
 
+		if (!l->pickupgroup && !l->named_pickupgroups) {
+			l->keymask &= ~KEYMASK_GPICKUP;
+		}
+
 		/* XXX Need to figure out how to handle CFwdNoAnswer */
 		if (l->cfwdtype & SKINNY_CFWD_ALL) {
 			ast_channel_call_forward_set(tmp, l->call_forward_all);
@@ -5624,7 +5630,7 @@
 			if (subline->callid) {
 				transmit_stop_tone(d, l->instance, sub->callid);
 				transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
-				transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, KEYMASK_ALL);
+				transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, l->keymask);
 				send_displaypromptstatus(d, "In Use", "", 0, l->instance, subline->callid);
 			}
 
@@ -5639,7 +5645,7 @@
 		case SUBSTATE_CONNECTED:
 			transmit_activatecallplane(d, l);
 			transmit_stop_tone(d, l->instance, sub->callid);
-			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED, KEYMASK_ALL);
+			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_CONNECTED, l->keymask);
 			transmit_callstate(d, l->instance, subline->callid, SKINNY_CONNECTED);
 			if (!sub->rtp) {
 				start_rtp(sub);
@@ -5666,7 +5672,7 @@
 			transmit_stopmediatransmission(d, sub);
 
 			transmit_callstate(d, l->instance, subline->callid, SKINNY_CALLREMOTEMULTILINE);
-			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, KEYMASK_ALL);
+			transmit_selectsoftkeys(d, l->instance, subline->callid, KEYDEF_SLACONNECTEDNOTACTIVE, l->keymask);
 			send_displaypromptstatus(d, "In Use", "", 0, l->instance, subline->callid);
 
 			sub->substate = SUBSTATE_HOLD;
@@ -5704,7 +5710,7 @@
 		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, KEYMASK_ALL);
+		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK, l->keymask);
 		send_displaypromptstatus(d, OCTAL_ENTRNUM, "", 0, l->instance, sub->callid);
 
 		sub->substate = SUBSTATE_OFFHOOK;
@@ -5726,6 +5732,9 @@
 			transmit_ringer_mode(d, SKINNY_RING_OFF);
 			transmit_definetimedate(d);
 			transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
+			if (l == d->activeline) {
+				transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK, l->keymask);
+			}
 		} else {
 			transmit_stop_tone(d, l->instance, sub->callid);
 			transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
@@ -5762,7 +5771,7 @@
 			transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
 			transmit_stop_tone(d, l->instance, sub->callid);
 			transmit_clear_display_message(d, l->instance, sub->callid);
-			transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT, KEYMASK_ALL);
+			transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT, l->keymask);
 			send_displaypromptstatus(d, "Dialing", "", 0, l->instance, sub->callid);
 		}
 
@@ -5815,7 +5824,7 @@
 			fromnum = "Unknown";
 		}
 		transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
-		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN, KEYMASK_ALL);
+		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN, l->keymask);
 		send_displaypromptstatus(d, OCTAL_FROM, fromnum, 0, l->instance, sub->callid);
 		send_displayprinotify(d, OCTAL_FROM, fromnum, 10, 5);
 		send_callinfo(sub, connected_id);
@@ -5842,7 +5851,7 @@
 		}
 		transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
 		transmit_callstate(d, l->instance, sub->callid, SKINNY_CALLWAIT);
-		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN, KEYMASK_ALL);
+		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN, l->keymask);
 		send_displaypromptstatus(d, OCTAL_CALLWAITING, "", 0, l->instance, sub->callid);
 		send_callinfo(sub, connected_id);
 		transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
@@ -5865,7 +5874,7 @@
 		transmit_stop_tone(d, l->instance, sub->callid);
 		transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
 		send_displaypromptstatus(d, OCTAL_CONNECTED, "", 0, l->instance, sub->callid);
-		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED, KEYMASK_ALL);
+		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED, l->keymask);
 		if (!sub->rtp) {
 			start_rtp(sub);
 		}
@@ -5941,7 +5950,7 @@
 
 		transmit_callstate(d, l->instance, sub->callid, SKINNY_HOLD);
 		transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
-		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD, KEYMASK_ALL);
+		transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD, l->keymask);
 		sub->substate = SUBSTATE_HOLD;
 		break;
 	default:
@@ -6155,7 +6164,7 @@
 		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, KEYMASK_ALL);
+		transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK, l->keymask);
 		transmit_activatecallplane(d, l);
 		transmit_displaynotify(d, "CFwd disabled", 10);
 		if (sub->owner && ast_channel_state(sub->owner) != AST_STATE_UP) {
@@ -6227,7 +6236,7 @@
 			len = strlen(sub->exten);
 			if (len == 0) {
 				transmit_stop_tone(d, l->instance, sub->callid);
-				transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD, KEYMASK_ALL&~KEYMASK_FORCEDIAL);
+				transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_DADFD, l->keymask&~KEYMASK_FORCEDIAL);
 			}
 			if (len < sizeof(sub->exten) - 1 && dgt != immed_dialchar) {
 				sub->exten[len] = dgt;
@@ -7127,7 +7136,7 @@
 				sub->exten[len-1] = '\0';
 				if (len == 1) {
 					transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
-					transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK, KEYMASK_ALL);
+					transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK, l->keymask);
 				}
 				transmit_backspace(d, l->instance, sub->callid);
 			}
@@ -7257,6 +7266,10 @@
 	case SOFTKEY_GPICKUP:
 		SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFTKEY_GPICKUP from %s, inst %d, callref %d\n",
 			d->name, instance, callreference);
+		if (!(l->pickupgroup || l->named_pickupgroups)) {
+			ast_log(LOG_WARNING, "SOFTKEY_GPICKUP should have been disabled on line %s\n", l->name);
+			break;
+		}
 		if (!sub || !sub->owner) {
 			c = skinny_new(l, NULL, AST_STATE_DOWN, NULL, SKINNY_INCOMING);
 		} else {
@@ -7392,7 +7405,7 @@
 	case SOFT_KEY_SET_REQ_MESSAGE:
 		SKINNY_DEBUG(DEBUG_PACKET, 3, "Received SOFT_KEY_SET_REQ_MESSAGE from %s\n", d->name);
 		transmit_softkeysetres(d);
-		transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK, KEYMASK_ALL);
+		transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK, d->activeline->keymask);
 		break;
 	case SOFT_KEY_EVENT_MESSAGE:
 		/* SKINNY_PACKETDEBUG handled in handle_soft_key_event_message */
