diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c
index 42fdc769194ec2d01ecb8409b650fb7bd7d7593d..aeee77a38dddf0a3e44e847e8650a3d7b967ac74 100644
--- a/channels/chan_brcm.c
+++ b/channels/chan_brcm.c
@@ -84,6 +84,7 @@ static int brcm_create_conference(struct brcm_pvt *p);
 static int brcm_stop_conference(struct brcm_subchannel *p);
 static int brcm_finish_transfer(struct ast_channel *owner, struct brcm_subchannel *p, int result);
 static int brcm_call(struct ast_channel *ast, const char *dest, int timeout);
+static int brcm_devicestate(const char *device_number);
 static int brcm_hangup(struct ast_channel *ast);
 static int brcm_getRtpStats(struct ast_channel *ast);
 static int brcm_answer(struct ast_channel *ast);
@@ -318,7 +319,7 @@ static struct ast_format_cap *default_cap;
 
 static int load_common_settings(struct ast_config **cfg);
 static void load_lines_settings(struct ast_config *cfg);
-static char *state2str(enum channel_state state);
+static char *state2str(enum brcm_channel_state state);
 
 /* exported capabilities */
 static struct ast_channel_tech brcm_tech = {
@@ -334,7 +335,8 @@ static struct ast_channel_tech brcm_tech = {
 	.getRtpStats = brcm_getRtpStats,	//Channel is NOT locked
 	.send_digit_end = brcm_senddigit_end,		//Channel is NOT locked
 	.indicate = brcm_indicate,			//Channel is locked
-	.transfer = brcm_transfer			// Channel is locked
+	.transfer = brcm_transfer,			// Channel is locked
+	.devicestate = brcm_devicestate	// Channel is NOT locked
 };
 
 static struct brcm_channel_tech fxs_tech = {
@@ -817,6 +819,68 @@ static int brcm_senddigit_end(struct ast_channel *ast, char digit, unsigned int
 	return 0;
 }
 
+/*
+ * This function is called by _ast_device_state() to get the state of the device
+ *
+ * @param[in] device_number the number of device in the format of 0/0, i.e. line_id/connection_id
+ *
+ * @return enum ast_device_state
+ */
+static int brcm_devicestate(const char *device_number)
+{
+	char *sep = NULL;
+	int chan_id, connection_id, sub_chan;
+	struct brcm_pvt *pvt;
+
+	if (!device_number || strlen(device_number) < 3 || (sep = strchr(device_number, '/')) == NULL) {
+		goto __ret;
+	}
+
+	chan_id = atoi(device_number);
+	connection_id = atoi(sep + 1);
+	if (chan_id < 0 || chan_id >= num_endpoints || connection_id < 0) {
+		goto __ret;
+	}
+
+	pvt = brcm_get_pvt_from_lineid(iflist, chan_id);
+	if (!pvt) {
+		goto __ret;
+	}
+
+	for (sub_chan = 0; sub_chan < NUM_SUBCHANNELS; sub_chan++) {
+		if (pvt->sub[sub_chan]->connection_id == connection_id)
+			break;
+	}
+	if (sub_chan >= NUM_SUBCHANNELS) {
+		goto __ret;
+	}
+
+	ast_debug(1, "the state of sub_channel %d/%d is %s(%u)\n", chan_id, sub_chan,
+			state2str(pvt->sub[sub_chan]->channel_state), pvt->sub[sub_chan]->channel_state);
+
+	switch (pvt->sub[sub_chan]->channel_state) {
+		case ONHOOK: return AST_DEVICE_NOT_INUSE;
+		case OFFHOOK: return AST_DEVICE_INUSE;
+		case DIALING: return AST_DEVICE_INUSE;
+		case CALLING: return AST_DEVICE_INUSE;
+		case INCALL: return AST_DEVICE_INUSE;
+		case ANSWER: return AST_DEVICE_INUSE;
+		case CALLENDED: return AST_DEVICE_NOT_INUSE;
+		case RINGING: return AST_DEVICE_RINGINUSE;
+		case CALLWAITING: return AST_DEVICE_INUSE;
+		case ONHOLD: return AST_DEVICE_ONHOLD;
+		case TRANSFERING: return AST_DEVICE_INUSE;
+		case RINGBACK: return AST_DEVICE_INUSE;
+		case AWAITONHOOK: return AST_DEVICE_UNAVAILABLE;
+		case ALLOCATED: return AST_DEVICE_NOT_INUSE;
+		default: return AST_DEVICE_UNKNOWN;
+	}
+
+__ret:
+	ast_debug(1, "invalid device_number %s\n", device_number);
+	return AST_DEVICE_UNKNOWN;
+}
+
 static int brcm_call(struct ast_channel *chan, const char *dest, int timeout)
 {
 	struct brcm_pvt *p;
@@ -1263,7 +1327,7 @@ static void brcm_reset_dtmf_buffer(struct brcm_pvt *p)
 	p->dtmfbuf[p->dtmf_len] = '\0';
 }
 
-static char *state2str(enum channel_state state)
+static char *state2str(enum brcm_channel_state state)
 {
 	switch (state) {
 	case ONHOOK:		return "ONHOOK";
@@ -1279,6 +1343,7 @@ static char *state2str(enum channel_state state)
 	case TRANSFERING:	return "TRANSFERING";
 	case RINGBACK:		return "RINGBACK";
 	case AWAITONHOOK:	return "AWAITONHOOK";
+	case ALLOCATED:		return "ALLOCATED";
 	default:			return "UNKNOWN";
 	}
 }
diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h
index ebe1ed80799417cf71c6ddb579d3f30bc5cc8e93..992dbe1c7642876c85863fdf040b533b2e6fd8b1 100644
--- a/channels/chan_brcm.h
+++ b/channels/chan_brcm.h
@@ -35,7 +35,7 @@
 #define CONT  1
 #define END   2
 
-enum channel_state {
+enum brcm_channel_state {
     ONHOOK,
     OFFHOOK,
     DIALING,
@@ -98,7 +98,7 @@ struct brcm_subchannel {
 	int id;
 	struct ast_channel *owner;		/* Channel we belong to, possibly NULL */
 	int connection_id;		/* Current connection id, may be -1 */
-	unsigned int channel_state;	/* Channel states */
+	enum brcm_channel_state channel_state;	/* Channel states */
 	unsigned int connection_init;	/* State for endpoint id connection initialization */
 	struct ast_frame fr;		/* Frame */
 	unsigned int sequence_number;	/* Endpoint RTP sequence number state */