[asterisk-commits] qwell: trunk r98776 - /trunk/channels/chan_skinny.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jan 14 11:40:36 CST 2008


Author: qwell
Date: Mon Jan 14 11:40:36 2008
New Revision: 98776

URL: http://svn.digium.com/view/asterisk?view=rev&rev=98776
Log:
Add proper call forwarding (all and busy) support for chan_skinny.
Note: NoAnswer support is currently not implemented, as it would take a
 significant amount of work to figure out how to do correctly.

Closes issue #11310, patches, testing, and support by DEA, mvanbaak, and myself.

Modified:
    trunk/channels/chan_skinny.c

Modified: trunk/channels/chan_skinny.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_skinny.c?view=diff&rev=98776&r1=98775&r2=98776
==============================================================================
--- trunk/channels/chan_skinny.c (original)
+++ trunk/channels/chan_skinny.c Mon Jan 14 11:40:36 2008
@@ -371,6 +371,18 @@
 	uint32_t space[3];
 };
 
+#define FORWARD_STAT_MESSAGE 0x0090
+struct forward_stat_message {
+	uint32_t activeforward;
+	uint32_t lineNumber;
+	uint32_t fwdall;
+	char fwdallnum[24];
+	uint32_t fwdbusy;
+	char fwdbusynum[24];
+	uint32_t fwdnoanswer;
+	char fwdnoanswernum[24];
+};
+
 #define SPEED_DIAL_STAT_RES_MESSAGE 0x0091
 struct speed_dial_stat_res_message {
 	uint32_t speedDialNumber;
@@ -422,6 +434,7 @@
 #define STIMULUS_LINE			0x09
 #define STIMULUS_VOICEMAIL		0x0F
 #define STIMULUS_AUTOANSWER		0x11
+#define STIMULUS_DND			0x3F
 #define STIMULUS_CONFERENCE		0x7D
 #define STIMULUS_CALLPARK		0x7E
 #define STIMULUS_CALLPICKUP		0x7F
@@ -439,6 +452,7 @@
 #define BT_LINE				STIMULUS_LINE
 #define BT_VOICEMAIL			STIMULUS_VOICEMAIL
 #define BT_AUTOANSWER			STIMULUS_AUTOANSWER
+#define BT_DND				STIMULUS_DND
 #define BT_CONFERENCE			STIMULUS_CONFERENCE
 #define BT_CALLPARK			STIMULUS_CALLPARK
 #define BT_CALLPICKUP			STIMULUS_CALLPICKUP
@@ -551,6 +565,8 @@
 #define SOFTKEY_MEETME			0x10
 #define SOFTKEY_PICKUP			0x11
 #define SOFTKEY_GPICKUP			0x12
+#define SOFTKEY_DND			0x13
+#define SOFTKEY_IDIVERT			0x14
 
 struct soft_key_template_definition soft_key_template_default[] = {
 	{ "\200\001", 		SOFTKEY_REDIAL },
@@ -571,6 +587,8 @@
 	{ "\200\020", 		SOFTKEY_MEETME },
 	{ "\200\021", 		SOFTKEY_PICKUP },
 	{ "\200\022", 		SOFTKEY_GPICKUP },
+	{ "\200\077", 		SOFTKEY_DND },
+	{ "\200\120", 		SOFTKEY_IDIVERT },
 };
 
 /* Localized message "codes" (in octal)
@@ -718,6 +736,7 @@
 	SOFTKEY_NEWCALL,
 	SOFTKEY_CFWDALL,
 	SOFTKEY_CFWDBUSY,
+	SOFTKEY_DND,
 	SOFTKEY_GPICKUP,
 	SOFTKEY_CONFRN,
 };
@@ -911,6 +930,7 @@
 	struct dialed_number_message dialednumber;
 	struct soft_key_event_message softkeyeventmessage;
 	struct enbloc_call_message enbloccallmessage;
+	struct forward_stat_message forwardstat;
 };
 
 /* packet composition */
@@ -1037,6 +1057,10 @@
 #define SKINNY_RING_OUTSIDE 3
 #define SKINNY_RING_FEATURE 4
 
+#define SKINNY_CFWD_ALL       (1 << 0)
+#define SKINNY_CFWD_BUSY      (1 << 1)
+#define SKINNY_CFWD_NOANSWER  (1 << 2)
+
 #define TYPE_TRUNK 1
 #define TYPE_LINE 2
 
@@ -1121,7 +1145,10 @@
 	char cid_num[AST_MAX_EXTENSION];		/* Caller*ID */
 	char cid_name[AST_MAX_EXTENSION];		/* Caller*ID */
 	char lastcallerid[AST_MAX_EXTENSION];		/* Last Caller*ID */
-	char call_forward[AST_MAX_EXTENSION];
+	int cfwdtype;
+	char call_forward_all[AST_MAX_EXTENSION];
+	char call_forward_busy[AST_MAX_EXTENSION];
+	char call_forward_noanswer[AST_MAX_EXTENSION];
 	char mailbox[AST_MAX_EXTENSION];
 	char vmexten[AST_MAX_EXTENSION];
 	char regexten[AST_MAX_EXTENSION];		/* Extension for auto-extensions */
@@ -1137,6 +1164,7 @@
 	int threewaycalling;
 	int mwiblink;
 	int cancallforward;
+	int getforward;
 	int callreturn;
 	int dnd; /* How does this affect callwait?  Do we just deny a skinny_request if we're dnd? */
 	int hascallerid;
@@ -1585,6 +1613,41 @@
 	}
 }
 
+static int set_callforwards(struct skinny_line *l, const char *cfwd, int cfwdtype)
+{
+	if (!l)
+		return 0;
+
+	if (!ast_strlen_zero(cfwd)) {
+		if (cfwdtype & SKINNY_CFWD_ALL) {
+			l->cfwdtype |= SKINNY_CFWD_ALL;
+			ast_copy_string(l->call_forward_all, cfwd, sizeof(l->call_forward_all));
+		}
+		if (cfwdtype & SKINNY_CFWD_BUSY) {
+			l->cfwdtype |= SKINNY_CFWD_BUSY;
+			ast_copy_string(l->call_forward_busy, cfwd, sizeof(l->call_forward_busy));
+		}
+		if (cfwdtype & SKINNY_CFWD_NOANSWER) {
+			l->cfwdtype |= SKINNY_CFWD_NOANSWER;
+			ast_copy_string(l->call_forward_noanswer, cfwd, sizeof(l->call_forward_noanswer));
+		}
+	} else {
+		if (cfwdtype & SKINNY_CFWD_ALL) {
+			l->cfwdtype &= ~SKINNY_CFWD_ALL;
+			memset(l->call_forward_all, 0, sizeof(l->call_forward_all));
+		}
+		if (cfwdtype & SKINNY_CFWD_BUSY) {
+			l->cfwdtype &= ~SKINNY_CFWD_BUSY;
+			memset(l->call_forward_busy, 0, sizeof(l->call_forward_busy));
+		}
+		if (cfwdtype & SKINNY_CFWD_NOANSWER) {
+			l->cfwdtype &= ~SKINNY_CFWD_NOANSWER;
+			memset(l->call_forward_noanswer, 0, sizeof(l->call_forward_noanswer));
+		}
+	}
+	return l->cfwdtype;
+}
+
 static void cleanup_stale_contexts(char *new, char *old)
 {
 	char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT];
@@ -2043,6 +2106,51 @@
 		req->data.activatecallplane.lineInstance = htolel(instance);
 		transmit_response(s, req);
 	}
+}
+
+
+static void transmit_cfwdstate(struct skinnysession *s, struct skinny_line *l)
+{
+	struct skinny_req *req;
+	int anyon = 0;
+
+	if (!(req = req_alloc(sizeof(struct forward_stat_message), FORWARD_STAT_MESSAGE)))
+		return;
+
+	if (l->cfwdtype & SKINNY_CFWD_ALL) {
+		if (!ast_strlen_zero(l->call_forward_all)) {
+			ast_copy_string(req->data.forwardstat.fwdallnum, l->call_forward_all, sizeof(req->data.forwardstat.fwdallnum));
+			req->data.forwardstat.fwdall = htolel(1);
+			anyon++;
+		} else {
+			req->data.forwardstat.fwdall = htolel(0);
+		}
+	}
+	if (l->cfwdtype & SKINNY_CFWD_BUSY) {
+		if (!ast_strlen_zero(l->call_forward_busy)) {
+			ast_copy_string(req->data.forwardstat.fwdbusynum, l->call_forward_busy, sizeof(req->data.forwardstat.fwdbusynum));
+			req->data.forwardstat.fwdbusy = htolel(1);
+			anyon++;
+		} else {
+			req->data.forwardstat.fwdbusy = htolel(0);
+		}
+	}
+	if (l->cfwdtype & SKINNY_CFWD_NOANSWER) {
+		if (!ast_strlen_zero(l->call_forward_noanswer)) {
+			ast_copy_string(req->data.forwardstat.fwdnoanswernum, l->call_forward_noanswer, sizeof(req->data.forwardstat.fwdnoanswernum));
+			req->data.forwardstat.fwdnoanswer = htolel(1);
+			anyon++;
+		} else {
+			req->data.forwardstat.fwdnoanswer = htolel(0);
+		}
+	}
+	req->data.forwardstat.lineNumber = htolel(l->instance);
+	if (anyon)
+		req->data.forwardstat.activeforward = htolel(7);
+	else
+		req->data.forwardstat.activeforward = htolel(0);
+
+	transmit_response(s, req);
 }
 
 static int skinny_extensionstate_cb(char *context, char *exten, int state, void *data)
@@ -2665,7 +2773,9 @@
 			ast_cli(a->fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
 			ast_cli(a->fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
 			ast_cli(a->fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
-			ast_cli(a->fd, "CallForward:      %s\n", S_OR(l->call_forward, "<not set>"));
+			ast_cli(a->fd, "CFwdAll:          %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
+			ast_cli(a->fd, "CFwdBusy:         %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
+			ast_cli(a->fd, "CFwdNoAnswer:     %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
 			ast_cli(a->fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
 			ast_cli(a->fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
 			ast_cli(a->fd, "MWIblink:         %d\n", l->mwiblink);
@@ -2923,6 +3033,8 @@
 					l->pickupgroup = cur_pickupgroup;
 					l->callreturn = callreturn;
 					l->cancallforward = cancallforward;
+					l->getforward = 0;
+					set_callforwards(l, NULL, 0);
 					l->callwaiting = callwaiting;
 					l->transfer = transfer;
 					l->threewaycalling = threewaycalling;
@@ -3035,7 +3147,6 @@
 	int len = 0;
 	int timeout = firstdigittimeout;
 	int res = 0;
-	int getforward=0;
 	int loop_pause = 100;
 
 	ast_verb(3, "Starting simple switch on '%s@%s'\n", l->name, d->name);
@@ -3062,22 +3173,26 @@
 		}
 		if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) {
 			if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) {
-				if (getforward) {
+				if (l->getforward) {
 					/* Record this as the forwarding extension */
-					ast_copy_string(l->call_forward, d->exten, sizeof(l->call_forward));
-					ast_verb(3, "Setting call forward to '%s' on channel %s\n",
-							l->call_forward, c->name);
+					set_callforwards(l, d->exten, l->getforward);
+					ast_verb(3, "Setting call forward (%d) to '%s' on channel %s\n",
+							l->cfwdtype, d->exten, c->name);
 					transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
-					if (res) {
-						break;
-					}
+					transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
+					transmit_displaynotify(s, "CFwd enabled", 10);
+					transmit_cfwdstate(s, l);
 					ast_safe_sleep(c, 500);
 					ast_indicate(c, -1);
  					ast_safe_sleep(c, 1000);
 					memset(d->exten, 0, sizeof(d->exten));
-					transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
 					len = 0;
-					getforward = 0;
+					l->getforward = 0;
+					if (sub->owner && sub->owner->_state != AST_STATE_UP) {
+						ast_indicate(c, -1);
+						ast_hangup(c);
+					}
+					return NULL;
 				} else {
 					ast_copy_string(c->exten, d->exten, sizeof(c->exten));
 					ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed));
@@ -3366,6 +3481,35 @@
 	transmit_tone(d->session, digit, l->instance, sub->callid);
 #endif
 	return -1; /* Stop inband indications */
+}
+
+static int get_devicestate(struct skinny_line *l)
+{
+	struct skinny_subchannel *sub;
+	int res = AST_DEVICE_UNKNOWN;
+
+	if (!l)
+		res = AST_DEVICE_INVALID;
+	else if (!l->parent)
+		res = AST_DEVICE_UNAVAILABLE;
+	else if (l->dnd)
+		res = AST_DEVICE_BUSY;
+	else {
+		if (l->hookstate == SKINNY_ONHOOK) {
+			res = AST_DEVICE_NOT_INUSE;
+		} else {
+			res = AST_DEVICE_INUSE;
+		}
+
+		for (sub = l->sub; sub; sub = sub->next) {
+			if (sub->onhold) {
+				res = AST_DEVICE_ONHOLD;
+				break;
+			}
+		}
+	}
+
+	return res;
 }
 
 static char *control2str(int ind) {
@@ -3554,7 +3698,16 @@
 		ast_module_ref(ast_module_info->self);
 		tmp->callgroup = l->callgroup;
 		tmp->pickupgroup = l->pickupgroup;
-		ast_string_field_set(tmp, call_forward, l->call_forward);
+
+		/* XXX Need to figure out how to handle CFwdNoAnswer */
+		if (l->cfwdtype & SKINNY_CFWD_ALL) {
+			ast_string_field_set(tmp, call_forward, l->call_forward_all);
+		} else if (l->cfwdtype & SKINNY_CFWD_BUSY) {
+			if (get_devicestate(l) != AST_DEVICE_NOT_INUSE) {
+				ast_string_field_set(tmp, call_forward, l->call_forward_busy);
+			}
+		}
+
 		ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
 		ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
 
@@ -3707,6 +3860,45 @@
 	return res;
 }
 
+static int handle_callforward_button(struct skinny_subchannel *sub, int cfwdtype)
+{
+	struct skinny_line *l = sub->parent;
+	struct skinny_device *d = l->parent;
+	struct skinnysession *s = d->session;
+	struct ast_channel *c = sub->owner;
+	pthread_t t;
+
+	if (l->hookstate == SKINNY_ONHOOK) {
+		l->hookstate = SKINNY_OFFHOOK;
+		transmit_speaker_mode(s, SKINNY_SPEAKERON);
+		transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
+	}
+	if (skinnydebug)
+		ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
+	transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
+
+	if (l->cfwdtype & cfwdtype) {
+		set_callforwards(l, NULL, cfwdtype);
+		ast_safe_sleep(c, 500);
+		transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
+		transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
+		transmit_displaynotify(s, "CFwd disabled", 10);
+		if (sub->owner && sub->owner->_state != AST_STATE_UP) {
+			ast_indicate(c, -1);
+			ast_hangup(c);
+		}
+		transmit_cfwdstate(s, l);
+	} else {
+		l->getforward = cfwdtype;
+		transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
+		transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
+		if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
+			ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
+			ast_hangup(c);
+		}
+	}
+	return 0;
+}
 static int handle_ip_port_message(struct skinny_req *req, struct skinnysession *s)
 {
 	/* no response necessary */
@@ -3974,32 +4166,75 @@
 			ast_verbose("Received Stimulus: Park Call(%d/%d)\n", instance, callreference);
 		/* XXX Park the call */
 		break;
-	case STIMULUS_FORWARDALL:
-		if (skinnydebug)
-			ast_verbose("Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
-		/* Why is DND under FORWARDALL? */
-		/* Because it's the same thing. */
+	case STIMULUS_DND:
+		if (skinnydebug)
+			ast_verbose("Received Stimulus: DND (%d/%d)\n", instance, callreference);
 
 		/* Do not disturb */
 		if (l->dnd != 0){
 			ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
 			l->dnd = 0;
-			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
+			transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_ON);
 			transmit_displaynotify(s, "DnD disabled", 10);
 		} else {
 			ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
 			l->dnd = 1;
-			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
+			transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
 			transmit_displaynotify(s, "DnD enabled", 10);
 		}
 		break;
+	case STIMULUS_FORWARDALL:
+		if (skinnydebug)
+			ast_verbose("Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
+
+		if (!sub || !sub->owner) {
+			c = skinny_new(l, AST_STATE_DOWN);
+		} else {
+			c = sub->owner;
+		}
+
+		if (!c) {
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+		} else {
+			sub = c->tech_pvt;
+			handle_callforward_button(sub, SKINNY_CFWD_ALL);
+		}
+		break;
 	case STIMULUS_FORWARDBUSY:
 		if (skinnydebug)
 			ast_verbose("Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
+
+		if (!sub || !sub->owner) {
+			c = skinny_new(l, AST_STATE_DOWN);
+		} else {
+			c = sub->owner;
+		}
+
+		if (!c) {
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+		} else {
+			sub = c->tech_pvt;
+			handle_callforward_button(sub, SKINNY_CFWD_BUSY);
+		}
 		break;
 	case STIMULUS_FORWARDNOANSWER:
 		if (skinnydebug)
 			ast_verbose("Received Stimulus: Forward No Answer (%d/%d)\n", instance, callreference);
+
+#if 0 /* Not sure how to handle this yet */
+		if (!sub || !sub->owner) {
+			c = skinny_new(l, AST_STATE_DOWN);
+		} else {
+			c = sub->owner;
+		}
+
+		if (!c) {
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+		} else {
+			sub = c->tech_pvt;
+			handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
+		}
+#endif
 		break;
 	case STIMULUS_DISPLAY:
 		/* Not sure what this is */
@@ -4796,30 +5031,75 @@
 			ast_verbose("Received Softkey Event: Transfer(%d/%d)\n", instance, callreference);
 		/* XXX figure out how to transfer */
 		break;
-	case SOFTKEY_CFWDALL:
-		if (skinnydebug)
-			ast_verbose("Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
+	case SOFTKEY_DND:
+		if (skinnydebug)
+			ast_verbose("Received Softkey Event: DND(%d/%d)\n", instance, callreference);
 
 		/* Do not disturb */
 		if (l->dnd != 0){
 			ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
 			l->dnd = 0;
-			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
+			transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_ON);
 			transmit_displaynotify(s, "DnD disabled", 10);
 		} else {
 			ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
 			l->dnd = 1;
-			transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
+			transmit_lamp_indication(s, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
 			transmit_displaynotify(s, "DnD enabled", 10);
 		}
 		break;
+	case SOFTKEY_CFWDALL:
+		if (skinnydebug)
+			ast_verbose("Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
+
+		if (!sub || !sub->owner) {
+			c = skinny_new(l, AST_STATE_DOWN);
+		} else {
+			c = sub->owner;
+		}
+
+		if (!c) {
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+		} else {
+			sub = c->tech_pvt;
+			handle_callforward_button(sub, SKINNY_CFWD_ALL);
+		}
+		break;
 	case SOFTKEY_CFWDBUSY:
 		if (skinnydebug)
 			ast_verbose("Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
+
+		if (!sub || !sub->owner) {
+			c = skinny_new(l, AST_STATE_DOWN);
+		} else {
+			c = sub->owner;
+		}
+
+		if (!c) {
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+		} else {
+			sub = c->tech_pvt;
+			handle_callforward_button(sub, SKINNY_CFWD_BUSY);
+		}
 		break;
 	case SOFTKEY_CFWDNOANSWER:
 		if (skinnydebug)
 			ast_verbose("Received Softkey Event: Forward No Answer (%d/%d)\n", instance, callreference);
+
+#if 0 /* Not sure how to handle this yet */
+		if (!sub || !sub->owner) {
+			c = skinny_new(l, AST_STATE_DOWN);
+		} else {
+			c = sub->owner;
+		}
+
+		if (!c) {
+			ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
+		} else {
+			sub = c->tech_pvt;
+			handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
+		}
+#endif
 		break;
 	case SOFTKEY_BKSPC:
 		if (skinnydebug)
@@ -5391,6 +5671,18 @@
 	return 0;
 }
 
+static int skinny_devicestate(void *data)
+{
+	struct skinny_line *l;
+	char *tmp;
+
+	tmp = ast_strdupa(data);
+
+	l = find_line_by_name(tmp);
+
+	return get_devicestate(l);
+}
+
 static struct ast_channel *skinny_request(const char *type, int format, void *data, int *cause)
 {
 	int oldformat;
@@ -5424,41 +5716,6 @@
 	}
 	restart_monitor();
 	return tmpc;
-}
-
-static int skinny_devicestate(void *data)
-{
-	struct skinny_line *l;
-	struct skinny_subchannel *sub;
-	char *tmp;
-	int res = AST_DEVICE_UNKNOWN;
-
-	tmp = ast_strdupa(data);
-
-	l = find_line_by_name(tmp);
-
-	if (!l)
-		res = AST_DEVICE_INVALID;
-	else if (!l->parent)
-		res = AST_DEVICE_UNAVAILABLE;
-	else if (l->dnd)
-		res = AST_DEVICE_BUSY;
-	else {
-		if (l->hookstate == SKINNY_ONHOOK) {
-			res = AST_DEVICE_NOT_INUSE;
-		} else {
-			res = AST_DEVICE_INUSE;
-		}
-
-		for (sub = l->sub; sub; sub = sub->next) {
-			if (sub->onhold) {
-				res = AST_DEVICE_ONHOLD;
-				break;
-			}
-		}
-	}
-
-	return res;
 }
 
 static int reload_config(void)




More information about the asterisk-commits mailing list