diff --git a/Makefile b/Makefile
index 86b17ee8d525ddb5a2dc1a0ff0ed19e71b30ee07..5fe54e86602f8d06f9dd22d0f44a7cfb6cd55899 100755
--- a/Makefile
+++ b/Makefile
@@ -254,7 +254,7 @@ OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
 	cdr.o tdd.o acl.o rtp.o manager.o asterisk.o \
 	dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
 	astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
-	utils.o config_old.o plc.o jitterbuf.o dnsmgr.o
+	utils.o config_old.o plc.o jitterbuf.o dnsmgr.o devicestate.o
 ifeq (${OSARCH},Darwin)
 OBJS+=poll.o dlfcn.o
 ASTLINK=-Wl,-dynamic
diff --git a/apps/app_chanisavail.c b/apps/app_chanisavail.c
index 1fe374108cbfc4999afcd7c8ddb0389b4b8cedef..3039f12752aa838c82610d106fcedeee57a1c485 100755
--- a/apps/app_chanisavail.c
+++ b/apps/app_chanisavail.c
@@ -31,6 +31,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
 #include "asterisk/app.h"
+#include "asterisk/devicestate.h"
 
 static char *tdesc = "Check if channel is available";
 
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 4b99f4d6e1babe13ba34be8463734f831e4fcc0f..cae7e5ef636bc98b0ee41ce48adf73062b135143 100755
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/causes.h"
 #include "asterisk/astdb.h"
+#include "asterisk/devicestate.h"
 
 #define QUEUE_STRATEGY_RINGALL		0
 #define QUEUE_STRATEGY_ROUNDROBIN	1
diff --git a/asterisk.c b/asterisk.c
index 249931ed3a38378b1bc8aef2f1c5f9936b273071..b2ce56ea10fe34c126ab1b2b31eb7187b884c098 100755
--- a/asterisk.c
+++ b/asterisk.c
@@ -65,6 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/version.h"
 #include "asterisk/build.h"
 #include "asterisk/linkedlists.h"
+#include "asterisk/devicestate.h"
 
 #include "defaults.h"
 
@@ -2095,6 +2096,10 @@ int main(int argc, char *argv[])
 		printf(term_quit());
 		exit(1);
 	}
+	if (ast_device_state_engine_init()) {
+		printf(term_quit());
+		exit(1);
+	}
 	ast_rtp_init();
 	if (ast_image_init()) {
 		printf(term_quit());
diff --git a/channel.c b/channel.c
index 04b77af27e206817ee652a12e37882cc6d4cddc6..6ec2ff044f1262187d560e2605e2b96564f20ae9 100755
--- a/channel.c
+++ b/channel.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/lock.h"
 #include "asterisk/app.h"
 #include "asterisk/transcap.h"
+#include "asterisk/devicestate.h"
 
 /* uncomment if you have problems with 'monitoring' synchronized files */
 #if 0
@@ -295,6 +296,58 @@ int ast_channel_register(const struct ast_channel_tech *tech)
 	return 0;
 }
 
+void ast_channel_unregister(const struct ast_channel_tech *tech)
+{
+	struct chanlist *chan, *last=NULL;
+
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type);
+
+	ast_mutex_lock(&chlock);
+
+	chan = backends;
+	while (chan) {
+		if (chan->tech == tech) {
+			if (last)
+				last->next = chan->next;
+			else
+				backends = backends->next;
+			free(chan);
+			ast_mutex_unlock(&chlock);
+
+			if (option_verbose > 1)
+				ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type);
+
+			return;
+		}
+		last = chan;
+		chan = chan->next;
+	}
+
+	ast_mutex_unlock(&chlock);
+}
+
+const struct ast_channel_tech *ast_get_channel_tech(const char *name)
+{
+	struct chanlist *chanls;
+
+	if (ast_mutex_lock(&chlock)) {
+		ast_log(LOG_WARNING, "Unable to lock channel tech list\n");
+		return NULL;
+	}
+
+	for (chanls = backends; chanls; chanls = chanls->next) {
+		if (strcasecmp(name, chanls->tech->type))
+			continue;
+
+		ast_mutex_unlock(&chlock);
+		return chanls->tech;
+	}
+
+	ast_mutex_unlock(&chlock);
+	return NULL;
+}
+
 /*--- ast_cause2str: Gives the string form of a given hangup cause */
 const char *ast_cause2str(int cause)
 {
@@ -605,7 +658,7 @@ void ast_channel_undefer_dtmf(struct ast_channel *chan)
  * We should definitely go for a better scheme that is deadlock-free.
  */
 static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
-					       const char *name)
+					       const char *name, const int namelen)
 {
 	const char *msg = prev ? "deadlock" : "initial deadlock";
 	int retries, done;
@@ -615,8 +668,14 @@ static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
 		ast_mutex_lock(&chlock);
 		for (c = channels; c; c = c->next) {
 			if (prev == NULL) {
-				/* want either head of list or match by name */
-				if (name == NULL || !strcasecmp(name, c->name))
+				/* want head of list */
+				if (!name)
+					break;
+				/* want match by full name */
+				if (!namelen && !strcasecmp(c->name, name))
+					break;
+				/* want match by name prefix */
+				if (!strncasecmp(c->name, name, namelen))
 					break;
 			} else if (c == prev) { /* found, return c->next */
 				c = c->next;
@@ -646,13 +705,19 @@ static struct ast_channel *channel_find_locked(const struct ast_channel *prev,
 /*--- ast_channel_walk_locked: Browse channels in use */
 struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev)
 {
-	return channel_find_locked(prev, NULL);
+	return channel_find_locked(prev, NULL, 0);
 }
 
 /*--- ast_get_channel_by_name_locked: Get channel by name and lock it */
 struct ast_channel *ast_get_channel_by_name_locked(const char *name)
 {
-	return channel_find_locked(NULL, name);
+	return channel_find_locked(NULL, name, 0);
+}
+
+/*--- ast_get_channel_by_name_prefix_locked: Get channel by name prefix and lock it */
+struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen)
+{
+	return channel_find_locked(NULL, name, namelen);
 }
 
 /*--- ast_safe_sleep_conditional: Wait, look for hangups and condition arg */
@@ -964,37 +1029,6 @@ int ast_hangup(struct ast_channel *chan)
 	return res;
 }
 
-void ast_channel_unregister(const struct ast_channel_tech *tech)
-{
-	struct chanlist *chan, *last=NULL;
-
-	if (option_debug)
-		ast_log(LOG_DEBUG, "Unregistering channel type '%s'\n", tech->type);
-
-	ast_mutex_lock(&chlock);
-
-	chan = backends;
-	while (chan) {
-		if (chan->tech == tech) {
-			if (last)
-				last->next = chan->next;
-			else
-				backends = backends->next;
-			free(chan);
-			ast_mutex_unlock(&chlock);
-
-			if (option_verbose > 1)
-				ast_verbose( VERBOSE_PREFIX_2 "Unregistered channel type '%s'\n", tech->type);
-
-			return;
-		}
-		last = chan;
-		chan = chan->next;
-	}
-
-	ast_mutex_unlock(&chlock);
-}
-
 int ast_answer(struct ast_channel *chan)
 {
 	int res = 0;
@@ -2167,70 +2201,6 @@ struct ast_channel *ast_request(const char *type, int format, void *data, int *c
 	return c;
 }
 
-int ast_parse_device_state(char *device)
-{
-	char name[AST_CHANNEL_NAME] = "";
-	char *cut;
-	struct ast_channel *chan;
-
-	chan = ast_channel_walk_locked(NULL);
-	while (chan) {
-		ast_copy_string(name, chan->name, sizeof(name));
-		ast_mutex_unlock(&chan->lock);
-		cut = strchr(name,'-');
-		if (cut)
-		        *cut = 0;
-		if (!strcmp(name, device)) {
-			if (chan->_state == AST_STATE_RINGING) {
-				return AST_DEVICE_RINGING;
-			} else {
-				return AST_DEVICE_INUSE;
-			}
-		}
-		chan = ast_channel_walk_locked(chan);
-	}
-	return AST_DEVICE_UNKNOWN;
-}
-
-int ast_device_state(char *device)
-{
-	char tech[AST_MAX_EXTENSION] = "";
-	char *number;
-	struct chanlist *chanls;
-	int res = 0;
-	
-	ast_copy_string(tech, device, sizeof(tech));
-	number = strchr(tech, '/');
-	if (!number) {
-	    return AST_DEVICE_INVALID;
-	}
-	*number = 0;
-	number++;
-		
-	if (ast_mutex_lock(&chlock)) {
-		ast_log(LOG_WARNING, "Unable to lock channel list\n");
-		return -1;
-	}
-	chanls = backends;
-	while(chanls) {
-		if (!strcasecmp(tech, chanls->tech->type)) {
-			ast_mutex_unlock(&chlock);
-			if (!chanls->tech->devicestate) 
-				return ast_parse_device_state(device);
-			else {
-				res = chanls->tech->devicestate(number);
-				if (res == AST_DEVICE_UNKNOWN)
-					return ast_parse_device_state(device);
-				else
-					return res;
-			}
-		}
-		chanls = chanls->next;
-	}
-	ast_mutex_unlock(&chlock);
-	return AST_DEVICE_INVALID;
-}
-
 int ast_call(struct ast_channel *chan, char *addr, int timeout) 
 {
 	/* Place an outgoing call, but don't wait any longer than timeout ms before returning. 
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 464ef64ea338506517c6719919cd3646c8bcf937..cdc98a321bc0086e94c22ce66958171f78c13430 100755
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -49,6 +49,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/utils.h"
 #include "asterisk/causes.h"
 #include "asterisk/astdb.h"
+#include "asterisk/devicestate.h"
 
 static const char desc[] = "Agent Proxy Channel";
 static const char channeltype[] = "Agent";
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index e1ceedaa9fb442ae0ec19e982f9253673d6080f0..7b4f556e981e8ca3251717671d7b9676126f223b 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -42,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/localtime.h"
 #include "asterisk/aes.h"
 #include "asterisk/dnsmgr.h"
+#include "asterisk/devicestate.h"
+
 #include <sys/mman.h>
 #include <arpa/inet.h>
 #include <dirent.h>
@@ -73,7 +75,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "iax2.h"
 #include "iax2-parser.h"
 #include "iax2-provision.h"
-#include "asterisk.h"
 
 /* Define NEWJB to use the new channel independent jitterbuffer,
  * otherwise, use the old jitterbuffer */
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index e26ff1902ca0d5a4159914d8986c3c5c20281bf3..5ed890f2b234fe5fc737d8ae24f5c934fd4686c9 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -62,6 +62,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/file.h"
 #include "asterisk/astobj.h"
 #include "asterisk/dnsmgr.h"
+#include "asterisk/devicestate.h"
 #ifdef OSP_SUPPORT
 #include "asterisk/astosp.h"
 #endif
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 817d3cc97671b4e1888938c45ce0bb2d98cf9e7c..9380d7884d99c6c5aa709ba88134eb1ed92583cf 100755
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -444,21 +444,6 @@ struct outgoing_helper {
 /*! Do not transmit voice data */
 #define AST_STATE_MUTE		(1 << 16)	
 
-/*! Device is valid but channel didn't know state */
-#define AST_DEVICE_UNKNOWN	0
-/*! Device is not used */
-#define AST_DEVICE_NOT_INUSE	1
-/*! Device is in use */
-#define AST_DEVICE_INUSE	2
-/*! Device is busy */
-#define AST_DEVICE_BUSY		3
-/*! Device is invalid */
-#define AST_DEVICE_INVALID	4
-/*! Device is unavailable */
-#define AST_DEVICE_UNAVAILABLE	5
-/*! Device is ringing */
-#define AST_DEVICE_RINGING	6
-
 /*! Create a channel structure */
 /*! Returns NULL on failure to allocate. New channels are 
 	by default set to the "default" context and
@@ -494,27 +479,6 @@ void  ast_channel_free(struct ast_channel *);
  */
 struct ast_channel *ast_request(const char *type, int format, void *data, int *status);
 
-/*! Search the Channels by Name */
-/*!
- * \param device like a dialstring
- * Search the Device in active channels by compare the channelname against 
- * the devicename. Compared are only the first chars to the first '-' char.
- * Returns an AST_DEVICE_UNKNOWN if no channel found or
- * AST_DEVICE_INUSE if a channel is found
- */
-int ast_parse_device_state(char *device);
-
-/*! Asks a channel for device state */
-/*!
- * \param device like a dialstring
- * Asks a channel for device state, data is  normaly a number from dialstring
- * used by the low level module
- * Trys the channel devicestate callback if not supported search in the
- * active channels list for the device.
- * Returns an AST_DEVICE_??? state -1 on failure
- */
-int ast_device_state(char *device);
-
 /*!
  * \param type type of channel to request
  * \param format requested channel format
@@ -545,6 +509,12 @@ int ast_channel_register(const struct ast_channel_tech *tech);
  */
 void ast_channel_unregister(const struct ast_channel_tech *tech);
 
+/*! Get a channel technology structure by name
+ * \param name name of technology to find
+ * \return a pointer to the structure, or NULL if no matching technology found
+ */
+const struct ast_channel_tech *ast_get_channel_tech(const char *name);
+
 /*! Hang up a channel  */
 /*! 
  * \param chan channel to hang up
@@ -759,6 +729,9 @@ struct ast_channel *ast_channel_walk_locked(const struct ast_channel *prev);
 /*! Get channel by name (locks channel) */
 struct ast_channel *ast_get_channel_by_name_locked(const char *chan);
 
+/*! Get channel by name prefix (locks channel) */
+struct ast_channel *ast_get_channel_by_name_prefix_locked(const char *name, const int namelen);
+
 /*! Waits for a digit */
 /*! 
  * \param c channel to wait for a digit on
diff --git a/include/asterisk/linkedlists.h b/include/asterisk/linkedlists.h
index 9f5f216fd2bb5f97e7598cd9b7594253a91e6cd0..b4085d7b9cb127845d77e997045032e9444bcbcd 100755
--- a/include/asterisk/linkedlists.h
+++ b/include/asterisk/linkedlists.h
@@ -306,11 +306,13 @@ struct {								\
   used to link entries of this list together.
 
   Removes the head entry from the list, and returns a pointer to it. The
-  forward-link pointer in the returned entry is \b not cleared.
+  forward-link pointer in the returned entry is \b not cleared. This macro
+  is safe to call on an empty list.
  */
 #define AST_LIST_REMOVE_HEAD(head, field) ({				\
 		typeof((head)->first) cur = (head)->first;		\
-		(head)->first = (head)->first->field.next;		\
+		if (cur)						\
+			(head)->first = cur->field.next;		\
 		cur;							\
 	})
 
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index b0f92b60a597040e19234cd538674eada21e7aa3..187372dcbf7309935ea00a4a6814d36fe2edabe2 100755
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -51,8 +51,6 @@ struct ast_sw;
 
 typedef int (*ast_state_cb_type)(char *context, char* id, int state, void *data);
 
-typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);
-
 /*! Data structure associated with a custom function */
 struct ast_custom_function {
 	char *name;
@@ -253,16 +251,6 @@ int ast_unregister_application(const char *app);
  */
 int ast_extension_state(struct ast_channel *c, char *context, char *exten);
 
-/*! Tells Asterisk the State for Device is changed */
-/*!
- * \param fmt devicename like a dialstring with format parameters
- * Asterisk polls the new extensionstates and calls the registered
- * callbacks for the changed extensions
- * Returns 0 on success, -1 on failure
- */
-int ast_device_state_changed(const char *fmt, ...)
-	__attribute__ ((format (printf, 1, 2)));
-
 /*! Registers a state change callback */
 /*!
  * \param context which context to look in
@@ -275,15 +263,6 @@ int ast_device_state_changed(const char *fmt, ...)
 int ast_extension_state_add(const char *context, const char *exten, 
 			    ast_state_cb_type callback, void *data);
 
-/*! Registers a device state change callback */
-/*!
- * \param data to pass to callback
- * The callback is called if the state for extension is changed
- * Return -1 on failure, ID on success
- */ 
-int ast_devstate_add(ast_devstate_cb_type callback, void *data);
-void ast_devstate_del(ast_devstate_cb_type callback, void *data);
-
 /*! Deletes a registered state change callback by ID */
 /*!
  * \param id of the callback to delete
@@ -629,6 +608,8 @@ char *ast_func_read(struct ast_channel *chan, const char *in, char *workspace, s
  */
 void ast_func_write(struct ast_channel *chan, const char *in, const char *value);
 
+void ast_hint_state_changed(const char *device);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff --git a/pbx.c b/pbx.c
index 767023c85fb436f6007a1beefae78612c60654d0..f4deb884dcc5ac8476544a9ed86ef0c39b8f13d3 100755
--- a/pbx.c
+++ b/pbx.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/causes.h"
 #include "asterisk/musiconhold.h"
 #include "asterisk/app.h"
+#include "asterisk/devicestate.h"
 
 /*
  * I M P O R T A N T :
@@ -160,15 +161,6 @@ struct ast_state_cb {
 	struct ast_state_cb *next;
 };
 	    
-/* ast_devstate_cb: An extension state notify */
-struct ast_devstate_cb {
-	void *data;
-	ast_devstate_cb_type callback;
-	struct ast_devstate_cb *next;
-};
-
-static struct ast_devstate_cb *devcbs;
-
 /* Hints are pointers from an extension in the dialplan to one or more devices (tech/name) */
 struct ast_hint {
 	struct ast_exten *exten;	/* Extension */
@@ -1805,130 +1797,48 @@ int ast_extension_state(struct ast_channel *c, char *context, char *exten)
 	return ast_extension_state2(e);    		/* Check all devices in the hint */
 }
 
-/*--- ast_device_state_changed: If device state in cblist is changed  - then notify callback function */
-int ast_device_state_changed(const char *fmt, ...) 
+void ast_hint_state_changed(const char *device)
 {
-	struct ast_hint *list;
+	struct ast_hint *hint;
 	struct ast_state_cb *cblist;
-	struct ast_devstate_cb *devcb;
-	char hint[AST_MAX_EXTENSION] = "";
-	char device[AST_MAX_EXTENSION];
-
-	char *cur, *rest;
+	char buf[AST_MAX_EXTENSION];
+	char *parse;
+	char *cur;
 	int state;
 
-	va_list ap;
-
-	va_start(ap, fmt);
-	vsnprintf(device, sizeof(device), fmt, ap);
-	va_end(ap);
-
-	rest = strchr(device, '-');
-	if (rest) {
-		*rest = 0;
-	}
-
-
-	state = ast_device_state(device);
-	if (option_debug > 2)
-		ast_log(LOG_DEBUG, "Changing state for %s - state %d\n", device, state);
-
 	ast_mutex_lock(&hintlock);
 
-	/* First check device callbacks */
-	devcb = devcbs;
-	while(devcb) {
-		if (devcb->callback)
-			devcb->callback(device, state, devcb->data);
-		devcb = devcb->next;
-	}
-
-	/* Then check callbacks in hints */
-	list = hints;
-
-	while (list) {
+	for (hint = hints; hint; hint = hint->next) {
+		ast_copy_string(buf, ast_get_extension_app(hint->exten), sizeof(buf));
+		parse = buf;
+		for (cur = strsep(&parse, "&"); cur; cur = strsep(&parse, "&")) {
+			if (strcmp(cur, device))
+				continue;
 
-		ast_copy_string(hint, ast_get_extension_app(list->exten), sizeof(hint));
-		cur = hint;
-		do {
-			rest = strchr(cur, '&');
-			if (rest) {
-				*rest = 0;
-				rest++;
-			}
+			/* Get device state for this hint */
+			state = ast_extension_state2(hint->exten);
 			
-			if (!strcmp(cur, device)) {	/* Is this device referred to in this hint? */
-
-				/* Get device state for this hint */
-				state = ast_extension_state2(list->exten);
-
-				if ((state != -1) && (state != list->laststate)) {
-					/* Device state changed since last check - notify the watcher */
-
-					/* For general callbacks */
-					cblist = statecbs;
-					while (cblist) {
-						cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
-						cblist = cblist->next;
-					}
+			if ((state == -1) || (state == hint->laststate))
+				continue;
 
-					/* For extension callbacks */
-					cblist = list->callbacks;
-					while (cblist) {
-						cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data);
-						cblist = cblist->next;
-					}
+			/* Device state changed since last check - notify the watchers */
 			
-					list->laststate = state;
-				}
-				break;
-			}
-			cur = rest;
-		} while (cur);
-		list = list->next;
-	}
-	ast_mutex_unlock(&hintlock);
-	return 1;
-}
+			/* For general callbacks */
+			for (cblist = statecbs; cblist; cblist = cblist->next)
+				cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
 			
-/*--- ast_devstate_add: Add device state watcher */
-int ast_devstate_add(ast_devstate_cb_type callback, void *data)
-{
-	struct ast_devstate_cb *devcb;
-	devcb = malloc(sizeof(struct ast_devstate_cb));
-	if (devcb) {
-		memset(devcb, 0, sizeof(struct ast_devstate_cb));
-		ast_mutex_lock(&hintlock);
-		devcb->data = data;
-		devcb->callback = callback;
-		devcb->next = devcbs;
-		devcbs = devcb;
-		ast_mutex_unlock(&hintlock);
+			/* For extension callbacks */
+			for (cblist = hint->callbacks; cblist; cblist = cblist->next)
+				cblist->callback(hint->exten->parent->name, hint->exten->exten, state, cblist->data);
+			
+			hint->laststate = state;
+			break;
+		}
 	}
-	return 0;
-}
 
-/*--- ast_devstate_del: Remove device state watcher */
-void ast_devstate_del(ast_devstate_cb_type callback, void *data)
-{
-	struct ast_devstate_cb *devcb, *prev = NULL, *next;
-	ast_mutex_lock(&hintlock);
-	devcb = devcbs;
-	while(devcb) {
-		next = devcb->next;
-		if ((devcb->data == data) && (devcb->callback == callback)) {
-			if (prev)
-				prev->next = next;
-			else
-				devcbs = next;
-			free(devcb);
-		} else
-			prev = devcb;
-		devcb = next;
-	}
 	ast_mutex_unlock(&hintlock);
 }
-
+			
 /*--- ast_extension_state_add: Add watcher for extension states */
 int ast_extension_state_add(const char *context, const char *exten, 
 			    ast_state_cb_type callback, void *data)