From c2a14e09be1ad02e26223fd5b984b91d00822b7b Mon Sep 17 00:00:00 2001
From: Wenpeng Song <wenpeng.song@iopsys.eu>
Date: Fri, 17 Feb 2023 09:18:43 +0000
Subject: [PATCH] Move chan_brcm out of Asterisk

A separate package asterisk-chan-voicemngr has been added to replace chan_brcm.
---
 channels/Makefile          |    1 -
 channels/chan_brcm.c       | 5169 ------------------------------------
 channels/chan_brcm.h       |  286 --
 configs/brcm.conf.sample   |   50 -
 include/asterisk/cdr.h     |    2 +-
 include/asterisk/channel.h |    2 +-
 6 files changed, 2 insertions(+), 5508 deletions(-)
 delete mode 100644 channels/chan_brcm.c
 delete mode 100644 channels/chan_brcm.h
 delete mode 100644 configs/brcm.conf.sample

diff --git a/channels/Makefile b/channels/Makefile
index 5558ee546a..b641173fe8 100644
--- a/channels/Makefile
+++ b/channels/Makefile
@@ -36,7 +36,6 @@ chan_mgcp.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)
 chan_unistim.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)
 chan_phone.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)
 chan_sip.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)
-chan_brcm.so: LIBS+=-lubus -lubox -lpicoevent
 
 chan_misdn.o: _ASTCFLAGS+=-Imisdn
 misdn_config.o: _ASTCFLAGS+=-Imisdn
diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c
deleted file mode 100644
index eeaf7ee6c0..0000000000
--- a/channels/chan_brcm.c
+++ /dev/null
@@ -1,5169 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2005, Digium, Inc.
- *
- * Mark Spencer <markster@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \author Benjamin Larsson <benjamin@southpole.se>
- * \author Jonas Höglund <jonash@southpole.se>
- * \author Yalu Zhang <yalu.zhang@iopsys.eu>
- *
- * \ingroup channel_drivers
- */
-
-//	#define BRCM_LOCK_DEBUG		/* If defined we will log lock events to the asterisk debug channel */
-
-#include "asterisk.h"
-
-#include <math.h>
-#include <ctype.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-#include <semaphore.h>
-#include <sys/types.h>
-#include <sys/stat.h>															// mkfifo()
-#include "asterisk/lock.h"
-#include "asterisk/channel.h"
-#include "asterisk/options.h"
-#include "asterisk/cli.h"
-#include "asterisk/config.h"
-#include "asterisk/module.h"
-#include "asterisk/pbx.h"
-#include "asterisk/utils.h"
-#include "asterisk/callerid.h"
-#include "asterisk/causes.h"
-#include "asterisk/stringfields.h"
-#include "asterisk/musiconhold.h"
-#include "asterisk/indications.h"
-#include "asterisk/sched.h"
-#include "asterisk/app.h"
-#include "asterisk/format_cap.h"
-#include "asterisk/format_compatibility.h"
-#include "asterisk/format_cache.h"
-#include "asterisk/logger.h"
-#include "asterisk/bridge.h"
-#include "asterisk/stasis_system.h"
-#include "asterisk/stasis_channels.h"
-
-#include <libubus.h>
-#include <libpicoevent.h>
-
-#include "chan_brcm.h"
-#ifndef AST_MODULE
-#define AST_MODULE "chan_brcm"
-#endif
-
-static void brcm_dialtone_set(struct brcm_pvt *p, dialtone_state state);
-static int brcm_signal_dialtone(struct brcm_pvt *p);
-static int brcm_in_conference(const struct brcm_pvt *p);
-static int cwtimeout_cb(const void *data);
-static int cwbeep_cb(const void *data);
-static int r4hanguptimeout_cb(const void *data);
-static void brcm_generate_rtp_packet(struct brcm_subchannel *p, uint8_t *packet_buf, int type, int marker, int dtmf_timestamp, int seqno);
-static void brcm_interpret_rtcp_packet(struct brcm_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size);
-static int brcm_mute_connection(struct brcm_subchannel *p);
-static int brcm_unmute_connection(struct brcm_subchannel *p);
-static int brcm_close_connection(struct brcm_subchannel *p);
-static int brcm_create_conference(struct brcm_pvt *p);
-static int brcm_stop_conference(struct brcm_subchannel *p);
-static void brcm_attended_call_transfer(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner);
-static void brcm_unattended_call_transfer(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner);
-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);
-static struct ast_frame *brcm_read(struct ast_channel *ast);
-static int brcm_write(struct ast_channel *ast, struct ast_frame *frame);
-static int brcm_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
-static int brcm_transfer(struct ast_channel *ast, const char *newdest);
-static int brcm_senddigit_begin(struct ast_channel *ast, char digit);
-static int brcm_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
-static int brcm_in_call(const struct brcm_pvt *p);
-static int brcm_in_callwaiting(const struct brcm_pvt *p);
-static int brcm_in_onhold(const struct brcm_pvt *p);
-static int brcm_subchannel_is_idle(const struct brcm_subchannel *sub);
-static struct ast_channel *brcm_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *dest, int *cause);
-static void brcm_lock_pvts(void);
-static void brcm_unlock_pvts(void);
-static struct brcm_pvt* brcm_get_next_pvt(struct brcm_pvt *p);
-static void *pe_base_run(void *unused);
-static int brcm_create_connection(struct brcm_subchannel *p);
-static int brcm_stop_dialtone(struct brcm_pvt *p);
-static void brcm_signal_howler(struct brcm_pvt *p);
-static int brcm_signal_ringing(struct brcm_pvt *p);
-static int brcm_stop_ringing(struct brcm_pvt *p);
-static int brcm_signal_ringing_callerid_pending(struct brcm_pvt *p);
-static int brcm_stop_ringing_callerid_pending(struct brcm_pvt *p);
-static int brcm_signal_callwaiting(const struct brcm_pvt *p);
-static int brcm_stop_callwaiting(const struct brcm_pvt *p);
-static int brcm_signal_callerid(struct ast_channel *chan, struct brcm_subchannel *sub);
-static struct brcm_subchannel *brcm_get_idle_subchannel(const struct brcm_pvt *p);
-static struct brcm_subchannel* brcm_get_active_subchannel(const struct brcm_pvt *p);
-static struct brcm_subchannel *brcm_subchannel_get_peer(const struct brcm_subchannel *sub);
-static struct brcm_pvt* brcm_get_pvt_from_lineid(struct brcm_pvt *p, int line_id);
-static void handle_dtmf_calling(struct brcm_subchannel *sub);
-static void brcm_cancel_dialing_timeouts(struct brcm_pvt *p);
-static int brcm_should_relay_dtmf(const struct brcm_subchannel *sub);
-static struct ast_channel *brcm_new(struct brcm_subchannel *subchan, int state, const char *ext, const char *context,
-		const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
-		struct ast_format_cap *format);
-static int handle_dialtone_timeout(const void *data);
-static int endpt_get_rtp_stats(int line);
-static int is_call_waiting_enabled(const char *sip_account);
-static int has_call_in_sip_client(const char *sip_account);
-
-/* Global brcm channel parameters */
-static const char tdesc[] = "Broadcom SLIC Driver";
-static const char config[] = "chan_telephony.conf";
-static const char broadcast_path[] = "voice.line";
-static channel_settings channel_config[MAX_NUM_LINEID];
-static int current_connection_id = 0;
-static int num_fxs_endpoints = -1;
-static int num_fxo_endpoints = -1;
-static int num_dect_endpoints = -1;
-static int num_endpoints = -1;
-
-/* driver scheduler */
-static struct ast_sched_context *sched = NULL;
-
-/* Call waiting */
-static int cwtimeout = DEFAULT_CALL_WAITING_TIMEOUT;
-static int cwBeep = DEFAULT_CALL_WAITING_BEEP_FREQ;
-
-/* R4 transfer */
-static int r4hanguptimeout = DEFAULT_R4_HANGUP_TIMEOUT;
-
-/* Automatic call on hold hangup */
-static int onholdhanguptimeout = DEFAULT_ONHOLD_HANGUP_TIMEOUT;
-
-/* Max call count per extension */
-#define DEFAULT_MAX_SESSION_PER_EXTENSION 2
-static int max_sessions_per_extension = DEFAULT_MAX_SESSION_PER_EXTENSION;
-
-/* Boolean, controls whether the transferor puts the transfer target on-hold before sending
- * REFER to the transferee */
-static int hold_target_before_refer = 1;
-
-/* Global jitter buffer configuration */
-static struct ast_jb_conf global_jbconf;
-
-//TODO change AST_MAX_EXTENSION to something shorter
-/* Structure for feature access codes */
-struct feature_access_code {
-	AST_LIST_ENTRY(feature_access_code) list;
-	char code[AST_MAX_EXTENSION];
-};
-
-/* List of configured feature access codes */
-static AST_LIST_HEAD_NOLOCK_STATIC(feature_access_codes, feature_access_code);
-
-/* Format a string of feature access codes */
-static const char *feature_access_code_string(char *buffer, unsigned int buffer_length);
-
-/* Add FAC to list */
-static int feature_access_code_add(const char *code);
-
-/* Clear list of FAC */
-static int feature_access_code_clear(void);
-
-/* Match dialed digits against feature access codes */
-static int feature_access_code_match(char *sequence);
-
-/*  Send dialed DTMF codes during call */
-static void send_outgoing_dtmf(struct ast_channel *owner, char dtmf_button, int frametype);
-
-static pthread_t ubus_thread = AST_PTHREADT_NULL;
-
-static struct ubus_context *ctx;
-static struct ubus_event_handler ObjAddListener; // Event handler for new ubus object events
-static struct ubus_event_handler ObjRmListener;  // Event handler for removed ubus object events
-
-static int base;
-static volatile uint32_t endpt_id = 0;
-static const char endpt_ubus_path[] = "endpt";
-static const char audio_rx_str[] = "/tmp/endpt_audio_tx";
-static const char audio_tx_str[] = "/tmp/endpt_audio_rx";
-static const char ubusStrObjAdd[] = "ubus.object.add";   // UBUS objects added to global context
-static const char ubusStrObjRm[] = "ubus.object.remove"; // UBUS objects added removed from global context
-static int audio_rx_fd = 0, audio_tx_fd = 0;
-static pe_bus_t *audio_rx_bus, *audio_tx_bus;
-static pe_stream_t *audio_rx_stream;
-static int mwi_dialtone_state = DIALTONE_ON;
-static char lineCallStatus[16];
-int dtmf_wait_timer = 2000; /*Time to wait for dtmf(for R4 call setup) before setting up a conference call*/
-#define RTP_HEADER_SIZE 12
-#define RTP_DTMF_SIZE 4
-
-enum {
-	EVENT_TYPE,
-	EVENT_LINE_ID,
-	__EVENT_MAX,
-};
-
-enum {
-	CALL_STATUS_EXTENSION_ID,
-	CALL_STATUS_LINE_ID,
-	__CALL_STATUS_MAX,
-};
-
-enum {																			// New ubus objects in global context
-	OBJ_ID,																		// UBUS ID of object
-	OBJ_PATH,																	// String path of object
-};
-
-enum {
-	STATE_OFF = 0,
-	STATE_ON,
-	STATE_LAST,
-};
-
-struct endpt_event {
-	const char *name;
-	enum LINE_EVENT event;
-	int line;
-};
-
-typedef struct __attribute__((__packed__)) {
-	int32_t line;
-	int32_t cnx_id;
-	uint32_t rtp_size;
-	uint8_t rtp[1];
-} audio_packet_t;
-
-static struct endpt_event event_map[] = {
-	{ .name = "DTMF0", .event = EVENT_DTMF0 },
-	{ .name = "DTMF1", .event = EVENT_DTMF1 },
-	{ .name = "DTMF2", .event = EVENT_DTMF2 },
-	{ .name = "DTMF3", .event = EVENT_DTMF3 },
-	{ .name = "DTMF4", .event = EVENT_DTMF4 },
-	{ .name = "DTMF5", .event = EVENT_DTMF5 },
-	{ .name = "DTMF6", .event = EVENT_DTMF6 },
-	{ .name = "DTMF7", .event = EVENT_DTMF7 },
-	{ .name = "DTMF8", .event = EVENT_DTMF8 },
-	{ .name = "DTMF9", .event = EVENT_DTMF9 },
-	{ .name = "DTMFA", .event = EVENT_DTMFA },
-	{ .name = "DTMFB", .event = EVENT_DTMFB },
-	{ .name = "DTMFC", .event = EVENT_DTMFC },
-	{ .name = "DTMFD", .event = EVENT_DTMFD },
-	{ .name = "DTMFS", .event = EVENT_DTMFS },
-	{ .name = "DTMFH", .event = EVENT_DTMFH },
-	{ .name = "OFFHOOK", .event = EVENT_OFFHOOK },
-	{ .name = "ONHOOK", .event = EVENT_ONHOOK },
-	{ .name = "FLASH", .event = EVENT_FLASH },
-	{ .name = "CALL_REJECT", .event = EVENT_CALL_REJECT },
-	{ .name = "DECT_UNAVAILABLE", .event = EVENT_DECT_UNAVAILABLE },
-	{ .name = "SWITCH", .event = EVENT_SWITCH },
-	{ .name = "JOIN", .event = EVENT_JOIN },
-	{ .name = "RELEASE", .event = EVENT_RELEASE },
-	{ .name = "", .event = EVENT_LAST },
-};
-
-static const struct blobmsg_policy asterisk_event_policy[] = {
-	[EVENT_TYPE] = { .name = "event", .type = BLOBMSG_TYPE_STRING },
-	[EVENT_LINE_ID] = { .name = "line", .type = BLOBMSG_TYPE_INT32 },
-};
-
-static const struct blobmsg_policy asterisk_call_status_policy[] = {
-	[CALL_STATUS_EXTENSION_ID] = { .name = "extension", .type = BLOBMSG_TYPE_INT32 },
-	[CALL_STATUS_LINE_ID] = { .name = "line", .type = BLOBMSG_TYPE_INT32 },
-};
-
-static const struct blobmsg_policy new_obj_policy[] = {
-	[OBJ_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },					// UBUS ID of object
-	[OBJ_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },				// String path of object
-};
-
-static struct ast_channel_tech *cur_tech;
-
-static struct stasis_subscription **registration_change_sub = NULL; /*!< subscription id for SIP registration change events for every line*/
-
-static const DTMF_CHARNAME_MAP dtmf_to_charname[] =
-{
-	{EVENT_DTMF0, "DTMF0", '0', 0},
-	{EVENT_DTMF1, "DTMF1", '1', 1},
-	{EVENT_DTMF2, "DTMF2", '2', 2},
-	{EVENT_DTMF3, "DTMF3", '3', 3},
-	{EVENT_DTMF4, "DTMF4", '4', 4},
-	{EVENT_DTMF5, "DTMF5", '5', 5},
-	{EVENT_DTMF6, "DTMF6", '6', 6},
-	{EVENT_DTMF7, "DTMF7", '7', 7},
-	{EVENT_DTMF8, "DTMF8", '8', 8},
-	{EVENT_DTMF9, "DTMF9", '9', 9},
-	{EVENT_DTMFA, "DTMFA", 'A', 12},
-	{EVENT_DTMFB, "DTMFB", 'B', 13},
-	{EVENT_DTMFC, "DTMFC", 'C', 14},
-	{EVENT_DTMFD, "DTMFD", 'D', 15},
-	{EVENT_DTMFH, "DTMFH", 0x23, 11}, //#
-	{EVENT_DTMFS, "DTMFS", 0x2A, 10}, //*
-	{EVENT_LAST,  "", '-', -1}
-};
-
-/* Linked list of pvt:s */
-static struct brcm_pvt *iflist;
-
-/* Protect the interface list (of brcm_pvt's) */
-AST_MUTEX_DEFINE_STATIC(iflock);
-
-/* Protect the monitoring thread, so only one process can kill or start it, and not
-   when it's doing something critical. */
-AST_MUTEX_DEFINE_STATIC(monlock);
-
-static struct ast_format_cap *default_cap;
-
-static int load_common_settings(struct ast_config **cfg);
-static void load_settings(struct ast_config *cfg);
-static char *state2str(enum brcm_channel_state state);
-
-/* exported capabilities */
-static struct ast_channel_tech brcm_tech = {
-	.type = "TELCHAN",
-	.description = tdesc,
-	.requester = brcm_request,			//No lock held (no channel yet)
-	.call = brcm_call,				//Channel is locked
-	.hangup = brcm_hangup,				//Channel is locked
-	.answer = brcm_answer,				//Channel is locked
-	.read = brcm_read,				//Channel is locked
-	.write = brcm_write,				//Channel is locked
-	.send_digit_begin = brcm_senddigit_begin,	//Channel is NOT locked
-	.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
-	.devicestate = brcm_devicestate			// Channel is NOT locked
-};
-
-static struct brcm_channel_tech fxs_tech = {
-	.signal_ringing = brcm_signal_ringing,
-	.signal_ringing_callerid_pending = brcm_signal_ringing_callerid_pending,
-	.signal_callerid = brcm_signal_callerid,
-	.stop_ringing = brcm_stop_ringing,
-	.stop_ringing_callerid_pending = brcm_stop_ringing_callerid_pending,
-	.release = NULL,
-};
-
-/* Tries to lock 10 timees, then gives up */
-/* static int pvt_trylock(struct brcm_pvt *pvt, const char *reason) */
-/* { */
-/* 	int i = 10; */
-/* 	while (i--) { */
-/* 		if (!ast_mutex_trylock(&pvt->lock)) { */
-/* 			ast_debug(9, "----> Successfully locked pvt port %d - reason %s\n", pvt->line_id, reason); */
-/* 			return 1; */
-/* 		} */
-/* 	} */
-/* 	ast_debug(9, "----> Failed to lock port %d - %s\n", pvt->line_id, reason); */
-/* 	return 0; */
-/* } */
-
-#ifdef BRCM_LOCK_DEBUG
-static int pvt_lock(struct brcm_pvt *pvt, const char *reason)
-{
-	ast_debug(9, "----> Trying to lock port %d - %s\n", pvt->line_id, reason);
-	ast_mutex_lock(&pvt->lock);
-	ast_debug(9, "----> Locked pvt port %d - reason %s\n", pvt->line_id, reason);
-	return 1;
-}
-
-
-static int pvt_lock_silent(struct brcm_pvt *pvt)
-{
-	ast_mutex_lock(&pvt->lock);
-	return 1;
-}
-
-
-static int pvt_unlock(struct brcm_pvt *pvt)
-{
-	ast_mutex_unlock(&pvt->lock);
-	ast_debug(10, "----> Unlocking pvt port %d\n", pvt->line_id);
-	return 1;
-}
-
-static int pvt_unlock_silent(struct brcm_pvt *pvt)
-{
-	ast_mutex_unlock(&pvt->lock);
-	return 1;
-}
-
-#else
-#define pvt_lock(pvt, reason)		ast_mutex_lock(&(pvt)->lock)
-#define pvt_lock_silent(pvt)		ast_mutex_lock(&(pvt)->lock)
-#define pvt_unlock(pvt)				ast_mutex_unlock(&(pvt)->lock)
-#define pvt_unlock_silent(pvt)		ast_mutex_unlock(&(pvt)->lock)
-#endif
-
-// Get call_id state based on the call_id value
-static callid_state get_callid_state(int call_id) {
-	if (call_id <= CALLID_INVALID)
-		return CALLID_INVALID;
-	else if (call_id == CALLID_OBTAINING)
-		return CALLID_OBTAINING;
-	else
-		return CALLID_ESTABLISHED;
-}
-
-// Get the endptmngr ubus address. It's dynamically updated
-// by another thread without locking.
-static uint32_t get_ubus_endpt_id(int log) {
-	if (!endpt_id) {
-		if (ubus_lookup_id(ctx, endpt_ubus_path, &endpt_id) != UBUS_STATUS_OK) {
-			if (log)
-				ast_log(LOG_ERROR, "Failed to look up endptmngr's UBUS path\n");
-			return 0;
-		}
-	}
-
-	return endpt_id;
-}
-
-// Callback for: a ubus call (invocation) has replied with some data
-static void ubus_call_answer(struct ubus_request *req, int type, struct blob_attr *msg)
-{
-	ast_verbose("%s() from thread %d\n", __func__, ast_get_tid());
-}
-
-// Callback for: a ubus call (invocation) has finished
-static void ubus_call_complete(struct ubus_request *req, int ret)
-{
-	ast_verbose("%s() from thread %d\n", __func__, ast_get_tid());
-	free(req);
-}
-
-static void endpt_signal(int line, char *signal, char *state, char *data) {
-	struct blob_buf bb;
-	struct ubus_request *req;
-	int res;
-
-	//ast_debug(5, "line = %d, signal = %s, state = %s, data = %s\n",  line, signal, state, data);
-
-	if (endpt_id) {
-		memset(&bb, 0, sizeof(bb));
-		blob_buf_init(&bb, 0);
-
-		blobmsg_add_u32(&bb, "line", line);
-		blobmsg_add_string(&bb, "signal", signal);
-		blobmsg_add_string(&bb, "state", state);
-		if (data)
-			blobmsg_add_string(&bb, "data", data);
-
-		req = calloc(1, sizeof(struct ubus_request));
-		if (!req) return;
-
-		ast_verbose("thread %d: ubus call endpt signal\n", ast_get_tid());
-		res = ubus_invoke_async(ctx, endpt_id, "signal", bb.head, req);
-
-		if(res != UBUS_STATUS_OK) {
-			ast_log(LOG_ERROR, "Error invoking method: %s %d\n", "signal", res);
-			free(req);
-			return;
-		}
-
-		req->data_cb = ubus_call_answer;
-		req->complete_cb = ubus_call_complete;
-		req->priv = NULL;
-		ubus_complete_request_async(ctx, req);
-	}
-}
-
-static int brcm_send_ubus_event(char *ev_name, int line)
-{
-	struct blob_buf blob;
-	struct ubus_context *ubusctx;
-	int res = 0;
-
-	ubusctx = ubus_connect(NULL);
-	if (!ubusctx) {
-		return -1;
-	}
-
-	memset(&blob, 0, sizeof(blob));
-	if(blob_buf_init(&blob, 0)) {
-		ubus_free(ubusctx);
-		return -1;
-	}
-
-	blobmsg_add_u32(&blob, "id", line);
-	blobmsg_add_string(&blob, "event", ev_name);
-
-	if (ubus_send_event(ubusctx, broadcast_path, blob.head) != UBUS_STATUS_OK) {
-		ast_log(LOG_NOTICE,"Error sending ubus message %s\n", ev_name);
-		res = -1;
-	}
-
-	ubus_free(ubusctx);
-	blob_buf_free(&blob);
-
-	return res;
-}
-
-static void endpt_connection(int line, int id, char *action) {
-	struct blob_buf bb;
-	struct ubus_request *req;
-	int res;
-
-	if (endpt_id) {
-		memset(&bb, 0, sizeof(bb));
-		blob_buf_init(&bb, 0);
-
-		blobmsg_add_u32(&bb, "line", line);
-		blobmsg_add_u32(&bb, "id", id);
-		blobmsg_add_string(&bb, "action", action);
-
-		req = calloc(1, sizeof(struct ubus_request));
-		if (!req) return;
-		ast_verbose("thread %d: ubus call endpt connection\n", ast_get_tid());
-		res = ubus_invoke_async(ctx, endpt_id, "connection", bb.head, req);
-
-		if(res != UBUS_STATUS_OK) {
-			ast_log(LOG_ERROR, "Error invoking method: %s %d\n", "connection", res);
-			free(req);
-			return;
-		}
-
-		req->data_cb = ubus_call_answer;
-		req->complete_cb = ubus_call_complete;
-		req->priv = NULL;
-		ubus_complete_request_async(ctx, req);
-	}
-}
-
-static int brcm_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
-{
-	struct brcm_subchannel *sub = ast_channel_tech_pvt(ast);
-	struct ast_bridge_channel *play_bridge_channel;
-	struct ast_bridge *myBridge;
-	struct ast_frame astFrame;
-	int res = 0;
-
-	ast_debug(2, "Channel %s gets an indication, condition = %d\n", ast_channel_name(ast), condition);
-
-	pvt_lock(sub->parent, "indicate");
-	//ast_mutex_lock(&sub->parent->lock);
-	switch(condition) {
-	case AST_CONTROL_UNHOLD:
-		brcm_stop_dialtone(sub->parent);
-
-		// Play a beep when unholding.
-		ast_channel_lock(ast);
-		play_bridge_channel = ast_channel_get_bridge_channel(ast);
-		ast_channel_unlock(ast);
-		ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, "beep", NULL);
-
-		sub->channel_state = INCALL;
-
-		// Tell all participants to re-sync RTP stream.
-		myBridge = ast_channel_internal_bridge(ast);
-		memset(&astFrame, 0, sizeof astFrame);
-		astFrame.frametype = AST_FRAME_CONTROL;
-		astFrame.subclass.integer = AST_CONTROL_SRCUPDATE;
-		ast_bridge_queue_everyone_else(myBridge, NULL, &astFrame);
-		break;
-
-	case AST_CONTROL_UPDATE_RTP_PEER:
-	case AST_CONTROL_SRCUPDATE:
-	case AST_CONTROL_SRCCHANGE:
-		sub->codec = -1;
-		if (sub->channel_state == RINGBACK)
-			endpt_signal(sub->parent->line_id, "ringback", "off", NULL);
-		break;
-	case AST_CONTROL_RINGING:
-		ast_debug(4, "Got AST_CONTROL_RINGING on %s, sub->codec = %d\n", ast_channel_name(ast), sub->codec);
-		sub->channel_state = RINGBACK;
-		// Play local ringback tone only if there is no incoming media packet
-		if (sub->codec == -1)
-			endpt_signal(sub->parent->line_id, "ringback", "on", NULL);
-		if (sub->owner && (get_callid_state(sub->call_id) != CALLID_ESTABLISHED)) {
-			sub->call_id = ast_channel_callid(sub->owner);
-			endpt_connection(sub->parent->line_id, sub->call_id, "update");
-		}
-		break;
-	case AST_CONTROL_UNHOLD_FOR_TRANSFER:
-		if (sub->channel_state == TRANSFERING) {
-			struct ast_channel *bridged_chan = ast_channel_bridge_peer(sub->owner);
-			if (bridged_chan) {
-				ast_debug(4, "Start unattended transfer to [%s] on channel %s\n", sub->blind_xfer_target, ast_channel_name(bridged_chan));
-				ast_channel_lock(bridged_chan);
-				if (!ast_test_flag(ast_channel_flags(bridged_chan), AST_FLAG_ZOMBIE) &&
-						!ast_check_hangup(bridged_chan)) {
-					if (ast_channel_tech(bridged_chan)->transfer) {
-						res = ast_channel_tech(bridged_chan)->transfer(bridged_chan, (const char *)sub->blind_xfer_target);
-						if (res != 0)
-							ast_log(LOG_ERROR, "ast_transfer() failed\n");
-					} else
-						ast_log(LOG_ERROR, "ast_transfer() is not supported on the peer channel\n");
-				}
-				ast_channel_unlock(bridged_chan);
-			} else {
-				ast_log(LOG_ERROR, "can't get the peer channel, unattended call transfer will not be proceeded\n");
-			}
-
-		}
-		break;
-	case AST_CONTROL_TRANSFER:
-		res = -1;
-		if (datalen != sizeof(enum ast_control_transfer)) {
-			ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_TRANSFER. Expected %d, got %d\n", (int) sizeof(enum ast_control_transfer), (int) datalen);
-		} else {
-			enum ast_control_transfer *message = (enum ast_control_transfer *) data;
-                        struct brcm_subchannel* peer_sub;
-                        peer_sub = brcm_subchannel_get_peer(sub);
-			if (peer_sub->channel_state == TRANSFERING)
-				brcm_finish_transfer(ast, peer_sub, *message);
-			else
-				brcm_finish_transfer(ast, sub, *message);
-		}
-		break;
-	case AST_CONTROL_CONGESTION:
-		ast_debug(4, "Got CONGESTION on %s\n", ast_channel_name(ast));
-		/* The other end is out of network resources */
-		if (ast_channel_state(ast) != AST_STATE_UP) {
-			/* If state is UP, we can't do anything */
-			ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
-			brcm_hangup(ast);
-			break;
-		}
-		res = -1;
-		break;
-	case AST_CONTROL_CONNECTED_LINE:
-		res = -1;
-		ast_debug(4, "Got CONNECTED LINE UPDATE on %s\n", ast_channel_name(ast));
-		/* Update caller IDs on display - dect ? */
-		struct brcm_subchannel *sub_peer = brcm_subchannel_get_peer(sub);
-		if ((sub->connection_id != -1) && (sub_peer->connection_id != -1)) {
-			struct ast_bridge *bridge = ast_channel_internal_bridge(sub->owner);
-			struct ast_bridge_channel *bridge_channel;
-			if(bridge){
-				// Find out which end party of call conference hangs up
-				AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
-					if (strstr(ast_channel_name(bridge_channel->chan), "PJSIP") != NULL) {
-						if (sub->call_id == ast_channel_callid(bridge_channel->chan)) {
-							endpt_connection(sub_peer->parent->line_id, sub_peer->call_id, "release");
-							sub_peer->channel_state = ONHOOK;
-							sub_peer->call_id = CALLID_INVALID;
-						}
-						else if(sub_peer->call_id == ast_channel_callid(bridge_channel->chan)) {
-							endpt_connection(sub->parent->line_id, sub->call_id, "release");
-							sub->channel_state = ONHOOK;
-							sub->call_id = CALLID_INVALID;
-						}
-					}
-				}
-				sub->conference_initiator = 0;
-				free(sub->conference_id);
-				sub->conference_id = NULL;
-
-				res = 0;
-			}
-		}
-		if (sub->owner && (get_callid_state(sub->call_id) != CALLID_ESTABLISHED)) {
-			sub->call_id = ast_channel_callid(sub->owner);
-			endpt_connection(sub->parent->line_id, sub->call_id, "update");
-			res = 0;
-		}
-		break;
-
-	case AST_CONTROL_BUSY:
-		ast_debug(4, "Got BUSY on %s\n", ast_channel_name(ast));
-		/* The other end is busy */
-		if (ast_channel_state(ast) != AST_STATE_UP) {
-			/* XXX We should play a busy tone here!! */
-			ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
-			brcm_hangup(ast);
-			break;
-		}
-		res = -1;
-		break;
-	case AST_CONTROL_PROGRESS:
-		ast_debug(4, "Got AST_CONTROL_PROGRESS on %s\n", ast_channel_name(ast));
-		/* Early media is coming our way */
-		/* What do we do with that? */
-		res = -1;
-		break;
-	case AST_CONTROL_NORMAL_DIALTONE:
-		brcm_dialtone_set(sub->parent, DIALTONE_ON);
-		break;
-	case AST_CONTROL_SPECIAL_DIALTONE:
-		brcm_dialtone_set(sub->parent, DIALTONE_SPECIAL_CONDITION);
-		break;
-	case AST_CONTROL_PVT_CAUSE_CODE: {
-		  const struct ast_control_pvt_cause_code *cause_code = data;
-		  int ast_cause = cause_code->ast_cause;
-		  ast_debug(2, "AST_CONTROL_PVT_CAUSE_CODE = %d, chan_name = %s\n", ast_cause, cause_code->chan_name);
-
-		  switch (ast_cause) {
-		  case AST_CAUSE_NO_USER_RESPONSE:
-		  case AST_CAUSE_NO_ANSWER:
-		  case AST_CAUSE_CALL_REJECTED:
-			  endpt_signal(sub->parent->line_id, "ringback", "off", NULL);
-			  if (ast_channel_state(ast) != AST_STATE_UP) {
-				  endpt_signal(sub->parent->line_id, "congestion", "on", NULL);
-                                  strncpy(sub->parent->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN);
-				  break;
-			  }
-			  res = -1;
-			  break;
-		  case AST_CAUSE_NORMAL_CLEARING:
-				  // This is just fine.
-			  	  break;
-		  case AST_CAUSE_USER_BUSY:
-				endpt_signal(sub->parent->line_id, "ringback", "off", NULL);
-				if (ast_channel_state(ast) != AST_STATE_UP) {
-					/* XXX We should play a busy tone here!! */
-                                        sub->channel_state = CALLENDED;
-					endpt_signal(sub->parent->line_id, "busy", "on", NULL);
-					strncpy(sub->parent->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN);
-					break;
-				}
-				res = -1;
-		  case AST_CAUSE_NETWORK_OUT_OF_ORDER:
-			  brcm_stop_dialtone(sub->parent); // stop any dialtone exist if disconnection happened due to network/server
-			  break;
-		  default:
-			  ast_debug(1, "Don't know how to handle cause code %d\n", ast_cause);
-			  break;
-		  }
-		}
-		break;
-	default:
-		res = -1;
-		ast_debug(1, "Don't know how to indicate condition %d\n", condition);
-		break;
-	}
-	pvt_unlock(sub->parent);
-	return res;
-}
-
-static int brcm_getRtpStats(struct ast_channel *ast)
-{
-	struct brcm_subchannel *sub;
-
-	sub = ast_channel_tech_pvt(ast);
-	if (!sub) {
-		ast_log(LOG_ERROR, "Failed to get peer subchannel\n");
-		return -1;
-	}
-
-	pvt_lock(sub->parent, "brcm_getRtpStats");
-	if (sub->parent) {
-		if (endpt_get_rtp_stats(sub->parent->line_id)) {
-			ast_log(LOG_WARNING, "Unable to get RTP statistics\n");
-		}
-		ast_channel_rtpStats_set(ast, &sub->rtp_stats);
-	}
-	pvt_unlock(sub->parent);
-
-	return 0;
-}
-
-static int brcm_transfer(struct ast_channel *ast, const char *newdest)
-{
-	struct brcm_pvt *pvt;
-	struct brcm_subchannel *subchan_active, *subchan_inactive;
-	struct ast_channel *chan_new;
-	char ext[strlen(newdest) + 1], *replaces;
-
-	ast_debug(1, "Transfer the existing call to [%s]\n", newdest);
-
-	// Get the other subchannel
-	subchan_active = ast_channel_tech_pvt(ast);
-	if (!subchan_active || !(pvt = subchan_active->parent) ||
-		!(subchan_inactive = brcm_subchannel_get_peer(subchan_active)) ||
-		!brcm_subchannel_is_idle(subchan_inactive)) {
-		return -1;
-	}
-
-	strncpy(ext, newdest, sizeof(ext));
-	replaces = strcasestr(ext, "?Replaces=");
-	if (replaces) {
-		*replaces = '\0';
-		replaces += strlen("?Replaces=");
-	}
-
-	if (!subchan_inactive->connection_init) {
-		subchan_inactive->connection_id = ast_atomic_fetchadd_int((int *)&current_connection_id, +1);
-		brcm_create_connection(subchan_inactive);
-	}
-
-	chan_new = brcm_new(subchan_inactive, AST_STATE_DOWN, ext, pvt->context, NULL, NULL, NULL);
-	if (!chan_new) {
-		ast_log(LOG_ERROR, "couldn't create channel\n");
-		return -1;
-	}
-
-	if (replaces)
-		pbx_builtin_setvar_helper(chan_new, "SIPTRANSFER_REPLACES", replaces);
-
-	ast_setstate(chan_new, AST_STATE_RING);
-	subchan_inactive->channel_state = TRANSFERING;
-
-	if (ast_pbx_start(chan_new)) {
-		ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(chan_new));
-		ast_hangup(chan_new);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int brcm_finish_transfer(struct ast_channel *owner, struct brcm_subchannel *p, int result)
-{
-	struct brcm_subchannel* peer_sub;
-	/*
-	 * We have received the result of a transfer operation.
-	 * This could be:
-	 * - Result of a Transfer-On-Hangup (Remote Transfer), in which case
-	 *   we should hangup the subchannel, no matter the result
-	 * - Result of a R4 Attended Transfer (Remote Transfer), in which case
-	 *   we should wait for hangup on both subchannels, or resume calls if failed
-	 *   Hangup should be received immediately, but we start a timer to hangup
-	 *   everything ourselves just to be sure.
-	 * - Probably nothing else - the built-in transfer should never let this
-	 *   control frame propagate to here
-	 */
-	if (p->channel_state != TRANSFERING) {
-		ast_log(LOG_WARNING, "Received AST_CONTROL_TRANSFER while in state %s\n", state2str(p->channel_state));
-		return -1;
-	}
-
-	peer_sub = brcm_subchannel_get_peer(p);
-	if (!peer_sub) {
-		ast_log(LOG_ERROR, "Failed to get peer subchannel\n");
-		return -1;
-	}
-
-	if (brcm_subchannel_is_idle(peer_sub)) {
-		// In the case of Transfer-On-Hangup peer sub should be a idle
-		if (result == AST_TRANSFER_SUCCESS) {
-			ast_log(LOG_NOTICE, "Remote transfer completed successfully, hanging up\n");
-		}
-		else {
-			ast_log(LOG_NOTICE, "Remote transfer failed, hanging up\n");
-		}
-		ast_queue_control(owner, AST_CONTROL_HANGUP);
-		p->channel_state = CALLENDED;
-	} else if (peer_sub->channel_state == ONHOLD) {
-		// In the case of R4 transfer peer sub should be on hold
-		if (result == AST_TRANSFER_SUCCESS) {
-			ast_log(LOG_NOTICE, "Remote transfer completed successfully, wait for remote hangup\n");
-			p->r4_hangup_timer_id = ast_sched_add(sched, r4hanguptimeout, r4hanguptimeout_cb, p);
-		} else {
-			//Do nothing. Let calls be up as they were before R4 was attempted (first call on hold, second call active)
-			ast_log(LOG_NOTICE, "Remote transfer failed\n");
-			p->channel_state = INCALL;
-		}
-	} else {
-		ast_log(LOG_WARNING, "AST_CONTROL_TRANSFER received in unexpected state\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-/*! \brief Incoming DTMF begin event */
-static int brcm_senddigit_begin(struct ast_channel *ast, char digit)
-{
-	struct brcm_subchannel *sub;
-	char signal[10];
-
-	//ast_debug(5, "DTMF send begin: %c\n", digit);
-
-	sub = ast_channel_tech_pvt(ast);
-	pvt_lock(sub->parent, "DTMF senddigit_begin");
-
-	snprintf(signal, sizeof(signal), "dtmf%c", digit);
-	endpt_signal(sub->parent->line_id, signal, "on", NULL);
-
-	pvt_unlock(sub->parent);
-	return 0;
-}
-
-/*! \brief Incoming DTMF end */
-static int brcm_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
-{
-	struct brcm_subchannel *sub;
-	char signal[10];
-
-	//ast_debug(5, "DTMF send end: %c, %d ms\n", digit, duration);
-
-	sub = ast_channel_tech_pvt(ast);
-	pvt_lock(sub->parent, "DTMF senddigit_end");
-
-	snprintf(signal, sizeof(signal), "dtmf%c", digit);
-	endpt_signal(sub->parent->line_id, signal, "off", NULL);
-
-	pvt_unlock(sub->parent);
-	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;
-	struct brcm_subchannel *sub;
-	struct brcm_subchannel *sub_peer;
-
-	struct timeval UtcTime = ast_tvnow();
-	struct ast_tm tm;
-	sub = ast_channel_tech_pvt(chan);
-
-	ast_debug(1, "line %d\n", sub->parent->line_id);
-	ast_localtime(&UtcTime, &tm, NULL);
-
-	if ((ast_channel_state(chan) != AST_STATE_DOWN) && (ast_channel_state(chan) != AST_STATE_RESERVED)) {
-		ast_log(LOG_WARNING, "brcm_call called on %s, neither down nor reserved\n", ast_channel_name(chan));
-		return -1;
-	}
-
-	//ast_mutex_lock(&sub->parent->lock);
-	pvt_lock(sub->parent, "brcm_call");
-
-	p = sub->parent;
-	sub_peer = brcm_subchannel_get_peer(sub);
-	if (!channel_config[p->line_id].enabled) {
-		ast_debug(1, "tel_line %d disabled!\n", p->line_id);
-		ast_channel_hangupcause_set(chan, AST_CAUSE_CALL_REJECTED);
-		ast_queue_control(chan, AST_CONTROL_BUSY);
-		brcm_send_ubus_event("CALL_REJECTED",p->line_id);
-	}
-	else if (channel_config[p->line_id].do_not_disturb) {
-		ast_debug(1, "Do not disturbed\n");
-		ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY);
-		brcm_send_ubus_event("USER_BUSY",p->line_id);
-		ast_queue_control(chan, AST_CONTROL_BUSY);
-	}
-	else if (brcm_in_call(p) &&                          		// a call is established
-		is_call_waiting_enabled(p->context)) {			// call waiting enabled
-		ast_debug(1, "Call waiting\n");
-		sub->channel_state = CALLWAITING;
-		brcm_signal_callwaiting(p);
-		int cwtimeout_ms = cwtimeout * 1000;
-		int cwBeep_ms = cwBeep * 1000;
-		sub->cw_timer_id = ast_sched_add(sched, cwtimeout_ms, cwtimeout_cb, sub);
-		sub->cwBeep_timer_id = ast_sched_add(sched, cwBeep_ms, cwbeep_cb, sub);
-		ast_setstate(chan, AST_STATE_RINGING_CW);
-		ast_queue_control(chan, AST_CONTROL_RINGING_CW);
-	}
-	else if (!brcm_subchannel_is_idle(sub_peer)) {
-		ast_debug(1, "Line is busy\n");
-		ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY);
-		ast_queue_control(chan, AST_CONTROL_BUSY);
-		/*When call comes but the sub_peer is not idle,move to old ONHOOK state*/
-		if(sub->channel_state == ALLOCATED)
-			sub->channel_state = ONHOOK;
-		brcm_send_ubus_event("USER_BUSY",p->line_id);
-
-		struct brcm_pvt *tmp = p;
-		struct brcm_subchannel *s = NULL;
-		int con_id = -1;
-
-		while(tmp) {
-			s = brcm_get_active_subchannel(tmp);
-			con_id = s->connection_id;
-			// for local call we need to find the other party and change its subchannel state to CALLENDED
-			// so the extensionCallStatus is properly set to Disconnected in brcm_answer()
-			if (con_id > 0 && (strncmp(tmp->extensionCallStatus, "Dialing", strlen(tmp->extensionCallStatus)) == 0)) {
-				s->channel_state = CALLENDED;
-				break;
-			}
-			tmp = brcm_get_next_pvt(tmp);
-		}
-	}
-	else {
-		ast_debug(1, "Not call waiting\n");
-                /*We can move status to Alerting ,since we are ringing now */
-                strncpy(p->extensionCallStatus, "Alerting", CALL_STATUS_MAX_LEN);
-		sub->channel_state = RINGING;
-		if (!channel_config[p->line_id].calleridenable) {
-			p->tech->signal_ringing(p);
-		} else {
-			p->tech->signal_ringing_callerid_pending(p);
-			p->tech->signal_callerid(chan, sub);
-		}
-
-		if (has_call_in_sip_client(p->context)) {
-			sub->cw_timer_id = ast_sched_add(sched, cwtimeout*1000, cwtimeout_cb, sub);
-			if (is_call_waiting_enabled(p->context)) {
-				ast_setstate(chan, AST_STATE_RINGING_CW);
-				ast_queue_control(chan, AST_CONTROL_RINGING_CW);
-			} else {
-				ast_setstate(chan, AST_STATE_RINGING);
-				ast_queue_control(chan, AST_CONTROL_RINGING);
-			}
-		} else {
-			ast_setstate(chan, AST_STATE_RINGING);
-			ast_queue_control(chan, AST_CONTROL_RINGING);
-		}
-
-		brcm_send_ubus_event("RINGING",p->line_id);
-	}
-	//ast_mutex_unlock(&sub->parent->lock);
-	pvt_unlock(sub->parent);
-
-	return 0;
-}
-
-static int brcm_hangup(struct ast_channel *ast)
-{
-	struct brcm_pvt *p;
-	struct brcm_subchannel *sub = ast_channel_tech_pvt(ast), *sub_peer;
-	struct ast_channel *peer_owner;
-	int conf_timer_removed = 0;
-
-	if (!sub) {
-		ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
-		return 0;
-	}
-
-	p = sub->parent;
-	pvt_lock(p, "TELCHAN hangup");
-	sub_peer = brcm_subchannel_get_peer(sub);
-
-	ast_debug(1, "ast=%s line_id=%d connection_id=%d dialtone=%s channel_state=%s peer_state=%s\n",
-		ast_channel_name(ast), p->line_id, sub->connection_id, dialtone_map[p->dialtone].str,
-		state2str(sub->channel_state), state2str(sub_peer->channel_state));
-	/* If call is not connected (INCALL) or is dialing but Subchannel is busy, move to Disconnected state */
-	if ((sub->channel_state!= ONHOOK && sub_peer->channel_state != OFFHOOK))
-	{
-		//Ignore state change if we are INCALL
-		if(sub->channel_state != INCALL && sub_peer->channel_state != INCALL)
-		{
-		  /*Cases where other party doesnt picksup call ,after timeout move it to idle status */
-		  if(sub->channel_state == RINGING && sub_peer->channel_state == ONHOOK)
-			  strncpy(p->extensionCallStatus, "Idle", CALL_STATUS_MAX_LEN);
-		  else
-			  strncpy(p->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN);
-		}
-	}
-
-	if (sub_peer->conf_timer_id != -1) {
-		conf_timer_removed = 1;
-		if (ast_sched_del(sched, sub_peer->conf_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled conference setup timer\n");
-		}
-		sub_peer->conf_timer_id = -1;
-	}
-
-	if (sub->conf_timer_id != -1){
-		conf_timer_removed = 1;
-		if (ast_sched_del(sched, sub->conf_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled conference setup timer\n");
-		}
-		sub->conf_timer_id = -1;
-	}
-
-	if (sub->channel_state == CALLWAITING) {
-		brcm_stop_callwaiting(p);
-	} else if (sub_peer->channel_state == ONHOLD &&
-			sub_peer->onhold_hangup_timer_id != -1 && sub->channel_state == RINGING) {
-		ast_debug(2, "There is a forgotten onhold call, not releasing channel\n");
-		endpt_signal(sub->parent->line_id, "ringback", "off", NULL);
-	} else if (sub->channel_state == RINGING || sub->onhold_hangup_timer_id != -1) {
-		//Stop ringing if other end hungup before we answered
-                channel_settings *s = &channel_config[p->line_id];
-		if (!s->calleridenable) {
-			p->tech->stop_ringing(p);
-		} else {
-			p->tech->stop_ringing_callerid_pending(p);
-		}
-	} else if (brcm_subchannel_is_idle(sub_peer) && p->tech->release) {
-		// No active subchannel left, release
-		ast_debug(1, "Release the call since the peer sub-channel is also idle\n");
-		p->tech->release(p);
-	}
-
-	if (sub->cw_timer_id != -1) {
-		if (ast_sched_del(sched, sub->cw_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n");
-		}
-		sub->cw_timer_id = -1;
-	}
-
-	if (sub->cwBeep_timer_id != -1) {
-		if (ast_sched_del(sched, sub->cwBeep_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled call waiting beep timer\n");
-		}
-		sub->cwBeep_timer_id = -1;
-	}
-
-	if(sub->r4_hangup_timer_id != -1) {
-		if (ast_sched_del(sched, sub->r4_hangup_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled r4 hangup timer\n");
-		}
-		sub->r4_hangup_timer_id = -1;
-	}
-
-	if(sub->onhold_hangup_timer_id != -1) {
-		if (ast_sched_del(sched, sub->onhold_hangup_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled onhold hangup timer\n");
-		}
-		sub->onhold_hangup_timer_id = -1;
-	}
-	ast_setstate(ast, AST_STATE_DOWN);
-
-	p->lastformat = NULL;
-	p->lastinput = NULL;
-	p->hf_detected = 0;
-
-	/**
-	 * Howler tone is played using a media file on an active channel
-	 * Treated like a normal call but we want to preserve the channel state
-	 * Additional check for ONHOOK channel state so that handle_dialtone_timeout()
-	 * isn't called again when going on-hook
-	 */
-	if (p->dialtone != DIALTONE_HOWLER && sub->channel_state != ONHOOK) {
-		/*In case the call ends before connecting ,move the party to ONHOOK state Since its already on ONHOOK ,
-		we never get on ONHOOK event again*/
-		if (sub->channel_state == RINGING || sub->channel_state == ONHOLD)
-			sub->channel_state = ONHOOK;
-		else
-			sub->channel_state = CALLENDED;
-		ast_debug(6, "Setting channel state to %s\n", state2str(sub->channel_state));
-	}
-
-	if (sub->conference_initiator && brcm_in_conference(p)) {
-		/* Switch still active call leg out of conference mode */
-		brcm_stop_conference(sub);
-		brcm_stop_conference(sub_peer);
-	}
-
-	if (sub_peer->channel_state == INCALL && conf_timer_removed == 1) {
-		ast_log(LOG_NOTICE,"In case some party hangs up ,Unhold the other parties \n");
-		pvt_lock(sub_peer->parent, "Brcm Hangup");
-		if(sub_peer->owner)
-			ast_channel_ref(sub_peer->owner);
-		peer_owner = sub_peer->owner;
-		pvt_unlock(sub_peer->parent);
-		brcm_unmute_connection(sub_peer);
-		ast_queue_unhold(peer_owner);
-		sub_peer->channel_state = INCALL;
-	}
-
-	memset(p->ext, 0, sizeof(p->ext));
-	sub->owner = NULL;
-	sub->conference_initiator = 0;
-	free(sub->conference_id);
-	sub->conference_id = NULL;
-	ast_module_unref(ast_module_info->self);
-	ast_verb(3, "Hungup '%s'\n", ast_channel_name(ast));
-	ast_channel_tech_pvt_set(ast, NULL);
-	brcm_close_connection(sub);
-
-	/* Check for channel state before dial tone timeout */
-	if(sub->channel_state == CALLENDED && sub_peer->channel_state != INCALL) {
-		/* If we hangup but not playing howler, start playing timeout tones */
-		p->dialtone = DIALTONE_ON;
-		handle_dialtone_timeout(p);
-	}
-
-	if (sub_peer->cwBeep_timer_id != -1) {
-		if (ast_sched_del(sched, sub_peer->cwBeep_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled call waiting beep timer\n");
-		}
-		sub_peer->cwBeep_timer_id = -1;
-	}
-
-	pvt_unlock(p);
-	return 0;
-}
-
-static int brcm_answer(struct ast_channel *ast)
-{
-	struct brcm_subchannel *sub = ast_channel_tech_pvt(ast);
-	struct brcm_pvt *pvt = sub->parent;
-
-	ast_debug(1, "brcm_answer(%s)\n", ast_channel_name(ast));
-	pvt_lock(pvt, "TELCHAN answer");
-
-	/* For attended call transfer, if the transfer target has accepted the call initiated by
-	 * us as the tranferee, we can terminate the original call with the transferor */
-	if (sub->channel_state == TRANSFERING) {
-		struct brcm_subchannel *peer = brcm_subchannel_get_peer(sub);
-
-		if (peer->owner) {
-			ast_debug(1, "Transferee terminates the original call with the transferor\n");
-			ast_queue_control(peer->owner, AST_CONTROL_HANGUP);
-			peer->owner = NULL;
-			peer->channel_state = CALLENDED;
-			brcm_close_connection(peer);
-		}
-	}
-
-	if (ast_channel_state(ast) != AST_STATE_UP) {
-		ast_setstate(ast, AST_STATE_UP);
-		ast_debug(2, "brcm_answer(%s) set state to up\n", ast_channel_name(ast));
-	}
-	ast_channel_rings_set(ast, 0);
-
-	/**
-	 * Howler tone is played using a media file on an active channel
-	 * Treated like a normal call but we want to preserve the channel_state
-	 */
-	if(pvt->dialtone != DIALTONE_HOWLER) {
-            if(sub->channel_state != CALLENDED)/*Dont change the channel state if call is terminated */
-		sub->channel_state = INCALL;
-	}
-	endpt_signal(pvt->line_id, "answer", "on", NULL);
-	brcm_send_ubus_event("RINGING_OFF",pvt->line_id);
-	endpt_signal(pvt->line_id, "ringback", "off", NULL);
-
-	if(sub->channel_state != CALLENDED)
-		strncpy(pvt->extensionCallStatus, "Connected", CALL_STATUS_MAX_LEN);
-	else
-		strncpy(pvt->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN);
-
-	pvt_unlock(pvt);
-
-	return 0;
-}
-
-/*
-* Map RTP data header value to a codec name
-*/
-static char* brcm_get_codec_string(int id) {
-	switch (id) {
-			case PCMA:		return "alaw"; break;
-			case PCMU:		return "ulaw"; break;
-			case G723:		return "g723.1"; break;
-			case G726:		return "g726"; break;
-			case G729:		return "g729"; break;
-			case G722:		return "g722"; break;
-			case CN:        	return "cn"; break;
-			case -1:		return "none set"; break;
-			default: 		return "unknown id"; break;
-	}
-}
-
-static int brcm_classify_rtp_packet(int id) {
-
-	//ast_debug(5, "RTP Packet ID = %d\n", id);
-
-	switch (id) {
-		case PCMU: 	return BRCM_AUDIO;
-		case G726: 	return BRCM_AUDIO;
-		case G723: 	return BRCM_AUDIO;
-		case PCMA: 	return BRCM_AUDIO;
-		case G729: 	return BRCM_AUDIO;
-		case G722: 	return BRCM_AUDIO;
-		case CN: 	return BRCM_AUDIO;
-		case RTCP_SR: 	return BRCM_RTCP_SR;
-		case RTCP_RR: 	return BRCM_RTCP_RR;
-		default:
-			ast_verbose("Unknown rtp packet id %d\n", id);
-			return BRCM_UNKNOWN;
-	}
-}
-
-static int map_ast_codec_id_to_rtp(const struct ast_format *astcodec)
-{
-	if (ast_format_cmp(astcodec, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
-		return PCMA;
-	} else if (ast_format_cmp(astcodec, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
-		return PCMU;
-	} else if (ast_format_cmp(astcodec, ast_format_g722) == AST_FORMAT_CMP_EQUAL) {
-		return G722;
-	} else if (ast_format_cmp(astcodec, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
-		return G723;
-	} else if (ast_format_cmp(astcodec, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
-		return G729;
-	} else if (ast_format_cmp(astcodec, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
-		return G726;
-	} else {
-		ast_verbose("Unknown asterisk format/codec id\n");
-		return PCMA;
-	}
-}
-
-
-static struct ast_frame  *brcm_read(struct ast_channel *ast)
-{
-	return &ast_null_frame;
-}
-
-/* Handle stream events on audio_bus. Parses raw stream and calls 
-   registered packet handlers. */
-static void audio_rx_stream_handler(pe_stream_t *stream __attribute__((unused)), pe_event_t *event __attribute__((unused))) {
-	if (pe_bus_receive(audio_rx_bus, event) < 0) {
-		printf("audio_bus rx buffer full");
-		return;																	// Drop packets if we can't cope the pace
-	}
-
-	pe_bus_dispatch(audio_rx_bus);
-}
-
-static int brcm_write(struct ast_channel *ast, struct ast_frame *frame)
-{
-	struct brcm_subchannel *sub = ast_channel_tech_pvt(ast);
-	int packet_size;
-	audio_packet_t *ap;
-
-	if (ast_channel_state(ast) != AST_STATE_UP && ast_channel_state(ast) != AST_STATE_RING) {
-		/* Silently ignore packets until channel is up */
-		ast_debug(5, "error: channel not up\n");
-		return 0;
-	}
-
-	/* Ignore if on hold */
-	if (sub->channel_state == ONHOLD) {
-		return 0;
-	}
-	if (frame->frametype == AST_FRAME_CNG) {
-		/*packet_size = sizeof(audio_packet_t) - 1 + RTP_HEADER_SIZE + frame->datalen;
-		CNG paket has only 1 data for the noise lvl, datalen=1*/
-		packet_size = sizeof(audio_packet_t) + RTP_HEADER_SIZE ;
-		ap = calloc(1, packet_size);
-		if (!ap) {
-			ast_log(LOG_ERROR, "Out of memory\n");
-			return -1;
-		}
-
-		ap->line = sub->parent->line_id;
-		ap->cnx_id = sub->parent->line_id;
-		ap->rtp_size = RTP_HEADER_SIZE + 1;
-
-		/* copy frame data to audio packet */
-		/* level = 127 - (level & 0x7f); */
-		ap->rtp[12]=127 - (frame->subclass.integer & 0x7f);
-
-		//ast_mutex_lock(&sub->parent->lock);
-		pvt_lock(sub->parent, "TELCHAN write frame");
-
-		/* generate the rtp header */
-		brcm_generate_rtp_packet(sub, ap->rtp, CN, 0, 0, frame->seqno);
-
-		/* set rtp id sent to endpoint */
-		sub->codec = CN;
-
-		//ast_mutex_unlock(&sub->parent->lock);
-		pvt_unlock(sub->parent);
-		pe_bus_send(audio_tx_bus, (uint8_t *)ap, packet_size);
-		free(ap);
-	}
-
-	if(frame->frametype == AST_FRAME_VOICE) {
-		packet_size = sizeof(audio_packet_t) - 1 + RTP_HEADER_SIZE + frame->datalen;
-		ap = calloc(1, packet_size);
-		if (!ap) {
-			ast_log(LOG_ERROR, "Out of memory\n");
-			return -1;
-		}
-
-		ap->line = sub->parent->line_id;
-		ap->cnx_id = sub->parent->line_id;
-		ap->rtp_size = RTP_HEADER_SIZE + frame->datalen;
-
-		/* copy frame data to audio packet */
-		memcpy(ap->rtp + RTP_HEADER_SIZE, frame->data.ptr, frame->datalen);
-
-		//ast_mutex_lock(&sub->parent->lock);
-		pvt_lock(sub->parent, "TELCHAN write frame");
-
-		/* generate the rtp header */
-		brcm_generate_rtp_packet(sub, ap->rtp, map_ast_codec_id_to_rtp(frame->subclass.format), 0, 0, frame->seqno);
-
-		/* set rtp id sent to endpoint */
-		sub->codec = map_ast_codec_id_to_rtp(frame->subclass.format);
-
-		//ast_mutex_unlock(&sub->parent->lock);
-		pvt_unlock(sub->parent);
-
-		pe_bus_send(audio_tx_bus, (uint8_t *)ap, packet_size);
-		free(ap);
-	}
-
-	if(frame->frametype == AST_FRAME_RTCP) {
-		packet_size = sizeof(audio_packet_t) - 1 + frame->datalen;
-		ap = calloc(1, packet_size);
-		if (!ap) {
-			ast_log(LOG_ERROR, "Out of memory\n");
-			return -1;
-		}
-
-		ap->line = sub->parent->line_id;
-		ap->cnx_id = sub->parent->line_id;
-		ap->rtp_size = frame->datalen;
-
-		/* copy frame data to audio packet */
-		memcpy(ap->rtp, frame->data.ptr, frame->datalen);
-
-		brcm_interpret_rtcp_packet(sub, ap->rtp, ap->rtp_size);
-
-		pe_bus_send(audio_tx_bus, (uint8_t *)ap, packet_size);
-		free(ap);
-	}
-	return 0;
-}
-
-static void brcm_reset_dtmf_buffer(struct brcm_pvt *p)
-{
-	memset(p->dtmfbuf, 0, sizeof(p->dtmfbuf));
-	p->dtmf_len = 0;
-	p->dtmf_first = -1;
-	p->dtmfbuf[p->dtmf_len] = '\0';
-}
-
-static char *state2str(enum brcm_channel_state state)
-{
-	switch (state) {
-	case ONHOOK:		return "ONHOOK";
-	case OFFHOOK:		return "OFFHOOK";
-	case DIALING:		return "DIALING";
-	case CALLING:		return "CALLING";
-	case INCALL:		return "INCALL";
-	case ANSWER:		return "ANSWER";
-	case CALLENDED:		return "CALLENDED";
-	case RINGING:		return "RINGING";
-	case CALLWAITING:	return "CALLWAITING";
-	case ONHOLD:		return "ONHOLD";
-	case TRANSFERING:	return "TRANSFERING";
-	case RINGBACK:		return "RINGBACK";
-	case AWAITONHOOK:	return "AWAITONHOOK";
-	case ALLOCATED:		return "ALLOCATED";
-	default:			return "UNKNOWN";
-	}
-}
-
-static int brcm_subchannel_is_idle(const struct brcm_subchannel *sub)
-{
-	if (sub->channel_state == ONHOOK || sub->channel_state == CALLENDED) {
-		return 1;
-	}
-	return 0;
-}
-
-struct brcm_subchannel *brcm_subchannel_get_peer(const struct brcm_subchannel *sub)
-{
-	struct brcm_subchannel *peer_sub;
-	peer_sub = (sub->parent->sub[0] == sub) ? sub->parent->sub[1] : sub->parent->sub[0];
-	return peer_sub;
-}
-
-/* Tell endpoint to play country specific dialtone. */
-static int brcm_signal_dialtone(struct brcm_pvt *p) {
-
-	ast_verbose("Setting dialtone to %s\n", dialtone_map[p->dialtone].str);	
-	switch (p->dialtone) {
-		case DIALTONE_OFF:
-		case DIALTONE_MWI_OFF:
-			endpt_signal(p->line_id, "dial", "off", NULL); // this will turn off any tones that is playing. Act as play dial-off.
-			break;
-		case DIALTONE_ON:
-			endpt_signal(p->line_id, "dial", "on", NULL);
-			break;
-		case DIALTONE_CONGESTION:
-			endpt_signal(p->line_id, "congestion", "on", NULL);
-			break;
-		case DIALTONE_SPECIAL_CONDITION:
-			endpt_signal(p->line_id, "stutter", "on", NULL);
-			break;
-		case DIALTONE_UNOBTAINABLE:
-			endpt_signal(p->line_id, "unobtainable", "on", NULL);
-			break;
-		case DIALTONE_HOWLER:
-			ast_debug(9, "Trigger howler tone from Asterisk\n");
-			brcm_signal_howler(p);
-			break;
-		default:
-			ast_log(LOG_ERROR, "Requested to signal unknown dialtone\n");
-			return -1;
-	}
-	return 0;
-}
-
-static void brcm_signal_howler(struct brcm_pvt *p) {
-	struct brcm_subchannel *sub = brcm_get_active_subchannel(p);
-
-	if(!sub) {
-		ast_debug(9, "Unable to find active subchannel\n");
-		return;
-	}
-
-	/* Start the pbx */
-	if (!sub->connection_init) {
-		sub->connection_id = ast_atomic_fetchadd_int((int *)&current_connection_id, +1);
-		brcm_create_connection(sub);
-	}
-
-	/* Create a new channel to context 'howler' handled by extensions.conf */
-	brcm_new(sub, AST_STATE_RING, "0", "howler", NULL, NULL, NULL);
-}
-
-int brcm_stop_dialtone(struct brcm_pvt *p) {
-	p->dialtone = DIALTONE_OFF;
-	brcm_signal_dialtone(p);
-	brcm_send_ubus_event("DIALTONE_OFF",p->line_id);
-	return 0;
-}
-
-static struct ast_channel *brcm_new(struct brcm_subchannel *subchan, int state, const char *ext, const char *context,
-		const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
-		struct ast_format_cap *format)
-{
-	struct ast_channel *chan = NULL;
-	struct ast_format *fmt;
-	struct ast_format_cap *caps;
-
-	caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
-	if (!caps) {
-		return NULL;
-	}
-	
-	chan = ast_channel_alloc(1, state, subchan->parent->cid_num, subchan->parent->cid_name, "", ext, context,
-			assignedids, requestor, 0, "TELCHAN/%d/%d", subchan->parent->line_id, subchan->connection_id);
-	if (chan) {
-		ast_channel_tech_set(chan, cur_tech);
-
-		ast_format_cap_append_from_cap(caps, default_cap, AST_MEDIA_TYPE_UNKNOWN);	
-		ast_channel_nativeformats_set(chan, caps);
-		ao2_ref(caps, -1);
-		fmt = ast_format_cap_get_format(ast_channel_nativeformats(chan), 0);
-
-		channel_settings *s = &channel_config[subchan->parent->line_id];
-
-		/* set codecs */
-		ast_channel_set_writeformat(chan, fmt);
-		ast_channel_set_rawwriteformat(chan, fmt);
-		ast_channel_set_readformat(chan, fmt);
-		ast_channel_set_rawreadformat(chan, fmt);
-
-		/* no need to call ast_setstate: the channel_alloc already did its job */
-		if (state == AST_STATE_RING)
-			ast_channel_rings_set(chan, 1);
-		ast_channel_tech_pvt_set(chan, subchan);
-		/* Don't use ast_set_callerid() here because it will
-		 * generate a NewCallerID event before the NewChannel event */
-		if (!ast_strlen_zero(subchan->parent->cid_num)) {
-			ast_channel_caller(chan)->ani.number.valid = 1;
-			ast_channel_caller(chan)->ani.number.str = ast_strdup(subchan->parent->cid_num);
-		}
-
-		ast_channel_caller(chan)->id.number.presentation = s->anonymouscallenable ? AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED : AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-		ast_channel_caller(chan)->id.name.presentation = s->calleridnameenable;
-
-		//Setup jitter buffer
-		ast_jb_configure(chan, &global_jbconf);
-		subchan->owner = chan;
-
-		ast_module_ref(ast_module_info->self);
-
-		if (state != AST_STATE_DOWN) {
-			if (ast_pbx_start(chan)) {
-				ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(chan));
-				ast_hangup(chan);
-				return NULL;
-			}
-		}
-
-		ast_channel_unlock(chan);
-	} else
-		ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
-
-	return chan;
-}
-
-
-static struct brcm_pvt* brcm_get_next_pvt(struct brcm_pvt *p) {
-	if (p && p->next)
-		return p->next;
-	else
-		return NULL;
-}
-
-struct brcm_pvt* brcm_get_pvt_from_lineid(struct brcm_pvt *p, int line_id)
-{
-	struct brcm_pvt *tmp = p;
-	if (p && p->line_id == line_id) return p;
-	tmp = brcm_get_next_pvt(tmp);
-
-	while(tmp) {
-		if (tmp->line_id == line_id) return tmp;
-		tmp = brcm_get_next_pvt(tmp);
-	}
-	return NULL;
-}
-
-struct brcm_subchannel* brcm_get_active_subchannel(const struct brcm_pvt *p)
-{
-	struct brcm_subchannel *sub = NULL;
-	int i;
-
-	if(!p)
-		return NULL;
-
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		switch (p->sub[i]->channel_state) {
-			case INCALL:
-			case DIALING:
-			case CALLING:
-			case OFFHOOK:
-			case AWAITONHOOK:
-			case RINGING:
-			case TRANSFERING:
-			case RINGBACK:
-				sub = p->sub[i];
-				return sub;
-			case CALLWAITING:
-			case ONHOLD:
-				break;
-			case ONHOOK:
-			case ANSWER:
-			case CALLENDED:
-				if (!sub) {
-					sub = p->sub[i];
-				}
-				break;
-			default:
-				ast_log(LOG_WARNING, "Unhandled channel state %d\n", p->sub[i]->channel_state);
-				break;
-		}
-	}
-
-	ast_assert(sub != NULL);
-	return sub;
-}
-
-static struct brcm_subchannel *brcm_get_onhold_subchannel(const struct brcm_pvt *p)
-{
-	struct brcm_subchannel *sub;
-	int i;
-	for(i=0; i<NUM_SUBCHANNELS; i++) {
-			sub = p->sub[i];
-			if (sub->channel_state == ONHOLD) {
-				return sub;
-			}
-	}
-	return NULL;
-}
-
-/*Set up a Conference call on press of flash hook once timer expires */
-static int setup_conference_call_cb( const void *data)
-{
-    struct brcm_subchannel *sub_peer;
-    struct ast_channel *peer_owner = NULL;
-    
-    ast_log(LOG_NOTICE ,"Set up a conference call\n");
-    struct brcm_pvt *p = (struct brcm_pvt *) data;
-    struct brcm_subchannel *sub = brcm_get_active_subchannel(p);
-    sub_peer = brcm_subchannel_get_peer(sub);
-    pvt_lock(sub->parent, "setup_conference_call_cb");
-    if (sub_peer->owner) {
-        ast_channel_ref(sub_peer->owner);
-        peer_owner = sub_peer->owner;
-    }
-
-    pvt_unlock(sub->parent);
-    /* Setup conference if no DTMF is pressed after flash ,i.e we are not waiting for DTMF now*/
-    if((sub->conf_timer_id != -1) || (sub_peer->conf_timer_id != -1))
-    {
-        ast_log(LOG_NOTICE,"Valid flags to start a Conference Call\n");
-        brcm_create_conference(p);
-        if (peer_owner) {
-            sub_peer->channel_state = INCALL;
-        }
-         sub->channel_state = INCALL;
-         sub->conf_timer_id = -1;
-         sub_peer->conf_timer_id = -1;
-    }
-
-    brcm_send_ubus_event("UNHOLD",sub->parent->line_id);
-    brcm_send_ubus_event("CONFERENCE_START",sub->parent->line_id);
-    if (peer_owner) {
-        ast_channel_unref(peer_owner);
-    }
-    return 0;
-}
-
-/* Hangup incoming call after call waiting times out */
-static int cwtimeout_cb(const void *data)
-{
-	struct brcm_subchannel *sub;
-	struct ast_channel *owner = NULL;
-
-
-	sub = (struct brcm_subchannel *) data;
-	ast_debug(2, "No response to call waiting, hanging up, sub->channel_state: %d\n", sub->channel_state);
-	//ast_mutex_lock(&sub->parent->lock);
-	pvt_lock(sub->parent, "Cwtimeout callback");
-	if (sub->cwBeep_timer_id != -1) {
-		if (ast_sched_del(sched, sub->cwBeep_timer_id)) {
-			ast_log(LOG_WARNING, "Failed to remove scheduled call waiting beep timer\n");
-		}
-		sub->cwBeep_timer_id = -1;
-	}
-	sub->cw_timer_id = -1;
-	if (sub->owner) {
-		ast_channel_ref(sub->owner);
-		owner = sub->owner;
-	}
-	//ast_mutex_unlock(&sub->parent->lock);
-	if (sub->channel_state == CALLWAITING)
-		brcm_stop_callwaiting(sub->parent);
-	else if (sub->channel_state == RINGING)
-		brcm_stop_ringing(sub->parent);
-	pvt_unlock(sub->parent);
-
-	if (owner) {
-		ast_channel_lock(owner);
-		ast_channel_hangupcause_set(owner, AST_CAUSE_USER_BUSY);
-		ast_queue_control(owner, AST_CONTROL_BUSY);
-		ast_channel_unlock(owner);
-		ast_channel_unref(owner);
-	}
-
-	return 0;
-}
-
-/* Play beep during call waiting */
-static int cwbeep_cb(const void *data)
-{
-	struct brcm_subchannel *sub = (struct brcm_subchannel *) data;
-	int cwBeep_ms = cwBeep * 1000;
-
-	pvt_lock(sub->parent, "cwbeep_cb callback");
-	if (sub->parent) {
-		brcm_signal_callwaiting(sub->parent);
-	}
-	pvt_unlock(sub->parent);
-
-	sub->cwBeep_timer_id = ast_sched_add(sched, cwBeep_ms, cwbeep_cb, sub);
-
-	return 0;
-}
-
-/* Hangup calls if not done by remote after R4 transfer */
-static int r4hanguptimeout_cb(const void *data)
-{
-	struct brcm_subchannel *sub;
-	struct brcm_subchannel *peer_sub;
-
-	struct ast_channel *sub_owner = NULL;
-	struct ast_channel *peer_sub_owner = NULL;
-
-	ast_debug(2, "No hangup from remote after remote transfer using R4, hanging up\n");
-
-	sub = (struct brcm_subchannel *) data;
-	peer_sub = brcm_subchannel_get_peer(sub);
-
-	//ast_mutex_lock(&sub->parent->lock);
-	pvt_lock(sub->parent, "r4hanguptimeout callback");
-
-	sub->r4_hangup_timer_id = -1;
-	peer_sub->channel_state = CALLENDED;
-	sub->channel_state = CALLENDED;
-
-	if (sub->owner) {
-		ast_channel_ref(sub->owner);
-		sub_owner = sub->owner;
-	}
-	if (peer_sub->owner) {
-		ast_channel_ref(peer_sub->owner);
-		peer_sub_owner = peer_sub->owner;
-	}
-	//ast_mutex_unlock(&sub->parent->lock);
-	pvt_unlock(sub->parent);
-
-	if (sub_owner) {
-		ast_queue_control(sub_owner, AST_CONTROL_HANGUP);
-		ast_channel_unref(sub_owner);
-	}
-
-	if (peer_sub_owner) {
-		ast_queue_control(peer_sub_owner, AST_CONTROL_HANGUP);
-		ast_channel_unref(peer_sub_owner);
-	}
-
-	return 0;
-}
-
-/* Hangup call onhold if user does not pick up after reminder ringing */
-static int onholdhanguptimeout_cb(const void *data)
-{
-	struct brcm_subchannel *sub;
-	struct ast_channel *sub_owner = NULL;
-
-	ast_debug(2, "No pickup after reminder ringing for call on hold, hanging up\n");
-	sub = (struct brcm_subchannel *) data;
-
-	//ast_mutex_lock(&sub->parent->lock);
-	pvt_lock(sub->parent, "onholdhanguptimeout callback");
-
-	sub->onhold_hangup_timer_id = -1;
-
-	if (sub->owner) {
-		ast_channel_ref(sub->owner);
-		sub_owner = sub->owner;
-	}
-	//ast_mutex_unlock(&sub->parent->lock);
-	pvt_unlock(sub->parent);
-
-	if (sub_owner) {
-		ast_queue_control(sub_owner, AST_CONTROL_HANGUP);
-		ast_channel_unref(sub_owner);
-	}
-
-	return 0;
-}
-
-/*
- * Helper function that tells asterisk to start a call on the provided pvt/sub/context
- * using the content of the dtmf buffer.
- */
-static void brcm_start_calling(struct brcm_subchannel *sub, char* context)
-{
-	sub->channel_state = CALLING;
-	ast_copy_string(sub->parent->ext, sub->parent->dtmfbuf, sizeof(sub->parent->ext));
-
-	ast_debug(1, "Calling %s@%s\n", sub->parent->ext, context);
-
-	/* Reset the dtmf buffer */
-	brcm_reset_dtmf_buffer(sub->parent);
-
-	/* Reset hook flash state */
-	sub->parent->hf_detected = 0;
-
-	/* Start the pbx */
-	if (!sub->connection_init) {
-		sub->connection_id = ast_atomic_fetchadd_int((int *)&current_connection_id, +1);
-		brcm_create_connection(sub);
-	}
-
-	/* Changed state from AST_STATE_UP to AST_STATE_RING ito get the brcm_answer callback
-	 * which is needed for call waiting. */
-	brcm_new(sub, AST_STATE_RING, sub->parent->ext, context, NULL, NULL, NULL);
-}
-
-/*
- * Start calling if we have a (partial) match in asterisks dialplan after an interdigit timeout.
- * Called on scheduler thread.
- */
-static int handle_interdigit_timeout(const void *data)
-{
-	ast_debug(9, "Interdigit timeout\n");
-	struct brcm_pvt *p = (struct brcm_pvt *) data;
-	//ast_mutex_lock(&p->lock);
-	pvt_lock(p, "interdigit callback");
-	p->interdigit_timer_id = -1;
-	struct brcm_subchannel *sub = brcm_get_active_subchannel(p);
-        if (channel_config[p->line_id].minimumnumberdigits  && strlen(p->dtmfbuf) >= channel_config[p->line_id].minimumnumberdigits){
-           if (ast_exists_extension(NULL, p->context, p->dtmfbuf, 1, p->cid_num))
- 	   {
-		//We have at least one matching extension in "normal" context,
-		//and interdigit timeout has passed, so have asterisk start calling.
-		//Asterisk will select the best matching extension if there are more than one possibility.
-		ast_debug(9, "Interdigit timeout, extension(s) matching %s found\n", p->dtmfbuf);
-		brcm_start_calling(sub, p->context);
-	   }
-        }
-        //if no limit on minimum digits check extension exits
-        if(!channel_config[p->line_id].minimumnumberdigits){
-            if (ast_exists_extension(NULL, p->context, p->dtmfbuf, 1, p->cid_num))
-           {
-                //We have at least one matching extension in "normal" context,
-                //and interdigit timeout has passed, so have asterisk start calling.
-                //Asterisk will select the best matching extension if there are more than one possibility.
-                ast_debug(9, "Interdigit timeout, extension(s) matching %s found\n", p->dtmfbuf);
-                brcm_start_calling(sub, p->context);
-           }
-       }
-	//ast_mutex_unlock(&p->lock);
-	pvt_unlock(p);
-	return 0;
-}
-
-/*
- * Start autodialing if we have an autodial extension.
- * Called on scheduler thread.
- */
-static int handle_autodial_timeout(const void *data)
-{
-	ast_debug(9, "Autodial timeout\n");
-	struct brcm_pvt *p = (struct brcm_pvt *) data;
-	pvt_lock(p, "autodial timeout");
-	//ast_mutex_lock(&p->lock);
-	p->autodial_timer_id = -1;
-	struct brcm_subchannel *sub = brcm_get_active_subchannel(p);
-	channel_settings *s = &channel_config[p->line_id];
-
-	if (ast_exists_extension(NULL, p->context, s->autodial_ext, 1, p->cid_num))
-	{
-		brcm_stop_dialtone(p);
-		ast_copy_string(p->dtmfbuf, s->autodial_ext, sizeof(p->dtmfbuf));
-		ast_debug(9, "Autodialing extension: %s\n", p->dtmfbuf);
-		brcm_start_calling(sub, p->context);
-	}
-	//ast_mutex_unlock(&p->lock);
-	pvt_unlock(p);
-	return 0;
-}
-
-/*
- * Dialtone expired, play congestion tone
- * Called on scheduler thread.
- */
-static int handle_dialtone_timeout(const void *data)
-{
-	struct brcm_pvt *p = (struct brcm_pvt *) data;
-
-	pvt_lock(p, "dialtone timeout");
-	strncpy(p->extensionCallStatus, "Disconnected", CALL_STATUS_MAX_LEN);
-	//ast_mutex_lock(&p->lock);
-	p->dialtone_timeout_timer_id = -1;
-
-	struct brcm_subchannel *sub = brcm_get_active_subchannel(p);
-
-	ast_debug(9, "Dialtone timeout, sub->channel_state: %s\n", state2str(sub->channel_state));
-
-	if (sub && (sub->channel_state == OFFHOOK || sub->channel_state == AWAITONHOOK || sub->channel_state == CALLENDED)) {
-		/* Enter state where nothing else other than ONHOOK is accepted and play series of tones */
-		sub->channel_state = AWAITONHOOK;
-		channel_settings *s = &channel_config[p->line_id];
-
-		switch (p->dialtone) {
-			case DIALTONE_ON:
-			case DIALTONE_SPECIAL_CONDITION:
-			case DIALTONE_CONGESTION:
-			case DIALTONE_MWI_OFF:
-				// Include all 4 dial tones available for asterisk.set1.mwi_dialtone_state
-				p->dialtone = DIALTONE_UNOBTAINABLE;
-				p->dialtone_timeout_timer_id = ast_sched_add(sched, s->offhook_nu_timeoutmsec, handle_dialtone_timeout, p);
-				break;
-			case DIALTONE_UNOBTAINABLE:
-				p->dialtone = DIALTONE_OFF;
-				p->dialtone_timeout_timer_id = ast_sched_add(sched, s->offhook_silence_timeoutmsec, handle_dialtone_timeout, p);
-				break;
-			case DIALTONE_OFF:
-				p->dialtone = DIALTONE_HOWLER;
-				break;
-			default:
-				p->dialtone = DIALTONE_OFF;
-				ast_log(LOG_ERROR, "Invalid dialtone timeout state\n");
-				break;
-		}
-		brcm_signal_dialtone(p);
-	}
-
-	//ast_mutex_unlock(&p->lock);
-	pvt_unlock(p);
-	return 0;
-}
-
-/*
- * Start calling if we have a match in asterisks dialplan.
- * Called after each new DTMF event, from monitor_events thread,
- * with the required locks already held.
- */
-void handle_dtmf_calling(struct brcm_subchannel *sub)
-{
-	struct brcm_pvt *p = sub->parent;
-	char termination_digit;
-	int dtmfbuf_len = strlen(p->dtmfbuf);
-	char dtmf_last_char = p->dtmfbuf[(dtmfbuf_len - 1)];
-	char dtmf_one_before_last_char = p->dtmfbuf[(dtmfbuf_len > 1 ? dtmfbuf_len - 2 : 0)];
-        
-	termination_digit = channel_config[p->line_id].terminationdigit?channel_config[p->line_id].terminationdigit:0x23;
-
-	if (ast_exists_extension(NULL, p->context_direct, p->dtmfbuf, 1, p->cid_num) && !ast_matchmore_extension(NULL, p->context_direct, p->dtmfbuf, 1, p->cid_num))
-	{
-		//We have a full match in the "direct" context, so have asterisk place a call immediately
-		ast_debug(9, "Direct extension matching %s found\n", p->dtmfbuf);
-		brcm_start_calling(sub, p->context_direct);
-	}
-
-
-	else if (ast_exists_extension(NULL, p->context, p->dtmfbuf, 1, p->cid_num) && dtmf_last_char == termination_digit
-                && dtmf_one_before_last_char != 0x2A && feature_access_code_match(p->dtmfbuf) != 1) {
-                if(channel_config[p->line_id].minimumnumberdigits)
-                {
-                    //Minimum dtmf limit is checked before starting a call.If limit is not reached,ignore
-                    //We have a match in the "normal" context, and user ended the dialling sequence with a # or temination digit set  in dialplan,
-                    //so have asterisk place a call immediately if sequence is not partially matching a feature access code
-                    ast_log(LOG_NOTICE, "Termination key %c is pressed during dialing, extension %s found\n",termination_digit, p->dtmfbuf);
-                    if(strlen(p->dtmfbuf) >= channel_config[p->line_id].minimumnumberdigits)
-                        brcm_start_calling(sub, p->context);
-                    else
-                        ast_log(LOG_ERROR, "Not reached the minimum digits to start a call!! \n");
-                }
-               else
-               {
-                     //No minimum limit, Start calling if we encounter a terminatingdigit
-                     //We have a match in the "normal" context, and user ended the dialling sequence with a # or temination digit set  in dialplan,
-                     //so have asterisk place a call immediately if sequence is not partially matching a feature access code
-                     ast_log(LOG_NOTICE, "No minimum digit limit set start a call right away \n");
-                     brcm_start_calling(sub, p->context);
-               }
-
-	}
-	else if (ast_exists_extension(NULL, p->context, p->dtmfbuf, 1, p->cid_num) && !ast_matchmore_extension(NULL, p->context, p->dtmfbuf, 1, p->cid_num))
-	{
-		//We have a full match in the "normal" context, so have asterisk place a call immediately,
-		//since no more digits can be added to the number
-		//(this is unlikely to happen since there is probably a "catch-all" extension)
-		ast_debug(9, "Unique extension matching %s found\n", p->dtmfbuf);
-		brcm_start_calling(sub, p->context);
-	}
-	else if (!ast_matchmore_extension(NULL, p->context, p->dtmfbuf, 1, p->cid_num))
-	{
-	    //Full match has been handled in the upper conditions
-	    //Number become invalid if no ast_matchmore_extension
-	    //Set dialtone to Unobtainable, and awaiting on hook
-	    ast_debug(9, "number not matching any extensions, awaiting on hook\n");
-	    p->dialtone = DIALTONE_UNOBTAINABLE;
-	    sub->channel_state = AWAITONHOOK;
-		p->dialtone_timeout_timer_id = ast_sched_add(sched, channel_config[p->line_id].offhook_nu_timeoutmsec, handle_dialtone_timeout, p);
-	    brcm_signal_dialtone(p);
-	}
-	else {
-               if (channel_config[p->line_id].minimumnumberdigits && strlen(p->dtmfbuf) >= channel_config[p->line_id].minimumnumberdigits ){
-                   int interdigitopenmsec = channel_config[p->line_id].interdigitopenmsec;
-                   if (interdigitopenmsec){
-                       ast_debug(9,"Scheduling interdigitopenmsec timeout of %d msec\n", interdigitopenmsec);
-                       p->interdigit_timer_id = ast_sched_add(sched, interdigitopenmsec, handle_interdigit_timeout, p);
-                   }
-                   else{
-                       int timeoutmsec = channel_config[p->line_id].timeoutmsec;
-                       ast_debug(9,"Interdigitopenmsec not found !!Using timeoutsec timeout of %d msec\n", timeoutmsec);
-                       p->interdigit_timer_id = ast_sched_add(sched, timeoutmsec, handle_interdigit_timeout, p);
-                   }
-               }
-               else {
-		     //No matches. We schedule a (new) interdigit timeout to occur
-		     int timeoutmsec = channel_config[p->line_id].timeoutmsec;
-		     ast_debug(9, "Scheduling interdigit timeout of %d msec\n", timeoutmsec);
-		     p->interdigit_timer_id = ast_sched_add(sched, timeoutmsec, handle_interdigit_timeout, p);
-               }
-	}
-}
-
-static void handle_Rnumber_etsi(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner)
-{
-	struct brcm_pvt *p = sub->parent;
-
-	switch (p->dtmf_first) {
-		/* Force busy on waiting call or hang up call on hold */
-		case '0':
-			if (sub->channel_state == INCALL && sub_peer->channel_state == CALLWAITING) {
-				ast_debug(2, "Sending busy to waiting call\n");
-
-				/* Immediately send busy next time someone calls us during this call */
-				//sub->cw_rejected = 1;
-
-				if (ast_sched_del(sched, sub_peer->cw_timer_id)) {
-					ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n");
-				}
-				sub_peer->cw_timer_id = -1;
-
-				ast_queue_control(peer_owner, AST_CONTROL_BUSY);
-				ast_indicate(owner, AST_CONTROL_UNHOLD);
-			} else if (sub->channel_state == INCALL && sub_peer->channel_state == ONHOLD) {
-				ast_debug(2, "Hanging up call on hold\n");
-
-				sub_peer = brcm_get_onhold_subchannel(p);
-
-				ast_queue_control(peer_owner, AST_CONTROL_HANGUP);
-				sub_peer->channel_state = CALLENDED;
-				brcm_close_connection(sub_peer);
-			}
-			break;
-		/* Hangup current call and answer waiting call */
-		case '1':
-			if (sub->channel_state == INCALL && (sub_peer->channel_state == CALLWAITING || sub_peer->channel_state == ONHOLD)) {
-
-				/* Close connection and hangup active subchannel */
-				if (owner) {
-					ast_queue_control(owner, AST_CONTROL_HANGUP);
-				}
-				sub->channel_state = CALLENDED;
-				brcm_close_connection(sub);
-
-				if (sub_peer->channel_state == CALLWAITING) {
-					ast_log(LOG_WARNING, "R1 call waiting\n");
-					/* Stop call waiting tone on current call */
-					brcm_stop_callwaiting(p);
-
-					if (ast_sched_del(sched, sub_peer->cw_timer_id)) {
-						ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n");
-					}
-					sub_peer->cw_timer_id = -1;
-
-					/* Pick up call waiting */
-					if (!sub_peer->connection_init) {
-						ast_debug(9, "create_connection()\n");
-						brcm_create_connection(sub_peer);
-					}
-					if (peer_owner) {
-						ast_queue_control(peer_owner, AST_CONTROL_ANSWER);
-						sub_peer->channel_state = INCALL;
-					}
-				} else if (sub_peer->channel_state == ONHOLD) {
-					ast_log(LOG_WARNING, "R1 Unholding\n");
-
-					/* Unhold inactive subchannel */
-					if (peer_owner) {
-						brcm_unmute_connection(sub_peer);
-						ast_queue_unhold(peer_owner);
-						sub_peer->channel_state = INCALL;
-					}
-				}
-			}
-			break;
-		/* Answer waiting call and put other call on hold (switch calls) */
-		case '2':
-			if (sub->channel_state == INCALL && (sub_peer->channel_state == CALLWAITING || sub_peer->channel_state == ONHOLD)) {
-
-				brcm_mute_connection(sub);
-				if (owner) {
-					ast_queue_hold(owner, NULL);
-				}
-
-				if (sub_peer->channel_state == CALLWAITING) {
-					ast_log(LOG_WARNING, "R2 Call waiting\n");
-
-					/* Stop call waiting tone on current call */
-					brcm_stop_callwaiting(p);
-
-					/* Cancel timer */
-					if (ast_sched_del(sched, sub_peer->cw_timer_id)) {
-						ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n");
-					}
-					sub_peer->cw_timer_id = -1;
-
-					if (ast_sched_del(sched, sub_peer->cwBeep_timer_id)) {
-						ast_log(LOG_WARNING, "Failed to remove scheduled call waiting beep timer\n");
-					}
-					sub_peer->cwBeep_timer_id = -1;
-
-					/* Pick up call waiting */
-					if (!sub_peer->connection_init) {
-						ast_debug(9, "create_connection()\n");
-						brcm_create_connection(sub_peer);
-					}
-					if (peer_owner) {
-						ast_queue_control(peer_owner, AST_CONTROL_ANSWER);
-						sub_peer->channel_state = INCALL;
-					}
-				} else if (sub_peer->channel_state == ONHOLD) {
-					ast_log(LOG_WARNING, "R2 on hold\n");
-
-					/* Unhold inactive subchannel */
-					if (peer_owner) {
-						brcm_unmute_connection(sub_peer);
-						ast_queue_unhold(peer_owner);
-						sub_peer->channel_state = INCALL;
-					}
-				}
-
-				sub->channel_state = ONHOLD;
-			}
-			break;
-		/* Connect waiting call to existing call to create 3-way */
-		case '3':
-			if (sub->channel_state == INCALL && sub_peer->channel_state == ONHOLD) {
-				ast_debug(2, "DTMF3 after HF\n");
-				brcm_create_conference(p);
-			}
-			break;
-		/* Remote transfer held call to active call */
-		case '4':
-			brcm_attended_call_transfer(sub, sub_peer, owner, peer_owner);
-			break;
-		case '5':
-			brcm_unattended_call_transfer(sub, sub_peer, owner, peer_owner);
-			break;
-		default:
-			ast_log(LOG_NOTICE, "Unhandled DTMF %c\n", p->dtmfbuf[0]);
-			break;
-	}
-}
-
-static void handle_Rnumber_uk(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner)
-{
-	struct brcm_pvt *p = sub->parent;
-
-	switch (p->dtmf_first) {
-		case '4':
-			brcm_attended_call_transfer(sub, sub_peer, owner, peer_owner);
-			break;
-		case '5':
-			brcm_unattended_call_transfer(sub, sub_peer, owner, peer_owner);
-			break;
-		default:
-			ast_log(LOG_ERROR, "Unhandled DTMF %c\n", p->dtmfbuf[0]);
-			break;
-	}
-}
-
-static void handle_Rkey_uk(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner)
-{
-	struct brcm_pvt *p = sub->parent;
-
-	if (sub->channel_state == INCALL && (sub_peer->channel_state == CALLWAITING || sub_peer->channel_state == ONHOLD)) {
-		brcm_mute_connection(sub);
-		if (sub_peer->channel_state == CALLWAITING) {
-			if (owner) {
-				ast_queue_hold(owner, NULL);
-			}
-			ast_log(LOG_NOTICE, " R in Call waiting\n");
-			/* Cancel timers */
-			if (ast_sched_del(sched, sub_peer->cw_timer_id)) {
-				ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n");
-			}
-			sub_peer->cw_timer_id = -1;
-			if (ast_sched_del(sched, sub_peer->cwBeep_timer_id)) {
-				ast_log(LOG_WARNING, "Failed to remove scheduled call waiting beep timer\n");
-			}
-			sub_peer->cwBeep_timer_id = -1;
-			/* Pick up call waiting */
-			if (!sub_peer->connection_init) {
-				ast_debug(9, "create_connection()\n");
-				brcm_create_connection(sub_peer);
-			}
-			if (peer_owner) {
-				ast_queue_control(peer_owner, AST_CONTROL_ANSWER);
-				sub_peer->channel_state = INCALL;
-				sub_peer->call_direction = INCOMING_CALL;
-				sub->channel_state = ONHOLD;
-			}
-		} else if (sub_peer->channel_state == ONHOLD) {
-			ast_log(LOG_NOTICE, "R on hold, line: %d action: %s\n",
-				p->line_id, sub->call_direction == INCOMING_CALL ? "Toggle" : "3way Conference");
-			if (sub->call_direction == OUTGOING_CALL) {
-				sub->channel_state = INCALL;
-				sub->conf_timer_id = ast_sched_add(sched, dtmf_wait_timer, setup_conference_call_cb, p);
-			} else if (sub->call_direction == INCOMING_CALL){
-				brcm_unmute_connection(sub_peer);
-				ast_queue_unhold(peer_owner);
-				sub_peer->channel_state = INCALL;
-
-				brcm_mute_connection(sub);
-				ast_queue_hold(owner, NULL);
-				sub->channel_state = ONHOLD;
-			}
-		}
-	} else if ((sub->channel_state == DIALING || sub->channel_state == OFFHOOK || sub->channel_state == RINGBACK) &&
-			sub_peer->channel_state != ONHOLD) {
-		ast_log(LOG_NOTICE, "R while offhook/dialing\n");
-		brcm_cancel_dialing_timeouts(p);
-		brcm_reset_dtmf_buffer(p);
-		p->hf_detected = 0;
-	}
-}
-/*
- * Perform actions for hook flash.
- * Preconditions: One subchannel should be in CALLWAITING or ONHOLD,
- * 		  One subchannel should be in INCALL.
- * 		  channel locks are held
- *		  brcm_pvt->lock is held
- */
-static void handle_hookflash(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner)
-{
-	struct brcm_pvt *p = sub->parent;
-	struct ast_bridge *bridge;
-	struct ast_bridge_channel *bridge_channel;
-
-	ast_log(LOG_NOTICE, "Hook Flash detected for phone line %d, p->dtmf_first = %d, flashSpec: %d\r\n", sub->parent->line_id, p->dtmf_first,
-		channel_config[p->line_id].flashSpec);
-
-	if (owner) {
-		bridge = ast_channel_internal_bridge(owner);
-	}
-	else if (peer_owner) {
-		bridge = ast_channel_internal_bridge(peer_owner);
-	} else {
-		p->hf_detected = 0;
-		return;
-	}
-
-	if (sub->channel_state == INCALL){
-		if (bridge && bridge->num_active > max_sessions_per_extension) {
-			ast_log(LOG_WARNING, "Max call per extension limit exceeded [%d/%d]\n", bridge->num_active, max_sessions_per_extension);
-			p->hf_detected = 0;
-			return;
-		}
-	} else if (sub->channel_state == CALLING && sub_peer->channel_state != ONHOLD){
-		//ignore the flash hook sending from endptmngr for DECT when got 183 from IVR system and interacting through DTMF
-		p->hf_detected = 0;
-		return;
-	}
-
-	if (p->dtmf_first < 0) {
-		ast_log(LOG_NOTICE, "sub->channel_state = %s, sub_peer->channel_state = %s\n", state2str(sub->channel_state), state2str(sub_peer->channel_state));
-		/* If current subchannel is in call and peer subchannel is idle, provide dialtone */
-		if (sub->channel_state == INCALL && (sub_peer->channel_state == ONHOOK || sub_peer->channel_state == CALLENDED)) {
-			ast_debug(2, "R while in call and idle peer subchannel\n");
-
-			brcm_cancel_dialing_timeouts(p);
-			brcm_reset_dtmf_buffer(p);
-			p->hf_detected = 0;
-
-			/* Put current call on hold */
-			if (owner) {
-				if(bridge){
-					AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
-						ast_indicate(bridge_channel->chan, AST_CONTROL_HOLD);
-					}
-				}
-
-				brcm_send_ubus_event("CALL_HOLD",p->line_id);
-				brcm_mute_connection(sub);
-				sub->channel_state = ONHOLD;
-				ast_queue_hold(owner, NULL);
-			}
-
-			/* Provide new line */
-			p->dialtone = DIALTONE_ON;
-			brcm_signal_dialtone(p);
-			sub_peer->channel_state = OFFHOOK;
-			sub_peer->call_direction = OUTGOING_CALL;
-		/* If offhook/dialing/calling and peer subchannel is on hold, switch call */
-		} else if ((sub->channel_state == DIALING ||
-				sub->channel_state == OFFHOOK ||
-				sub->channel_state == AWAITONHOOK ||
-				sub->channel_state == CALLING )
-				&& sub_peer->channel_state == ONHOLD) {
-
-			ast_debug(2, "R while offhook/dialing and peer subchannel on hold\n");
-
-			brcm_cancel_dialing_timeouts(p);
-			brcm_reset_dtmf_buffer(p);
-			p->hf_detected = 0;
-
-			if (sub->channel_state == OFFHOOK || sub->channel_state == AWAITONHOOK) {
-				brcm_stop_dialtone(p);
-			}
-			sub->channel_state = ONHOOK;
-
-			/* Hang up current */
-			if(owner) {
-				ast_queue_control(owner, AST_CONTROL_HANGUP);
-			}
-
-			/* Pick up old */
-			if (peer_owner) {
-				if(bridge){
-					AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
-						ast_indicate(bridge_channel->chan, AST_CONTROL_UNHOLD);
-						ast_log(LOG_NOTICE,"Pick up old unhold\n");
-					}
-				}
-				brcm_send_ubus_event("CALL_UNHOLD",p->line_id);
-				brcm_unmute_connection(sub_peer);
-				ast_queue_unhold(peer_owner);
-				sub_peer->channel_state = INCALL;
-			}
-		/* Switch back to old call (remote hung up) */
-		} else if ((sub->channel_state == ONHOOK || sub->channel_state == CALLENDED) && sub_peer->channel_state == ONHOLD) {
-			ast_debug(2, "R when idle and peer subchannel on hold\n");
-
-			brcm_cancel_dialing_timeouts(p);
-			p->hf_detected = 0;
-			if(sub->channel_state == RINGBACK) {
-				brcm_reset_dtmf_buffer(p);
-				brcm_stop_dialtone(p);
-			}
-
-			/* Hang up current */
-			if (owner) {
-				ast_queue_control(owner, AST_CONTROL_HANGUP);
-			}
-
-			/* Pick up old */
-			if (peer_owner) {
-				brcm_unmute_connection(sub_peer);
-				ast_queue_unhold(peer_owner);
-				brcm_send_ubus_event("CALL_UNHOLD",p->line_id);
-				sub_peer->channel_state = INCALL;
-			}
-		} else if (sub->channel_state == RINGBACK && sub_peer->channel_state == ONHOLD) {
-			ast_debug(4, "R during ringback\n");
-			sub->channel_state = INCALL;
-			sub->conf_timer_id = ast_sched_add(sched, dtmf_wait_timer, setup_conference_call_cb, p);
-		}
-
-		if (channel_config[p->line_id].flashSpec == FLASH_SPEC_UK)
-			handle_Rkey_uk(sub, sub_peer, owner, peer_owner);
-	}
-
-	if (p->dtmf_first > 0) {
-		if (channel_config[p->line_id].flashSpec == FLASH_SPEC_ETSI)
-			handle_Rnumber_etsi(sub, sub_peer, owner, peer_owner);
-		else
-			handle_Rnumber_uk(sub, sub_peer, owner, peer_owner);
-	}
-	brcm_reset_dtmf_buffer(p);
-}
-
-static void handle_dect_event(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner, enum LINE_EVENT event)
-{
-	struct brcm_pvt *p = sub->parent;
-
-	ast_log(LOG_NOTICE, "%s sub->channel_state = %d, sub_peer->channel_state = %d\n", __func__, sub->channel_state, sub_peer->channel_state);
-	if (event == EVENT_JOIN) {
-		ast_log(LOG_NOTICE, "Join detected for phone line %d\n", sub->parent->line_id);
-
-		// Start 3way call conference
-		if (sub->channel_state == INCALL && sub_peer->channel_state == ONHOLD)
-			sub->conf_timer_id = ast_sched_add(sched, dtmf_wait_timer, setup_conference_call_cb, p);
-	}
-	else if (event == EVENT_SWITCH) {
-		ast_log(LOG_NOTICE, "Switch detected for phone line %d\n", sub->parent->line_id);
-		// Toggle calls
-		if (sub->channel_state == INCALL && sub_peer->channel_state == ONHOLD) {
-			brcm_unmute_connection(sub_peer);
-			ast_queue_unhold(peer_owner);
-			sub_peer->channel_state = INCALL;
-
-			brcm_mute_connection(sub);
-			ast_queue_hold(owner, NULL);
-			sub->channel_state = ONHOLD;
-		}
-	}
-	else if (event == EVENT_RELEASE) {
-		ast_log(LOG_NOTICE, "EVENT_RELEASE detected for phone line %d\n", sub->parent->line_id);
-		if (sub->channel_state == INCALL && sub_peer->channel_state != CALLWAITING) {
-				ast_log(LOG_ERROR, "Hanging up call\n");
-				ast_queue_control(owner, AST_CONTROL_HANGUP);
-		} else if ((sub->channel_state == RINGBACK || sub->channel_state == CALLENDED) && sub_peer->channel_state == ONHOLD) {
-			endpt_signal(sub->parent->line_id, "ringback", "off", NULL);
-			ast_queue_control(owner, AST_CONTROL_HANGUP);
-			brcm_unmute_connection(sub_peer);
-			ast_queue_unhold(peer_owner);
-			sub_peer->channel_state = INCALL;
-		} else if (sub->channel_state == AWAITONHOOK && sub_peer->channel_state == ONHOLD) {
-			sub->channel_state = ONHOOK;
-			brcm_unmute_connection(sub_peer);
-			ast_queue_unhold(peer_owner);
-			sub_peer->channel_state = INCALL;
-		}
-	}
-	brcm_reset_dtmf_buffer(p);
-}
-
-static void handle_dtmf(enum LINE_EVENT event,
-		struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner)
-{
-	struct brcm_pvt *p;
-	const DTMF_CHARNAME_MAP *dtmfMap = dtmf_to_charname;
-	struct timeval tim;
-
-	/* Lookup event to find corresponding DTMF */
-	while (dtmfMap->event != event) {
-		dtmfMap++;
-		if (dtmfMap->event == EVENT_LAST) {
-			/* DTMF not found. Should not be reached. */
-			ast_log(LOG_WARNING, "Failed to handle DTMF. Event not found.\n");
-			return;
-		}
-	}
-
-	char dtmf_button = dtmfMap->c;
-	gettimeofday(&tim, NULL);
-	p = sub->parent;
-
-	if (p->dtmf_first < 0) {
-		p->dtmf_first = dtmf_button;
-		ast_debug(9,"Pressed DTMF %s\n", dtmfMap->name);
-		if (owner && brcm_should_relay_dtmf(sub)) {
-			// INCALL
-			send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_BEGIN);
-		}
-
-		/* Do not send AST_FRAME_DTMF_BEGIN to allow DSP-generated tone to pass through */
-	}
-	else if (p->dtmf_first == dtmf_button) {
-		ast_log(LOG_NOTICE,"Released DTMF %s\n", dtmfMap->name);
-		//ast_log(LOG_DTMF, "Detected DTMF %c, line %d\n", dtmfMap->c, sub->parent->line_id);
-
-		if (p->hf_detected) {
-			ast_debug(2, "DTMF after HF\n");
-			p->hf_detected = 0;
-			if (sub->channel_state == INCALL &&
-				(brcm_in_callwaiting(p) || brcm_in_onhold(p) || brcm_in_conference(p))) {
-				handle_hookflash(sub, sub_peer, owner, peer_owner);
-			} else {
-				/* HF while not in a call doesn't make sense */
-				ast_debug(2, "DTMF after HF while not in call. \
-						state: %d, \
-						callwaiting: %d, \
-						onhold: %d, \
-						conference: %d\n",
-					sub->channel_state,
-					brcm_in_callwaiting(p),
-					brcm_in_onhold(p),
-					brcm_in_conference(p));
-			}
-		} else {
-			//ast_debug(5,"DTMF %s in state %s.\n", dtmfMap->name, state2str(sub->channel_state));
-			p->dtmfbuf[p->dtmf_len] = dtmf_button;
-			p->dtmf_len++;
-			p->dtmfbuf[p->dtmf_len] = '\0';
-			p->dtmf_first = -1;
-			if (sub->channel_state == OFFHOOK) {
-				sub->channel_state = DIALING;
-				//ast_debug(5,"Set to state %s.\n", state2str(sub->channel_state));
-			}
-			else if (sub->channel_state != INCALL) {
-				struct ast_frame f = { 0, };
-				f.subclass.integer = dtmf_button;
-				f.src = "TELCHAN";
-				f.frametype = AST_FRAME_DTMF_END;
-
-				//ast_debug(5,"DTMF %s not in call.\n", dtmfMap->name);
-
-				if (owner) {
-					//ast_debug(5,"DTMF %s queuing frame.\n", dtmfMap->name);
-					ast_queue_frame(owner, &f);
-				}
-			} else {
-				if (owner) {
-					// INCALL
-					send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_END);
-				}
-			}
-		}
-	}
-	else {
-		p->dtmf_first = -1;
-	}
-}
-
-static void send_outgoing_dtmf(struct ast_channel *owner, char dtmf_button, int frametype) {
-	struct ast_frame fr;
-
-	if (!owner) return;
-
-	if (frametype != AST_FRAME_DTMF_BEGIN &&
-			frametype != AST_FRAME_DTMF_END) {
-		return;
-	}
-
-	if (ast_channel_state(owner) != AST_STATE_UP &&
-			ast_channel_state(owner) != AST_STATE_RING) {
-		return;
-	}
-
-	memset(&fr, 0, sizeof fr);
-	ast_debug(2, "Sending DTMF %c %s\n", dtmf_button, ast_channel_name(owner));
-	fr.src = brcm_tech.type;
-	fr.frametype = frametype;
-	fr.subclass.integer = dtmf_button;
-
-	ast_queue_frame(owner, &fr);
-}
-
-/* Handle audio packets from endptmngr. */
-static void audio_packet_handler(pe_packet_t *p) {
-	struct brcm_subchannel *sub;
-	int rtp_packet_type  = BRCM_UNKNOWN, drop_frame = 0;
-	struct ast_frame fr  = {0};
-	audio_packet_t *ap = (audio_packet_t *)p->data;
-	struct brcm_pvt *pvt;
-
-	fr.src = "TELCHAN";
-	rtp_packet_type = brcm_classify_rtp_packet(ap->rtp[1]);
-	pvt = brcm_get_pvt_from_lineid(iflist, ap->line);
-	sub = brcm_get_active_subchannel(pvt);
-	if (!pvt || !sub) {
-		ast_log(LOG_ERROR, "Failed to find subchannel for %s/%d/%d\n",
-			fr.src, ap->line, ap->cnx_id);
-		endpt_connection(ap->line, ap->cnx_id, "destroy");						// Request line close
-		return;
-	}
-
-	//pvt_lock(sub->parent, "brcm monitor packets");
-	//ast_mutex_lock(&sub->parent->lock);
-	struct ast_channel *owner = NULL;
-	if (sub->owner) {
-		ast_channel_ref(sub->owner);
-		owner = sub->owner;
-	}
-
-	/* We seem to get packets from DSP even if connection is muted (perhaps muting only affects packet callback).
-	 * Drop packets if subchannel is on hold. */
-	/* Handle rtp packet according to classification */
-	if (sub->channel_state != ONHOLD && rtp_packet_type == BRCM_AUDIO &&
-			(ap->rtp[0] & 0x80) && ap->rtp_size) {
-		fr.frametype = AST_FRAME_VOICE;
-		fr.offset = 0;
-		fr.data.ptr = ap->rtp + 12;
-		fr.datalen = ap->rtp_size - 12;
-
-		switch (ap->rtp[1]) {
-		case PCMU:
-			fr.subclass.format = ast_format_ulaw;
-			fr.samples = 160;
-			break;
-		case PCMA:
-			fr.subclass.format = ast_format_alaw;
-			fr.samples = 160;
-			break;
-		case G726:
-			fr.subclass.format = ast_format_g726;
-			fr.samples = 160; //for 20 ms frame size
-			break;
-		case G723:
-			fr.subclass.format = ast_format_g723;
-			fr.samples = 240;
-			break;
-		case G729:
-			fr.subclass.format = ast_format_g729;
-			fr.samples = 80; //for 10 ms frame size
-			break;
-		case G722:
-			fr.subclass.format = ast_format_g722;
-			fr.samples = 160;
-			break;
-		case CN:
-			fr.frametype = AST_FRAME_CNG;
-			fr.subclass.integer = ap->rtp[12];
-			break;
-		default:
-			ast_log(LOG_WARNING, "Unknown rtp codec id [%d], %d\n", ap->rtp[1], p->data[1]);
-			return;
-		}
-	} else if (rtp_packet_type == BRCM_RTCP_SR || rtp_packet_type == BRCM_RTCP_RR) {
-		fr.frametype = AST_FRAME_RTCP;
-		fr.data.ptr = ap->rtp;
-		fr.datalen = ap->rtp_size;
-		fr.subclass.integer = (rtp_packet_type == BRCM_RTCP_SR ? RTCP_SR : RTCP_RR);
-	} else {
-		//ast_debug(5, "Dropping RTP frame of type %d.\n", rtp_packet_type);
-		drop_frame=1;
-		//pvt_unlock(sub->parent);
-	}
-	//ast_mutex_unlock(&sub->parent->lock);
-	//pvt_unlock(sub->parent);
-
-	if (owner) {
-		if (!drop_frame && (ast_channel_state(owner) == AST_STATE_UP || ast_channel_state(owner) == AST_STATE_RING)) {
-			ast_queue_frame(owner, &fr);
-		}
-		ast_channel_unref(owner);
-	}
-}
-
-static void brcm_cancel_dialing_timeouts(struct brcm_pvt *p)
-{
-	//If we have interdigit timeout, cancel it
-	if (p->interdigit_timer_id > 0) {
-		p->interdigit_timer_id = ast_sched_del(sched, p->interdigit_timer_id);
-	}
-
-	//If we have a autodial timeout, cancel it
-	if (p->autodial_timer_id > 0) {
-		p->autodial_timer_id = ast_sched_del(sched, p->autodial_timer_id);
-	}
-
-	//If we have a dialtone timeout, cancel it
-	if (p->dialtone_timeout_timer_id > 0) {
-		p->dialtone_timeout_timer_id = ast_sched_del(sched, p->dialtone_timeout_timer_id);
-	}
-}
-
-static int brcm_should_relay_dtmf(const struct brcm_subchannel *sub)
-{
-	if (sub->channel_state == INCALL && sub->parent->hf_detected == 0) {
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Call a CLI command as specfied by cmd. The output is directed to a temp file and then
- * each line of output is passed to the check_output callback function. The data parameter
- * is also passed to the callback and can be used by the callback function to store any
- * data required to help process the output.
- *
- * This function returns 1 if the check_output callback function returns 1 otherwise it
- * will return 0 once all output has been processed.
- */
-static int call_cli_command(const char *cmd, int (*check_output)(const char *, const char *data), const char *data)
-{
-        int res = 0;
-        char template[] = "/tmp/ast-brcm-XXXXXX";     /* template for temporary file */
-        char line[160];
-        int fd_temp = -1;
-        FILE *fp = NULL;
-
-        if ((fd_temp = mkstemp(template)) < 0) {
-                ast_log(LOG_ERROR, "Failed to create temporary file for command \"%s\": %s\n",
-                                cmd, strerror(errno));
-                return res;
-        }
-
-        if (ast_cli_command(fd_temp, cmd) == 0) {
-                close(fd_temp);
-                fd_temp = -1;
-
-                fp = fopen(template, "r");
-                if (fp) {
-                        while (fgets(line, sizeof(line), fp) != NULL) {
-                                if ((*check_output)(line, data)) {
-                                        res = 1;
-                                        break;
-                                }
-                        }
-                }
-        } else {
-                ast_log(LOG_ERROR, "Execution CLI \"%s\" failed\n", cmd);
-        }
-
-        if (fd_temp >= 0)
-                close(fd_temp);
-        if (fp)
-                fclose(fp);
-        unlink(template);
-        return res;
-}
-
-static int check_voicemail_messages_waiting(const char *line, const char *data)
-{
-	return (strstr(line, "messages_waiting") != NULL && strstr(line, "yes") != NULL);
-}
-
-static int check_voicemail_dialtone(const char *line, const char *data)
-{
-	int ret = 1;
-
-	if (strstr(line, "mwi_dialtone_state") != NULL && strstr(line, "off") != NULL)
-		mwi_dialtone_state = DIALTONE_MWI_OFF;
-	else if (strstr(line, "mwi_dialtone_state") != NULL && strstr(line, "congestion") != NULL)
-		mwi_dialtone_state = DIALTONE_CONGESTION;
-	else if (strstr(line, "mwi_dialtone_state") != NULL && strstr(line, "special") != NULL)
-		mwi_dialtone_state = DIALTONE_SPECIAL_CONDITION;
-	else {
-		mwi_dialtone_state = DIALTONE_ON;
-		ret = 0;
-	}
-
-	return ret;
-}
-
-static int voicemail_messages_waiting(const char *sip_account)
-{
-	char cmd[32];
-	sprintf(cmd, "pjsip show endpoint %s", sip_account);
-	if (call_cli_command(cmd, &check_voicemail_messages_waiting, NULL))
-		return call_cli_command(cmd, &check_voicemail_dialtone, NULL);
-	else
-		return 0;
-}
-
-static int check_endpoint_cw_enabled(const char *line, const char *data)
-{
-	return (strstr(line, "call_waiting_enabled") != NULL && strstr(line, "true") != NULL);
-
-}
-
-static int check_endpoint_state_in_use(const char *line, const char *data)
-{
-	return (strstr(line, "Endpoint:") != NULL && strstr(line, "In use") != NULL);
-
-}
-
-static int is_call_waiting_enabled(const char *sip_account)
-{
-	char cmd[32];
-	// do not check pjsip endpoint configuration if it is internal call
-	if (strcmp(sip_account, "local_extensions") == 0)
-		return 0;
-	sprintf(cmd, "pjsip show endpoint %s", sip_account);
-	return call_cli_command(cmd, &check_endpoint_cw_enabled, NULL);
-}
-static int has_call_in_sip_client(const char *sip_account)
-{
-	char cmd[32];
-	// do not check pjsip endpoint configuration if it is internal call
-	if (strcmp(sip_account, "local_extensions") == 0)
-		return 0;
-	sprintf(cmd, "pjsip show endpoint %s", sip_account);
-	return call_cli_command(cmd, &check_endpoint_state_in_use, NULL);
-}
-
-static int check_is_sip_account_registered(const char *line, const char *sip_account)
-{
-	/* The example output of the command is shown below.
-	 * Some extra spaces are removed since the line is too long.
-	 * sip0:5060 N 1313@10.0.2. 285 Registered Mon, 17 Jun 2019 17:12:58 */
-	return ((strstr(line, sip_account) != NULL) && (strstr(line, "Registered") != NULL));
-}
-
-static int is_sip_account_registered(const char *sip_account)
-{
-	const char *cmd = "pjsip show registrations";
-	return call_cli_command(cmd, &check_is_sip_account_registered, sip_account);
-}
-
-static int check_endpoint_status(const char *line, const char *sip_account)
-{
-	int ret = 1;
-
-	if((strstr(line, sip_account) != NULL) && (strstr(line, "Not in use") != NULL)) {
-		strcpy(lineCallStatus, "Idle\0");
-	} else if((strstr(line, sip_account) != NULL) && (strstr(line, "In use") != NULL)) {
-		strcpy(lineCallStatus, "Connected\0");
-	} else if((strstr(line, sip_account) != NULL) && (strstr(line, "Busy") != NULL)) {
-		strcpy(lineCallStatus, "Disconnected\0");
-	} else if((strstr(line, sip_account) != NULL) && (strstr(line, "Ringing") != NULL)) {
-		strcpy(lineCallStatus, "Dialing\0");
-	} else if((strstr(line, sip_account) != NULL) && (strstr(line, "Ring+Inuse") != NULL)) {
-		strcpy(lineCallStatus, "Dialing\0");
-	} else if((strstr(line, sip_account) != NULL) && (strstr(line, "On Hold") != NULL)) {
-		strcpy(lineCallStatus, "Connected\0");
-	} else if((strstr(line, sip_account) != NULL) && (strstr(line, "Alerting") != NULL)) {
-		strcpy(lineCallStatus, "Alerting\0");
-	} else {
-		strcpy(lineCallStatus, "Idle\0");
-		ret = 0;
-	}
-	return ret;
-}
-
-static int getLineState(const char *sip_account, char *lineCallStatus)
-{
-	char cmd[32];
-	sprintf(cmd, "pjsip show endpoint %s", sip_account);
-
-	return call_cli_command(cmd, &check_endpoint_status, sip_account);
-}
-
-static void brcm_process_event(struct endpt_event *ev)
-{
-	struct brcm_pvt *p = NULL;
-	struct brcm_subchannel *sub = NULL;
-	struct brcm_subchannel *sub_peer = NULL;
-	struct ast_channel *owner = NULL;
-	struct ast_channel *peer_owner = NULL;
-
-	ast_debug(3, "Received event %s from line %d\n", ev->name, ev->line);
-
-	// Ignore events when the telline is not enabled
-	if (!channel_config[ev->line].enabled) {
-		ast_debug(3, "Line %d disabled, ignore event %s!\n", ev->line, ev->name);
-		return;
-	}
-
-	p = brcm_get_pvt_from_lineid(iflist, ev->line);
-	if (!p) {
-		ast_debug(3, "No pvt with the correct line_id %d found!\n", ev->line);
-		return;
-	}
-
-	pvt_lock(p, "brcm monitor events");
-	sub = brcm_get_active_subchannel(p);
-	sub_peer = brcm_subchannel_get_peer(sub);
-	if (!sub || !sub_peer) {
-		ast_debug(3, "sub-channels are not found\n");
-		pvt_unlock(p);
-		return;
-	}
-	if (sub->owner) {
-		ast_channel_ref(sub->owner);
-		owner = sub->owner;
-	}
-	if (sub_peer->owner) {
-		ast_channel_ref(sub_peer->owner);
-		peer_owner = sub_peer->owner;
-	}
-	pvt_unlock(p);
-
-	ast_debug(3, "call state:%s, peer call state:%s\n", state2str(sub->channel_state),
-		state2str(sub_peer->channel_state));
-
-	/* Get locks in correct order */
-	if (owner && peer_owner) {
-		if (owner < peer_owner) {
-			ast_channel_lock(owner);
-			ast_channel_lock(peer_owner);
-		} else {
-			ast_channel_lock(peer_owner);
-			ast_channel_lock(owner);
-		}
-	} else if (owner) {
-		ast_channel_lock(owner);
-	} else if (peer_owner) {
-		ast_channel_lock(peer_owner);
-	}
-
-	pvt_lock(p, "brcm monitor events");
-	if (sub) {
-		switch (ev->event) {
-		case EVENT_OFFHOOK: {
-			if (!strlen(p->extensionCallStatus) || sub->channel_state == ONHOOK)
-				strncpy(p->extensionCallStatus, "Dialing", CALL_STATUS_MAX_LEN);
-			else if (sub->channel_state == RINGING)
-				strncpy(p->extensionCallStatus, "Connected", CALL_STATUS_MAX_LEN);
-
-			/* Reset the dtmf buffer */
-			memset(p->dtmfbuf, 0, sizeof(p->dtmfbuf));
-			p->dtmf_len          = 0;
-			p->dtmf_first        = -1;
-			p->dtmfbuf[p->dtmf_len] = '\0';
-			sub->channel_state = OFFHOOK;
-
-			if (owner) {
-				if (!sub->connection_init) {
-					ast_debug(9, "create_connection()\n");
-					brcm_stop_dialtone(p);
-					brcm_create_connection(sub);
-				}
-
-				if (sub->cw_timer_id > -1) {
-					/* Picking up during reminder ringing for call waiting */
-					if (ast_sched_del(sched, sub->cw_timer_id) < 0)
-						ast_debug(3, "Error deleting timer\n");
-					sub->cw_timer_id = -1;
-				}
-
-				if (sub->cwBeep_timer_id > -1) {
-					/* Picking up during reminder ringing for call waiting */
-					if (ast_sched_del(sched, sub->cwBeep_timer_id) < 0)
-						ast_debug(3, "Error deleting timer\n");
-					sub->cwBeep_timer_id = -1;
-				}
-
-				sub->channel_state = INCALL;
-				ast_queue_control(owner, AST_CONTROL_ANSWER);
-				brcm_send_ubus_event("ANSWERED_CALL",p->line_id);
-			} else if (sub_peer->channel_state == ONHOLD) {
-				/* Picking up during reminder ringing for call on hold */
-				if (ast_sched_del(sched, sub_peer->onhold_hangup_timer_id) < 0) {
-					ast_debug(3, "Error deleting timer\n");
-				}
-				sub_peer->onhold_hangup_timer_id = -1;
-				sub->channel_state = CALLENDED;
-				sub_peer->channel_state = INCALL;
-				ast_queue_control(peer_owner, AST_CONTROL_ANSWER);
-				brcm_unmute_connection(sub_peer);
-				endpt_connection(sub_peer->parent->line_id, sub_peer->call_id, "create");
-				ast_queue_unhold(peer_owner);
-				brcm_send_ubus_event("CALL_UNHOLD", p->line_id);
-			} else if (sub->channel_state == OFFHOOK) {
-				/* EVENT_OFFHOOK changed endpoint state to OFFHOOK, apply dialtone */
-				if ( p->context[0] != '\0' && is_sip_account_registered(p->context)) {
-					ast_debug(9, "Resetting dial tones.\n");
-					channel_settings *s = &channel_config[p->line_id];
-					p->dialtone = voicemail_messages_waiting(p->context) ? mwi_dialtone_state : s->mwi_enabled ? DIALTONE_SPECIAL_CONDITION: DIALTONE_ON;
-					brcm_signal_dialtone(p);
-					brcm_send_ubus_event("DIALTONE_ON", p->line_id);
-
-					if (strlen(s->autodial_ext)) {
-						/* Schedule autodial timeout if autodial extension is set */
-						p->autodial_timer_id = ast_sched_add(sched, s->autodial_timeoutmsec, handle_autodial_timeout, p);
-					} else {
-						/* No autodial, schedule dialtone timeout */
-						ast_verbose("Scheduling dialtone timeout in %dms\n", s->dialtone_timeoutmsec);
-						p->dialtone_timeout_timer_id = ast_sched_add(sched, s->dialtone_timeoutmsec, handle_dialtone_timeout, p);
-					}
-				} else {
-					ast_debug(9, "OFFHOOK but SIP account not registered\n");
-				}
-			}
-			break;
-		}
-		case EVENT_ONHOOK: {
-			strncpy(p->extensionCallStatus, "Idle", CALL_STATUS_MAX_LEN);
-			if (sub->channel_state == OFFHOOK || sub->channel_state == AWAITONHOOK) {
-				/* Received EVENT_ONHOOK in state OFFHOOK/AWAITONHOOK, stop dial/congestion tone */
-				brcm_stop_dialtone(p);
-			} else if (sub->channel_state == RINGBACK) {
-				/* Outgoing unanswered call - rtp stats need to be collected */
-				brcm_getRtpStats(owner);
-			}
-
-			sub->channel_state = ONHOOK;
-			brcm_cancel_dialing_timeouts(p);
-			p->hf_detected = 0;
-
-			if (sub_peer->channel_state  == CALLENDED)
-				sub_peer->channel_state = ONHOOK;
-
-			/* Reset the dtmf buffer */
-			memset(p->dtmfbuf, 0, sizeof(p->dtmfbuf));
-			p->dtmf_len          = 0;
-			p->dtmf_first        = -1;
-			p->dtmfbuf[p->dtmf_len] = '\0';
-
-			if (owner) {
-				ast_queue_control(owner, AST_CONTROL_HANGUP);
-			}
-
-			if (sub_peer->channel_state == CALLWAITING) {
-				/* Remind user of waiting call */
-				sub_peer->channel_state = RINGING;
-				p->tech->signal_ringing(p);
-				brcm_send_ubus_event("RINGING",p->line_id);
-			} else if (sub_peer->channel_state == ONHOLD) {
-				/* Remind user of call on hold */
-				sub_peer->onhold_hangup_timer_id = ast_sched_add(sched, onholdhanguptimeout * 1000, onholdhanguptimeout_cb, sub_peer);
-				ast_debug(2, "Forgotten call on hold for %s!\n", ast_channel_name(peer_owner));
-				endpt_connection(sub_peer->parent->line_id, sub_peer->call_id, "destroy");
-				usleep(500000);
-				p->tech->signal_ringing_callerid_pending(p);
-				p->tech->signal_callerid(sub_peer->owner, sub_peer);
-				sub->channel_state = RINGING;
-				ast_queue_control(peer_owner, AST_CONTROL_RINGING);
-				brcm_send_ubus_event("RINGING",p->line_id);
-			} else if (peer_owner && sub_peer->channel_state != TRANSFERING) {
-				/* Hangup peer subchannels in call or on hold */
-				ast_debug(2, "Hanging up call (not transfering)\n");
-				ast_queue_control(peer_owner, AST_CONTROL_HANGUP);
-			}
-			break;
-		}
-		case EVENT_DTMF0:
-		case EVENT_DTMF1:
-		case EVENT_DTMF2:
-		case EVENT_DTMF3:
-		case EVENT_DTMF4:
-		case EVENT_DTMF5:
-		case EVENT_DTMF6:
-		case EVENT_DTMF7:
-		case EVENT_DTMF8:
-		case EVENT_DTMF9:
-		case EVENT_DTMFA:
-		case EVENT_DTMFB:
-		case EVENT_DTMFC:
-		case EVENT_DTMFD:
-		case EVENT_DTMFS:
-		case EVENT_DTMFH:
-			{
-				brcm_cancel_dialing_timeouts(p);
-
-				unsigned int old_state = sub->channel_state;
-				handle_dtmf(ev->event, sub, sub_peer, owner, peer_owner);
-				if (sub->channel_state == DIALING && old_state != sub->channel_state) {
-					/* DTMF event took channel state to DIALING. Stop dial tone. */
-					ast_debug(2, "Dialing. Stop dialtone.\n");
-					brcm_stop_dialtone(p);
-				}
-
-				if (sub->channel_state == DIALING) {
-					ast_debug(2, "Handle DTMF calling\n");
-					handle_dtmf_calling(sub);
-				}
-				break;
-			}
-
-		case EVENT_FLASH:
-			p->hf_detected = 1;
-			handle_hookflash(sub, sub_peer, owner, peer_owner);
-			break;
-
-		case EVENT_CALL_REJECT:
-			if (sub->channel_state == RINGING || (sub->channel_state == INCALL && sub_peer->channel_state == CALLWAITING)) {
-				const char *linkedid = ast_channel_linkedid(owner);
-				const char *peer_linkedid;
-				struct brcm_pvt *pvt = iflist;
-				int i;
-
-				if (peer_owner)
-					peer_linkedid = ast_channel_linkedid(peer_owner);
-
-				/* Release all requested channels for the same incoming call when one channel rejects, e.g. from DECT handset */
-				while (pvt) {
-					pvt_lock(pvt, "lock pvt for call reject");
-
-					for (i = 0; i < NUM_SUBCHANNELS; i++) {
-						struct brcm_subchannel *sc = pvt->sub[i];
-						if ((sc->channel_state == RINGING || sc->channel_state == CALLWAITING) && sc->owner) {
-							const char *link = ast_channel_linkedid(sc->owner);
-
-							if (sub->channel_state == RINGING && (link == linkedid || strcmp(link, linkedid) == 0)) {
-								ast_debug(2, "Hang up the unanswered call on channel %s since %s has rejected\n",
-										ast_channel_name(sc->owner), ast_channel_name(owner));
-
-								ast_channel_hangupcause_set(sc->owner, AST_CAUSE_CALL_REJECTED);
-								ast_queue_control(sc->owner, AST_CONTROL_HANGUP);
-							} else if (sub->channel_state == INCALL && (link == peer_linkedid || strcmp(link, peer_linkedid) == 0)) {
-								ast_debug(2, "Hang up the unanswered call on channel %s since %s has rejected\n",
-										ast_channel_name(sc->owner), ast_channel_name(peer_owner));
-
-								ast_channel_hangupcause_set(sc->owner, AST_CAUSE_CALL_REJECTED);
-								ast_queue_control(sc->owner, AST_CONTROL_HANGUP);
-							}
-						}
-					}
-
-					pvt_unlock(pvt);
-					pvt = brcm_get_next_pvt(pvt);
-				}
-
-				brcm_send_ubus_event("CALL_REJECTED", ev->line);
-			} else if (sub->channel_state == CALLENDED && owner) {
-					ast_queue_control(owner, AST_CONTROL_HANGUP);
-			}
-			break;
-		case EVENT_DECT_UNAVAILABLE:
-			ast_channel_hangupcause_set(owner, AST_CAUSE_USER_BUSY);
-			ast_queue_control(owner, AST_CONTROL_BUSY);
-		case EVENT_SWITCH:
-		case EVENT_JOIN:
-		case EVENT_RELEASE:
-			ast_debug(1, "EVENT %d from dect received\n", ev->event);
-			handle_dect_event(sub, sub_peer, owner, peer_owner, ev->event);
-			break;
-		default:
-			ast_debug(1, "Ignore event %s\n", ev->name);
-			break;
-		}
-	}
-	pvt_unlock(p);
-
-	if (owner) {
-		ast_channel_unlock(owner);
-		ast_channel_unref(owner);
-	}
-	if (peer_owner) {
-		ast_channel_unlock(peer_owner);
-		ast_channel_unref(peer_owner);
-	}
-}
-
-/* Load settings for each line */
-static void brcm_initialize_pvt(struct brcm_pvt *p)
-{
-	channel_settings *s = &channel_config[p->line_id];
-
-	ast_copy_string(p->language, s->language, sizeof(p->language));
-	ast_copy_string(p->context, s->context, sizeof(p->context));
-	ast_copy_string(p->context_direct, s->context_direct, sizeof(p->context_direct));
-	ast_copy_string(p->cid_num, s->cid_num, sizeof(p->cid_num));
-	ast_copy_string(p->cid_name, s->cid_name, sizeof(p->cid_name));
-}
-
-static struct brcm_pvt *brcm_allocate_pvt(void)
-{
-	/* Make a brcm_pvt structure for this interface */
-	struct brcm_pvt *tmp;
-
-	tmp = ast_calloc(1, sizeof(*tmp));
-	if (tmp) {
-		struct brcm_subchannel *sub;
-		int i;
-
-		for (i=0; i<NUM_SUBCHANNELS; i++) {
-			sub = ast_calloc(1, sizeof(*sub));
-			if (sub) {
-				sub->id = i;
-				sub->call_id = CALLID_INVALID;
-				sub->owner = NULL;
-				sub->connection_id = -1;
-				sub->connection_init = 0;
-				sub->channel_state = ONHOOK;
-				sub->time_stamp = 0;
-				sub->ssrc = 0;
-				sub->codec = -1;
-				sub->parent = tmp;
-				sub->cw_timer_id = -1;
-				sub->cwBeep_timer_id = -1;
-				sub->conf_timer_id = -1;
-				sub->r4_hangup_timer_id = -1;
-				sub->onhold_hangup_timer_id = -1;
-				sub->period = 20;												// 20 ms
-				sub->conference_initiator = 0;
-				tmp->sub[i] = sub;
-				sub->jitter_count = 0;
-				sub->farEndInterrivalJitter = 0;
-				sub->blind_xfer_target[0] = '\0';
-				ast_debug(2, "subchannel created\n");
-			} else {
-				ast_log(LOG_ERROR, "no subchannel created\n");
-			}
-		}
-		tmp->line_id = -1;
-		tmp->dtmf_len = 0;
-		tmp->dtmf_first = -1;
-		tmp->lastformat = NULL;
-		tmp->lastinput = NULL;
-		memset(tmp->ext, 0, sizeof(tmp->ext));
-		tmp->next = NULL;
-		tmp->dialtone = DIALTONE_UNKNOWN;
-		tmp->interdigit_timer_id = -1;
-		tmp->autodial_timer_id = -1;
-		ast_mutex_init(&tmp->lock);
-		tmp->tech = &fxs_tech;
-	}
-	return tmp;
-}
-
-
-static void brcm_create_pvts(struct brcm_pvt *p, int mode) {
-	int i;
-	struct brcm_pvt *tmp = iflist;
-	struct brcm_pvt *tmp_next;
-
-	for (i=0; i<num_endpoints ; i++) {
-		tmp_next = brcm_allocate_pvt();
-		if (tmp == NULL) {
-			iflist = tmp_next; //First loop round, set iflist to point at first pvt
-			tmp    = tmp_next;
-			tmp->next = NULL;
-		} else {
-			tmp->next = tmp_next;
-			tmp_next->next = NULL;
-			tmp = tmp_next;
-		}
-	}
-}
-
-static void brcm_assign_line_id(struct brcm_pvt *p)
-{
-	struct brcm_pvt *tmp = p;
-	int i;
-	/* Assign line_id's */
-	for (i=0 ; i<num_endpoints ; i++) {
-		tmp->line_id = i;
-		brcm_initialize_pvt(tmp);
-		int j;
-		for (j=0; j<NUM_SUBCHANNELS; j++) {
-			tmp->sub[j]->channel_state = ONHOOK;
-		}
-		tmp = tmp->next;
-	}
-}
-
-static int brcm_in_dialing(const struct brcm_pvt *p)
-{
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		if (p->sub[i]->channel_state == DIALING) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int brcm_in_ringback(const struct brcm_pvt *p)
-{
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		if (p->sub[i]->channel_state == RINGBACK) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int brcm_in_call(const struct brcm_pvt *p)
-{
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		if (p->sub[i]->channel_state == INCALL) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int brcm_in_callwaiting(const struct brcm_pvt *p)
-{
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		if (p->sub[i]->channel_state == CALLWAITING) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int brcm_in_transferring(const struct brcm_pvt *p)
-{
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		if (p->sub[i]->channel_state == TRANSFERING) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int brcm_in_onhold(const struct brcm_pvt *p)
-{
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		if (p->sub[i]->channel_state == ONHOLD) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int brcm_in_conference(const struct brcm_pvt *p)
-{
-	return (p->sub[0]->channel_state == INCALL && 
-		p->sub[1]->channel_state == INCALL) ||
-		p->sub[0]->conference_initiator ||
-		p->sub[1]->conference_initiator;
-}
-
-/*
- * Return idle subchannel
- */
-struct brcm_subchannel *brcm_get_idle_subchannel(const struct brcm_pvt *p)
-{
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		if (p->sub[i]->channel_state == ONHOOK || p->sub[i]->channel_state == CALLENDED) {
-			return p->sub[i];
-		}
-	}
-	return NULL;
-}
-
-static struct ast_channel *brcm_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *dest, int *cause)
-{
-	struct brcm_pvt *p;
-	struct brcm_subchannel *sub = NULL;
-	struct ast_channel *tmp = NULL;
-	struct ast_str * buf = ast_str_create(256);
-	int line_id = -1;
-
-	ast_debug(3, "requestor=%p(%s), dest=[%s], type=[%s]\n", requestor, requestor ? ast_channel_name(requestor) : "",
-			dest ? dest : "", type ? type : "");
-
-	ast_format_cap_get_names(cap, &buf);
-	ast_debug(1, "Asked to create a channel with formats: %s\n", ast_str_buffer(buf));
-
-	/* Search for an unowned channel */
-	if (ast_mutex_lock(&iflock)) {
-		ast_log(LOG_ERROR, "Unable to lock interface list???\n");
-		return NULL;
-	}
-
-
-	/* Get line id */
-	line_id = atoi((char*)dest);
-	//ast_debug(1, "brcm_request = %s, line_id=%d, format %x\n", (char*) data, line_id, (unsigned int) format);
-
-	/* Map id to the correct pvt */
-	p = brcm_get_pvt_from_lineid(iflist, line_id);
-
-	/* If the id doesn't exist (p==NULL) use 0 as default */
-	if (!p) {
-		ast_log(LOG_ERROR, "Port id %s not found using default 0 instead.\n", (char*) dest);
-		p = iflist;
-	}
-
-	pvt_lock(p, "brcm request");
-	//ast_mutex_lock(&p->lock);
-
-	sub = brcm_get_idle_subchannel(p);
-
-	/* Check that the request has an allowed format */
-	if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
-		struct ast_str *codec_buf = ast_str_alloca(64);
-		ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
-	} else if (sub) {
-		sub->channel_state = ALLOCATED;
-		sub->connection_id = ast_atomic_fetchadd_int((int *)&current_connection_id, +1);
-		tmp = brcm_new(sub, AST_STATE_DOWN, sub->parent->ext, sub->parent->context, assignedids, requestor ? requestor : NULL, cap);
-	} else {
-		*cause = AST_CAUSE_BUSY;
-		ast_log(LOG_NOTICE, "Idle subchannel not found\n");
-	}
-
-	pvt_unlock(p);
-	ast_mutex_unlock(&iflock);
-
-	if (tmp)
-		ast_debug(3, "Created a new ast_channel %s, uniqid:%s, linkedid:%s\n", ast_channel_name(tmp), ast_channel_uniqueid(tmp),
-			ast_channel_linkedid(tmp));
-	return tmp;
-}
-
-
-static void brcm_lock_pvts(void)
-{
-	struct brcm_pvt *p = iflist;
-	while(p) {
-		pvt_lock(p, "brcm lock pvts");
-		//ast_mutex_lock(&p->lock);
-		p = brcm_get_next_pvt(p);
-	}
-}
-
-static void brcm_unlock_pvts(void)
-{
-	struct brcm_pvt *p = iflist;
-	while(p) {
-		pvt_unlock(p);
-		//ast_mutex_unlock(&p->lock);
-		p = brcm_get_next_pvt(p);
-	}
-}
-
-static void brcm_show_subchannels(struct ast_cli_args *a, struct brcm_pvt *p)
-{
-	struct brcm_subchannel *sub;
-
-	/* Output status for sub channels */
-	int i;
-	for (i=0; i<NUM_SUBCHANNELS; i++) {
-		sub = p->sub[i];
-		ast_cli(a->fd, "Subchannel: %d\n", sub->id);
-		ast_cli(a->fd, "  Connection id       : %d\n", sub->connection_id);
-
-		ast_cli(a->fd, "  Owner               : %p\n", sub->owner);
-		ast_cli(a->fd, "  Channel state       : %s\n", state2str(sub->channel_state));
-		ast_cli(a->fd, "  Connection init     : %d\n", sub->connection_init);
-		ast_cli(a->fd, "  Codec used          : %s\n", brcm_get_codec_string(sub->codec));
-		ast_cli(a->fd, "  RTP SSRC            : %d\n", sub->ssrc);
-		ast_cli(a->fd, "  RTP timestamp       : %d\n", sub->time_stamp);
-		ast_cli(a->fd, "  CW Timer id         : %d\n", sub->cw_timer_id);
-		ast_cli(a->fd, "  CW Beep Timer id    : %d\n", sub->cwBeep_timer_id);
-		ast_cli(a->fd, "  R4 Hangup Timer id  : %d\n", sub->r4_hangup_timer_id);
-		ast_cli(a->fd, "  Conference initiator: %d\n", sub->conference_initiator);
-		ast_cli(a->fd, "  Onhold Hangup Timer id: %d\n", sub->onhold_hangup_timer_id);
-	}
-}
-
-static void brcm_show_pvts(struct ast_cli_args *a)
-{
-	struct brcm_pvt *p = iflist;
-	int i = 0;
-
-	while(p) {
-		pvt_lock(p, "brcm show pvts");
-		//ast_mutex_lock(&p->lock);
-		ast_cli(a->fd, "\nPvt nr: %d\n",i);
-		ast_cli(a->fd, "Line id             : %d\n", p->line_id);
-		ast_cli(a->fd, "Pvt next ptr        : 0x%x\n", (unsigned int) p->next);
-		ast_cli(a->fd, "DTMF buffer         : %s\n", p->dtmfbuf);
-		ast_cli(a->fd, "Default context     : %s\n", p->context);
-		ast_cli(a->fd, "Direct context      : %s\n", p->context_direct);
-		channel_settings* s = &channel_config[p->line_id];
-
-		ast_cli(a->fd, "Ringsignal          : %s\n", s->ringsignal ? "on" : "off");
-		ast_cli(a->fd, "Dialout msecs       : %d\n", s->timeoutmsec);
-		ast_cli(a->fd, "Autodial extension  : %s\n", s->autodial_ext);
-		ast_cli(a->fd, "Autodial msecs      : %d\n", s->autodial_timeoutmsec);
-		ast_cli(a->fd, "Dialt. timeout msecs: %d\n", s->dialtone_timeoutmsec);
-
-		ast_cli(a->fd, "Ast JitterBuf impl  : %s\n", global_jbconf.impl);
-		ast_cli(a->fd, "Ast JitterBuf max   : %ld\n", global_jbconf.max_size);
-		ast_cli(a->fd, "Do not disturb      : %s\n", s->do_not_disturb ? "on" : "off");
-		ast_cli(a->fd, "CLIR                : %s\n", s->anonymouscallenable ? "on" : "off");
-
-		ast_cli(a->fd, "Dialtone            : ");
-		const DIALTONE_MAP *dialtone = dialtone_map;
-		while (dialtone->state != DIALTONE_LAST) {
-			if (dialtone->state == p->dialtone) {
-				break;
-			}
-			dialtone++;
-		}
-		ast_cli(a->fd, "%s\n", dialtone->str);
-		ast_cli(a->fd, "Dialtone Timer id   : %d\n", p->dialtone_timeout_timer_id);
-
-		/* Print status for subchannels */
-		brcm_show_subchannels(a, p);
-
-		ast_cli(a->fd, "\n");
-
-		i++;
-		pvt_unlock(p);
-		//ast_mutex_unlock(&p->lock);
-		p = brcm_get_next_pvt(p);
-	}
-}
-
-/*! \brief CLI for showing brcm status.
- * This is a new-style CLI handler so a single function contains
- * the prototype for the function, the 'generator' to produce multiple
- * entries in case it is required, and the actual handler for the command.
- */
-
-static char *brcm_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	char buffer[AST_MAX_EXTENSION];
-
-	if (cmd == CLI_INIT) {
-		e->command = "telephony show status";
-		e->usage =
-			"Usage: telephony show status\n"
-			"       Shows the current chan_brcm status.\n";
-		return NULL;
-	} else if (cmd == CLI_GENERATE)
-		return NULL;
-
-	/* print chan brcm status information */
-	ast_cli(a->fd, "Channel version: %s\n\n", CHANNEL_VERSION);
-	ast_cli(a->fd, "Number of endpoints: %d\n", num_endpoints);
-	ast_cli(a->fd, "FAC list      : %s\n", feature_access_code_string(buffer, AST_MAX_EXTENSION));
-
-	/* print status for individual pvts */
-	brcm_show_pvts(a);
-
-	return CLI_SUCCESS;
-}
-
-/*! \brief CLI for showing brcm dialtone status. */
-static char *brcm_show_dialtone_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	if (cmd == CLI_INIT) {
-		e->command = "brcm show dialtone status";
-		e->usage =
-			"Usage: brcm show dialtone status\n"
-			"       Shows the current chan_brcm dialtone status.\n";
-		return NULL;
-	}
-	else if (cmd == CLI_GENERATE) {
-		return NULL;
-	}
-
-	struct brcm_pvt *p = iflist;
-	int i = 0;
-
-	ast_cli(a->fd, "Pvt nr\tDialtone\n\n");
-	while(p) {
-		const DIALTONE_MAP *dialtone = dialtone_map;
-		while (dialtone->state != DIALTONE_LAST) {
-			if (dialtone->state == p->dialtone) {
-				break;
-			}
-			dialtone++;
-		}
-		ast_cli(a->fd, "%d\t%s\n", i, dialtone->str);
-
-		i++;
-		p = brcm_get_next_pvt(p);
-	}
-
-	return CLI_SUCCESS;
-}
-
-/*! \brief CLI for reloading brcm config. */
-static char *brcm_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	struct ast_config *cfg = NULL;
-	if (cmd == CLI_INIT) {
-		e->command = "telephony reload";
-		e->usage =
-			"Usage: telephony reload\n"
-			"       Reload chan_brcm configuration.\n";
-		return NULL;
-	} else if (cmd == CLI_GENERATE) {
-		return NULL;
-	}
-
-	ast_mutex_lock(&iflock);
-
-	/* Acquire locks for all pvt:s to prevent nasty things from happening */
-	brcm_lock_pvts();
-
-	feature_access_code_clear();
-
-	/* Reload configuration */
-        if (load_common_settings(&cfg)) {
-		brcm_unlock_pvts();
-		ast_mutex_unlock(&iflock);
-		return CLI_FAILURE;
-	}
-
-	load_settings(cfg);
-	struct brcm_pvt *p = iflist;
-	while(p) {
-		brcm_initialize_pvt(p);
-		p = brcm_get_next_pvt(p);
-	}
-
-	brcm_unlock_pvts();
-	ast_mutex_unlock(&iflock);
-
-	ast_verbose("TELCHAN reload done\n");
-
-	return CLI_SUCCESS;
-}
-
-static char *brcm_set_parameters_on_off(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	int on_off = 0;
-
-	if (cmd == CLI_INIT) {
-		e->command = "brcm set {echocancel|ringsignal} {on|off}";
-		e->usage =
-			"Usage: brcm set {echocancel|ringsignal} {on|off} PvtNr\n"
-			"       echocancel, echocancel mode.\n"
-			"       ringsignal, ring signal mode.\n"
-			"       PvtNr, the Pvt to modify.\n";
-		return NULL;
-	} else if (cmd == CLI_GENERATE) {
-		return NULL;
-	}
-
-	if (a->argc <= 4) {
-		return CLI_SHOWUSAGE; //Too few arguments
-	}
-
-	int pvt_id = atoi(a->argv[4]);
-	if (pvt_id >= num_endpoints || pvt_id < 0) {
-		return CLI_SHOWUSAGE;
-	}
-	channel_settings *s = &channel_config[pvt_id];
-
-	if (!strcasecmp(a->argv[3], "on")) {
-		on_off = 1;
-	} else {
-		on_off = 0;
-	}
-
-	if (!strcasecmp(a->argv[2], "ringsignal")) {
-		s->ringsignal = on_off;
-	}
-	return CLI_SUCCESS;
-}
-
-static char *brcm_set_parameters_value(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	if (cmd == CLI_INIT) {
-		e->command = "brcm set dialout_msecs";
-		e->usage =
-			"Usage: brcm set dialout_msecs 4000 PvtNr\n"
-			"       dialout_msecs, dialout delay in msecs.\n"
-			"       PvtNr, the Pvt to modify.\n";
-		return NULL;
-	} else if (cmd == CLI_GENERATE)
-		return NULL;
-
-	if (a->argc <= 4)
-		return CLI_SHOWUSAGE;
-
-	int pvt_id = atoi(a->argv[4]);
-    if (pvt_id >= num_endpoints || pvt_id < 0) {
-        return CLI_SHOWUSAGE;
-    }
-    channel_settings *s = &channel_config[pvt_id];
-
-	s->timeoutmsec = atoi(a->argv[3]);
-
-	return CLI_SUCCESS;
-}
-
-static char *brcm_set_autodial_extension(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-	struct brcm_pvt *p;
-
-	if (cmd == CLI_INIT) {
-		e->command = "brcm set autodial";
-		e->usage =
-			"Usage: brcm set autodial 0 1234\n"
-			"       brcm set autodial 0 \"\"\n"
-			"       autodial, extension to autodial on of hook.\n";
-		return NULL;
-	} else if (cmd == CLI_GENERATE)
-		return NULL;
-
-	if (a->argc <= 4)
-		return CLI_SHOWUSAGE;
-
-//	ast_verbose("%d %s",(a->argv[3][0] -'0'), a->argv[4]);
-
-	p = iflist;
-	while(p) {
-		if (p->line_id == (a->argv[3][0]-'0')) {
-			channel_settings *s = &channel_config[p->line_id];
-			ast_copy_string(s->autodial_ext, a->argv[4], sizeof(s->autodial_ext));
-			break;
-		}
-		p = brcm_get_next_pvt(p);
-	}
-
-	return CLI_SUCCESS;
-}
-
-
-/*! \brief Channel CLI commands definition */
-static struct ast_cli_entry cli_brcm[] = {
-	AST_CLI_DEFINE(brcm_show_status, "Show chan_brcm status"),
-	AST_CLI_DEFINE(brcm_show_dialtone_status, "Show chan_brcm dialtone status"),
-	AST_CLI_DEFINE(brcm_set_parameters_on_off,  "Set chan_brcm parameters"),
-	AST_CLI_DEFINE(brcm_set_parameters_value,  "Set chan_brcm dialout msecs"),
-	AST_CLI_DEFINE(brcm_set_autodial_extension,  "Set chan_brcm autodial extension"),
-	AST_CLI_DEFINE(brcm_reload, "Reload chan_brcm configuration"),
-};
-
-
-static int unload_module(void)
-{
-	struct brcm_pvt *p, *pl;
-
-	//ast_sched_dump(sched);
-
-	/* First, take us out of the channel loop */
-	if (cur_tech)
-		ast_channel_unregister(cur_tech);
-	if (!ast_mutex_lock(&iflock)) {
-		/* Hangup all interfaces if they have an owner */
-		p = iflist;
-		while(p) {
-			int i;
-			pvt_lock(p, "brcm unload module");
-			//ast_mutex_lock(&p->lock);
-			for (i=0; i<NUM_SUBCHANNELS; i++) {
-				struct ast_channel *owner = p->sub[i]->owner;
-				if (owner) {
-					ast_channel_ref(owner);
-					ast_mutex_unlock(&p->lock);
-					ast_softhangup(owner, AST_SOFTHANGUP_APPUNLOAD);
-					ast_channel_unref(owner);
-					ast_mutex_lock(&p->lock);
-				}
-			}
-			free(registration_change_sub);
-			registration_change_sub = NULL;
-			pvt_unlock(p);
-			//ast_mutex_unlock(&p->lock);
-			p = p->next;
-		}
-		iflist = NULL;
-		ast_mutex_unlock(&iflock);
-	} else {
-		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
-		return -1;
-	}
-
-	if (!ast_mutex_lock(&monlock)) {
-		if (ubus_thread != AST_PTHREADT_NULL && ubus_thread != AST_PTHREADT_STOP) {
-			ast_verbose("Stopping ubus thread...\n");
-			pthread_kill(ubus_thread, SIGUSR2);
-			pthread_join(ubus_thread, NULL);
-			ubus_thread = AST_PTHREADT_STOP;
-			ast_verbose("ubus thread is stopped\n");
-		}
-		ast_mutex_unlock(&monlock);
-	} else {
-		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
-		return -1;
-	}
-
-	if (!ast_mutex_lock(&iflock)) {
-		/* Destroy all the interfaces and free their memory */
-		p = iflist;
-		while(p) {
-			/* Close the socket, assuming it's real */
-			pl = p;
-			p = p->next;
-			/* Free associated memory */
-			ast_free(pl);
-		}
-		iflist = NULL;
-		ast_mutex_unlock(&iflock);
-	} else {
-		ast_log(LOG_WARNING, "Unable to lock the monitor\n");
-		return -1;
-	}
-
-	/* Unregister CLI commands */
-	ast_cli_unregister_multiple(cli_brcm, ARRAY_LEN(cli_brcm));
-
-	feature_access_code_clear();
-	ast_sched_context_destroy(sched);
-
-	return 0;
-}
-
-/*
- * Create a channel_settings struct with default values.
- */
-static channel_settings channel_settings_create(void)
-{
-	channel_settings line_conf = (channel_settings){
-		.enabled = 1,
-		.language = "",
-		.cid_num = "",
-		.cid_name = "",
-		.context_direct = "default-direct",
-		.context = "default",
-		.autodial_ext = "",
-		.ringsignal = 1,
-		.timeoutmsec = 4000,
-		.autodial_timeoutmsec = 60000,
-		.period = 20,
-		.hangup_xfer = 0,
-		.dialtone_timeoutmsec = 20000,
-		.offhook_nu_timeoutmsec = 60000,
-		.offhook_silence_timeoutmsec = 180000,		
-		.do_not_disturb = 0,
-		.calleridenable = 0, //clip
-                .calleridnameenable = 0,  //cnip
-                .anonymouscallenable = 0, //clir
-		.flashSpec = 0,
-	};
-	return line_conf;
-}
-
-/*
- * Load config file settings into the specified channel_settings struct.
- * Can be called multiple times in order to load from multiple ast_variables.
- */
-static void channel_settings_load(channel_settings *channel_config, struct ast_variable *v)
-{
-	while(v) {
-		if (!strcasecmp(v->name, "enabled")) {
-			channel_config->enabled = ast_true(v->value)?1:0;
-		} else if (!strcasecmp(v->name, "language")) {
-			ast_copy_string(channel_config->language, v->value, sizeof(channel_config->language));
-		} else if (!strcasecmp(v->name, "callerid")) {
-			ast_callerid_split(v->value, channel_config->cid_name, sizeof(channel_config->cid_name), channel_config->cid_num, sizeof(channel_config->cid_num));
-		} else if (!strcasecmp(v->name, "context")) {
-			ast_copy_string(channel_config->context, v->value, sizeof(channel_config->context));
-		} else if (!strcasecmp(v->name, "context_direct")) {
-			ast_copy_string(channel_config->context_direct, v->value, sizeof(channel_config->context_direct));
-		} else if (!strcasecmp(v->name, "autodial")) {
-			ast_copy_string(channel_config->autodial_ext, v->value, sizeof(channel_config->autodial_ext));
-		} else if (!strcasecmp(v->name, "ringsignal")) {
-			channel_config->ringsignal = ast_true(v->value)?1:0;
-		} else if (!strcasecmp(v->name, "dialoutmsec")) {
-			channel_config->timeoutmsec = atoi(v->value);
-                } else if (!strcasecmp(v->name, "interdigitopenmsec")) {
-                        channel_config->interdigitopenmsec = atoi(v->value);
-                } else if (!strcasecmp(v->name, "minimumnumberdigits")) {
-                        channel_config->minimumnumberdigits = atoi(v->value);
-                } else if (!strcasecmp(v->name, "terminationdigit")) {
-                        channel_config->terminationdigit =v->value[0];
-		} else if (!strcasecmp(v->name, "autodial_timeoutmsec")) {
-			channel_config->autodial_timeoutmsec = atoi(v->value);
-		} else if (!strcasecmp(v->name, "dialtone_timeoutmsec")) {
-			channel_config->dialtone_timeoutmsec = atoi(v->value);
-		} else if (!strcasecmp(v->name, "offhook_nu_timeoutmsec")) {
-			channel_config->offhook_nu_timeoutmsec = atoi(v->value);
-		} else if (!strcasecmp(v->name, "offhook_silence_timeoutmsec")) {
-			channel_config->offhook_silence_timeoutmsec = atoi(v->value);
-		}
-		else if (!strcasecmp(v->name, "hangup_xfer")) {
-			channel_config->hangup_xfer = ast_true(v->value)?1:0;
-		}
-		else if (!strcasecmp(v->name, "do_not_disturb")) {
-			channel_config->do_not_disturb = ast_true(v->value)?1:0;
-		}
-		else if (!strcasecmp(v->name, "calleridenable")) {
-			channel_config->calleridenable = ast_true(v->value)?1:0;
-		}
-                else if (!strcasecmp(v->name, "calleridnameenable")) {
-                        channel_config->calleridnameenable = ast_true(v->value)?1:0;
-                }
-                else if (!strcasecmp(v->name, "anonymouscallenable")) {
-                        channel_config->anonymouscallenable = ast_true(v->value)?1:0;
-                }
-		else if (!strcasecmp(v->name, "flash_spec")) {
-			if (!strcasecmp(v->value, "etsi"))
-				channel_config->flashSpec = FLASH_SPEC_ETSI;
-			else
-				channel_config->flashSpec = FLASH_SPEC_UK;
-                }
-		else if (!strcasecmp(v->name, "mwi_enabled")) {
-			channel_config->mwi_enabled = ast_true(v->value)?1:0;
-		}
-		v = v->next;
-	}
-}
-
-static int load_common_settings(struct ast_config **cfg)
-{
-	struct ast_flags config_flags = { 0 };
-
-	/* Set default values */
-	hold_target_before_refer = 1;
-	
-	if ((*cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
-		ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
-		return AST_MODULE_LOAD_DECLINE;
-	}
-
-	/* We *must* have a config file otherwise stop immediately */
-	if (!(*cfg)) {
-		ast_log(LOG_ERROR, "Unable to load config %s\n", config);
-		return AST_MODULE_LOAD_DECLINE;
-	}
-
-	/* Load jitterbuffer defaults, Copy the default jb config over global_jbconf */
-	memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
-
-	/* Load global settings */
-	struct ast_variable *v;
-	v = ast_variable_browse(*cfg, "default");
-
-	while(v) {
-		if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
-			ast_debug(2, "Loaded jitterbuffer settings '%s'\n", v->value);
-			v = v->next;
-			continue;
-		}
-
-		if (!strcasecmp(v->name, "cwtimeout")) {
-			cwtimeout = atoi(v->value);
-			if (cwtimeout > 60 || cwtimeout < 0) {
-				cwtimeout = DEFAULT_CALL_WAITING_TIMEOUT;
-				ast_log(LOG_WARNING, "Incorrect cwtimeout '%s', defaulting to '%d'\n", v->value, cwtimeout);
-			}
-		} else if (!strcasecmp(v->name, "r4hanguptimeout")) {
-			r4hanguptimeout = atoi(v->value);
-			if (r4hanguptimeout > 30000 || r4hanguptimeout < 0) {
-				r4hanguptimeout = DEFAULT_R4_HANGUP_TIMEOUT;
-				ast_log(LOG_WARNING, "Incorrect r4hanguptimeout '%s', defaulting to '%d'\n",
-						v->value, r4hanguptimeout);
-			}
-		} else if (!strcasecmp(v->name, "onholdhanguptimeout")) {
-			onholdhanguptimeout = atoi(v->value);
-			if (onholdhanguptimeout > 60 || onholdhanguptimeout < 0) {
-				onholdhanguptimeout = DEFAULT_ONHOLD_HANGUP_TIMEOUT;
-				ast_log(LOG_WARNING, "Incorrect onholdhanguptimeout '%s', defaulting to '%d'\n",
-						v->value, onholdhanguptimeout);
-			}
-		} else if (!strcasecmp(v->name, "hold_target_before_refer")) {
-			if (!strcasecmp(v->value, "no")) {
-				ast_debug(1, "The transfer target will not be put on-hold before sending REFER\n");
-				hold_target_before_refer = 0;
-			}
-		} else if (!strcasecmp(v->name, "featureaccesscodes")) {
-			char *tok;
-
-			if (ast_strlen_zero(v->value)) {
-				ast_debug(1, "No value given for featureaccesscodes on line %d\n", v->lineno);
-			}
-			else {
-				tok = strtok(ast_strdupa(v->value), ",");
-				while (tok) {
-					char *code = ast_strdupa(tok);
-					code = ast_strip(code);
-
-					feature_access_code_add(code);
-
-					tok = strtok(NULL, ",");
-				}
-			}
-		}
-
-		v = v->next;
-	}
-
-	return 0;
-}
-
-static void load_settings(struct ast_config *cfg)
-{
-	struct ast_variable *v;
-
-	// Load settings fore all channels / endpoints
-	for (int i = 0; i < num_endpoints; i++) {
-		// Create and init a new settings struct
-		channel_config[i] = channel_settings_create();
-		// Load default settings
-		v = ast_variable_browse(cfg, "default");
-		channel_settings_load(&channel_config[i], v);
-		// Load per line specific settings
-		char config_section[64];
-		snprintf(config_section, 64, "extension%d", i);
-		v = ast_variable_browse(cfg, config_section);
-		if (!v) {
-			ast_log(LOG_WARNING, "Unable to load endpoint specific config (missing config section?): %s\n", config_section);
-		}
-		channel_settings_load(&channel_config[i], v);
-	}
-}
-
-enum {
-	NUM_ENDPOINTS,
-	NUM_FXO_ENDPOINTS,
-	NUM_FXS_ENDPOINTS,
-	NUM_DECT_ENDPOINTS,
-	__MAX_ENDPOINTS,
-};
-
-static const struct blobmsg_policy endpt_count_policy[__MAX_ENDPOINTS] = {
-	[NUM_ENDPOINTS] = { .name = "num_endpoints", .type = BLOBMSG_TYPE_INT32 },
-	[NUM_FXO_ENDPOINTS] = { .name = "num_fxo_endpoints", .type = BLOBMSG_TYPE_INT32 },
-	[NUM_FXS_ENDPOINTS] = { .name = "num_fxs_endpoints", .type = BLOBMSG_TYPE_INT32 },
-	[NUM_DECT_ENDPOINTS] = { .name = "num_dect_endpoints", .type = BLOBMSG_TYPE_INT32 },
-};
-
-enum {
-	RTP_STATS_LINE_ID,
-	RTP_STATS_LOCAL_BURST_DENSITY,
-	RTP_STATS_REMOTE_BURST_DENSITY,
-	RTP_STATS_LOCAL_BURST_DURATION,
-	RTP_STATS_REMOTE_BURST_DURATION,
-	RTP_STATS_LOCAL_GAP_DENSITY,
-	RTP_STATS_REMOTE_GAP_DENSITY,
-	RTP_STATS_LOCAL_GAP_DURATION,
-	RTP_STATS_REMOTE_GAP_DURATION,
-	RTP_STATS_LOCAL_JB_RATE,
-	RTP_STATS_REMOTE_JB_RATE,
-	RTP_STATS_LOCAL_JB_MAX,
-	RTP_STATS_REMOTE_JB_MAX,
-	RTP_STATS_LOCAL_JB_NOMINAL,
-	RTP_STATS_REMOTE_JB_NOMINAL,
-	RTP_STATS_LOCAL_JB_ABS_MAX,
-	RTP_STATS_REMOTE_JB_ABS_MAX,
-	RTP_STATS_DISCARDED,
-	RTP_STATS_LOST,
-	RTP_STATS_RX_PKTS,
-	RTP_STATS_TX_PKTS,
-	RTP_STATS_JB_AVG,
-	RTP_STATS_JITTER,
-	RTP_STATS_LOSS_RATE,
-	RTP_STATS_MAX_JITTER,
-	RTP_STATS_AVERAGE_ROUND_TRIP_DELAY,
-	__MAX_RTP_STATS,
-};
-
-static const struct blobmsg_policy endpt_rtp_stats_policy[__MAX_RTP_STATS] = {
-	[RTP_STATS_LINE_ID] = { .name = "lineId", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_BURST_DENSITY] = { .name = "localBurstDensity", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_BURST_DENSITY] = { .name = "remoteBurstDensity", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_BURST_DURATION] = { .name = "localBurstDuration", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_BURST_DURATION] = { .name = "remoteBurstDuration", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_GAP_DENSITY] = { .name = "localGapDensity", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_GAP_DENSITY] = { .name = "remoteGapDensity", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_GAP_DURATION] = { .name = "localGapDuration", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_GAP_DURATION] = { .name = "remoteGapDuration", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_JB_RATE] = { .name = "localJbRate", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_JB_RATE] = { .name = "remoteJbRate", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_JB_MAX] = { .name = "localJbMax", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_JB_MAX] = { .name = "remoteJbMax", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_JB_NOMINAL] = { .name = "localJbNominal", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_JB_NOMINAL] = { .name = "remoteJbNominal", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_LOCAL_JB_ABS_MAX] = { .name = "localJbAbsMax", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_REMOTE_JB_ABS_MAX] = { .name = "remoteJbAbsMax", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_DISCARDED] = { .name = "discarded", .type = BLOBMSG_TYPE_INT32 },
-	[RTP_STATS_LOST] = { .name = "lost", .type = BLOBMSG_TYPE_INT32 },
-	[RTP_STATS_RX_PKTS] = { .name = "rxpkts", .type = BLOBMSG_TYPE_INT32 },
-	[RTP_STATS_TX_PKTS] = { .name = "txpkts", .type = BLOBMSG_TYPE_INT32 },
-	[RTP_STATS_JB_AVG] = { .name = "jbAvg", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_JITTER] = { .name = "jitter", .type = BLOBMSG_TYPE_INT32 },
-	[RTP_STATS_LOSS_RATE] = { .name = "uLossRate", .type = BLOBMSG_TYPE_INT16 },
-	[RTP_STATS_MAX_JITTER] = { .name = "maxJitter", .type = BLOBMSG_TYPE_INT32 },
-	[RTP_STATS_AVERAGE_ROUND_TRIP_DELAY] = { .name = "averageRoundTripDelay", .type = BLOBMSG_TYPE_INT32 },
-};
-
-// Reception of event
-// { "ubus.object.add": {"id":123, "path":"foo"} }
-static void ubus_event_new_obj(struct ubus_context *ctx __attribute__((unused)), struct ubus_event_handler *ev __attribute__((unused)),
-		const char *type, struct blob_attr *blob)
-{
-	struct blob_attr *keys[ARRAY_SIZE(new_obj_policy)];
-	const char *objPath;
-	uint32_t objId;
-
-	// Tokenize message key/value paris into an array
-	if (blobmsg_parse(new_obj_policy, ARRAY_SIZE(new_obj_policy),
-			keys, blob_data(blob), blob_len(blob))) {
-		return;
-	}
-
-	if (!type || !keys[OBJ_ID] || !keys[OBJ_PATH])
-		return; // Did we get all arguments we need?
-
-	objId = blobmsg_get_u32(keys[OBJ_ID]);
-	objPath = blobmsg_get_string(keys[OBJ_PATH]);
-
-	if(strcmp(type, ubusStrObjAdd) == 0) { // Object added to global context
-		if(strcmp(objPath, endpt_ubus_path) == 0) {
-			ast_log(LOG_DEBUG, "the UBUS object %s has been added\n", endpt_ubus_path);
-			endpt_id = objId;
-		}
-	} else if(strcmp(type, ubusStrObjRm) == 0) { // Object removed from global context
-		if(strcmp(objPath, endpt_ubus_path) == 0) {
-			ast_log(LOG_DEBUG, "the UBUS object %s has been removed\n", endpt_ubus_path);
-			endpt_id = 0;
-		}
-	}
-}
-
-static void endpt_get_count_cb(struct ubus_request *req,
-							   int type, struct blob_attr *msg) {
-	struct blob_attr *tb[__MAX_ENDPOINTS];
-
-	blobmsg_parse(endpt_count_policy, __MAX_ENDPOINTS, tb, blob_data(msg), blob_len(msg));
-
-	if (tb[NUM_FXS_ENDPOINTS])
-		num_fxs_endpoints = blobmsg_get_u32(tb[NUM_FXS_ENDPOINTS]);
-	if (tb[NUM_FXO_ENDPOINTS])
-		num_fxo_endpoints = blobmsg_get_u32(tb[NUM_FXO_ENDPOINTS]);
-	if (tb[NUM_DECT_ENDPOINTS])
-		num_dect_endpoints = blobmsg_get_u32(tb[NUM_DECT_ENDPOINTS]);
-	num_endpoints = num_fxs_endpoints + num_dect_endpoints;
-}
-
-static int endpt_get_count(void) {
-	struct blob_buf bb;
-
-	endpt_id = get_ubus_endpt_id(0);
-	if(!endpt_id)
-		return -1;
-
-	memset(&bb, 0, sizeof(bb));
-	blob_buf_init(&bb, 0);
-	blobmsg_add_u8(&bb, "effective", 0);
-
-	return (ubus_invoke(ctx, endpt_id, "count", bb.head,
-		endpt_get_count_cb, NULL, 2000) == UBUS_STATUS_OK ? 0 : -1);
-}
-
-static void ubus_call_answer_rtp_stats(struct ubus_request *req, int type, struct blob_attr *msg) {
-	struct blob_attr *tb[__MAX_RTP_STATS];
-	uint16_t lineId = 0;
-	struct brcm_pvt *p = NULL;
-	struct brcm_subchannel *sub = NULL;
-
-	ast_log(LOG_DEBUG, "thread %d: got answer from endptmngr on rtp_stats ubus call.\n", ast_get_tid());
-	blobmsg_parse(endpt_rtp_stats_policy, __MAX_RTP_STATS, tb, blob_data(msg), blob_len(msg));
-
-	if (tb[RTP_STATS_LINE_ID])
-		lineId = blobmsg_get_u16(tb[RTP_STATS_LINE_ID]);
-
-	p = brcm_get_pvt_from_lineid(iflist, lineId);
-	if (!p) {
-		ast_log(LOG_ERROR, "No pvt with the line_id %d found!\n", lineId);
-		return;
-	}
-
-	sub = brcm_get_active_subchannel(p);
-	if (!sub) {
-		ast_log(LOG_ERROR, "No active subchannel to write rtp stats!\n");
-		return;
-	}
-
-	if (tb[RTP_STATS_LOCAL_BURST_DENSITY])
-		sub->rtp_stats.localBurstDensity = blobmsg_get_u16(tb[RTP_STATS_LOCAL_BURST_DENSITY]);
-	if (tb[RTP_STATS_REMOTE_BURST_DENSITY])
-		sub->rtp_stats.remoteBurstDensity = blobmsg_get_u16(tb[RTP_STATS_REMOTE_BURST_DENSITY]);
-	if (tb[RTP_STATS_LOCAL_BURST_DURATION])
-		sub->rtp_stats.localBurstDuration = blobmsg_get_u16(tb[RTP_STATS_LOCAL_BURST_DURATION]);
-	if (tb[RTP_STATS_REMOTE_BURST_DURATION])
-		sub->rtp_stats.remoteBurstDuration = blobmsg_get_u16(tb[RTP_STATS_REMOTE_BURST_DURATION]);
-	if (tb[RTP_STATS_LOCAL_GAP_DENSITY])
-		sub->rtp_stats.localGapDensity = blobmsg_get_u16(tb[RTP_STATS_LOCAL_GAP_DENSITY]);
-	if (tb[RTP_STATS_REMOTE_GAP_DENSITY])
-		sub->rtp_stats.remoteGapDensity = blobmsg_get_u16(tb[RTP_STATS_REMOTE_GAP_DENSITY]);
-	if (tb[RTP_STATS_LOCAL_GAP_DURATION])
-		sub->rtp_stats.localGapDuration = blobmsg_get_u16(tb[RTP_STATS_LOCAL_GAP_DURATION]);
-	if (tb[RTP_STATS_REMOTE_GAP_DURATION])
-		sub->rtp_stats.remoteGapDuration = blobmsg_get_u16(tb[RTP_STATS_REMOTE_GAP_DURATION]);
-	if (tb[RTP_STATS_LOCAL_JB_RATE])
-		sub->rtp_stats.localJbRate = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_RATE]);
-	if (tb[RTP_STATS_REMOTE_JB_RATE])
-		sub->rtp_stats.remoteJbRate = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_RATE]);
-	if (tb[RTP_STATS_LOCAL_JB_MAX])
-		sub->rtp_stats.localJbMax = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_MAX]);
-	if (tb[RTP_STATS_REMOTE_JB_MAX])
-		sub->rtp_stats.remoteJbMax = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_MAX]);
-	if (tb[RTP_STATS_LOCAL_JB_NOMINAL])
-		sub->rtp_stats.localJbNominal = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_NOMINAL]);
-	if (tb[RTP_STATS_REMOTE_JB_NOMINAL])
-		sub->rtp_stats.remoteJbNominal = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_NOMINAL]);
-	if (tb[RTP_STATS_LOCAL_JB_ABS_MAX])
-		sub->rtp_stats.localJbAbsMax = blobmsg_get_u16(tb[RTP_STATS_LOCAL_JB_ABS_MAX]);
-	if (tb[RTP_STATS_REMOTE_JB_ABS_MAX])
-		sub->rtp_stats.remoteJbAbsMax = blobmsg_get_u16(tb[RTP_STATS_REMOTE_JB_ABS_MAX]);
-	if (tb[RTP_STATS_DISCARDED])
-		sub->rtp_stats.discarded = blobmsg_get_u32(tb[RTP_STATS_DISCARDED]);
-	if (tb[RTP_STATS_LOST])
-		sub->rtp_stats.lost = blobmsg_get_u32(tb[RTP_STATS_LOST]);
-	if (tb[RTP_STATS_RX_PKTS])
-		sub->rtp_stats.rxpkts = blobmsg_get_u32(tb[RTP_STATS_RX_PKTS]);
-	if (tb[RTP_STATS_TX_PKTS])
-		sub->rtp_stats.txpkts = blobmsg_get_u32(tb[RTP_STATS_TX_PKTS]);
-	if (tb[RTP_STATS_JB_AVG])
-		sub->rtp_stats.jbAvg = blobmsg_get_u16(tb[RTP_STATS_JB_AVG]);
-	if (tb[RTP_STATS_JITTER])
-		sub->rtp_stats.jitter = blobmsg_get_u32(tb[RTP_STATS_JITTER]);
-	if (tb[RTP_STATS_LOSS_RATE])
-		sub->rtp_stats.uLossRate = blobmsg_get_u16(tb[RTP_STATS_LOSS_RATE]);
-	if (tb[RTP_STATS_MAX_JITTER])
-		sub->rtp_stats.maxJitter = blobmsg_get_u32(tb[RTP_STATS_MAX_JITTER]);
-	if (tb[RTP_STATS_AVERAGE_ROUND_TRIP_DELAY])
-		sub->rtp_stats.averageRoundTripDelay = blobmsg_get_u32(tb[RTP_STATS_AVERAGE_ROUND_TRIP_DELAY]);
-
-	sub->rtp_stats.averageFarEndInterarrivalJitter = sub->jitter_count ? (sub->farEndInterrivalJitter / sub->jitter_count) : 0;
-
-	ast_log(LOG_DEBUG, "RTP stats received:\nlocalBurstDensity: %d, remoteBurstDensity: %d, "
-			"localBurstDuration: %d, remoteBurstDuration: %d, localGapDensity: %d, "
-			"remoteGapDensity: %d, localGapDuration: %d, remoteGapDuration: %d, "
-			"localJbRate: %d, remoteJbRate: %d, localJbMax: %d, remoteJbMax: %d, "
-			"localJbNominal: %d remoteJbNominal: %d, localJbAbsMax: %d, "
-			"remoteJbAbsMax: %d, discarded: %d, lost: %d, rxpkts: %d, txpkts: %d, "
-			"jbAvg: %d, jitter: %d, uLossRate: %d, maxJitter: %d, averageRoundTripDelay: %d, "
-			"averageFarEndInterarrivalJitter: %d\n",
-			sub->rtp_stats.localBurstDensity, sub->rtp_stats.remoteBurstDensity, sub->rtp_stats.localBurstDuration,
-			sub->rtp_stats.remoteBurstDuration, sub->rtp_stats.localGapDensity, sub->rtp_stats.remoteGapDensity,
-			sub->rtp_stats.localGapDuration, sub->rtp_stats.remoteGapDuration, sub->rtp_stats.localJbRate,
-			sub->rtp_stats.remoteJbRate, sub->rtp_stats.localJbMax, sub->rtp_stats.remoteJbMax, sub->rtp_stats.localJbNominal,
-			sub->rtp_stats.remoteJbNominal, sub->rtp_stats.localJbAbsMax, sub->rtp_stats.remoteJbAbsMax, sub->rtp_stats.discarded,
-			sub->rtp_stats.lost, sub->rtp_stats.rxpkts, sub->rtp_stats.txpkts, sub->rtp_stats.jbAvg, sub->rtp_stats.jitter,
-			sub->rtp_stats.uLossRate, sub->rtp_stats.maxJitter, sub->rtp_stats.averageRoundTripDelay, sub->rtp_stats.averageFarEndInterarrivalJitter);
-}
-
-static int endpt_get_rtp_stats(int line) {
-	struct ubus_context *local_ctx;
-	struct blob_buf bb;
-	int ret;
-	struct brcm_pvt *p = NULL;
-	struct brcm_subchannel *sub = NULL;
-
-	/*
-	 * Reset rtp_stats first because ubus_call_answer_rtp_stats() will not be called if "ubus call endpt rtp_stats" fails,
-	 * e.g. an unanswered incoming call on which the connection is not created. In this case, all RTP statistics counters
-	 * shall be zeros.
-	 */
-	p = brcm_get_pvt_from_lineid(iflist, line);
-	if (!p) {
-		ast_log(LOG_ERROR, "No pvt with the line %d found!\n", line);
-		return -1;
-	}
-
-	sub = brcm_get_active_subchannel(p);
-	if (!sub) {
-		ast_log(LOG_ERROR, "No active subchannel to get rtp stats!\n");
-		return -1;
-	}
-	memset(&sub->rtp_stats, 0, sizeof(sub->rtp_stats));
-
-	if (!endpt_id) {
-		return -1;
-	}
-
-	local_ctx = ubus_connect(NULL);
-	if (!local_ctx) {
-		ast_log(LOG_ERROR, "%s(): ubus_connect() failed\n", __func__);
-		return -1;
-	}
-
-	memset(&bb, 0, sizeof(bb));
-	blob_buf_init(&bb, 0);
-
-	blobmsg_add_u32(&bb, "line", line);
-	blobmsg_add_u8(&bb, "reset", 1); // always reset RTP stats after get them
-
-	ast_log(LOG_DEBUG, "thread %d: ubus call endpt rtp_stats \"{'line':%d,'reset':true}\"", ast_get_tid(), line);
-	ret = ubus_invoke(local_ctx, endpt_id, "rtp_stats", bb.head, ubus_call_answer_rtp_stats, NULL, 500);
-
-	blob_buf_free(&bb);
-	ubus_free(local_ctx);
-
-	if (ret != UBUS_STATUS_OK) {
-		ast_log(LOG_DEBUG, "ubus_invoke for rtp_stats failed with return value %d\n", ret);
-		return -1;
-	}
-
-	return 0;
-}
-
-// Reception of RPC call
-// ubus call asterisk event '{ "line" : 1, "event" : "EVENT_DTMF0" }'
-static int asterisk_event(struct ubus_context *ctx, struct ubus_object *obj,
-				   struct ubus_request_data *req, const char *method,
-				   struct blob_attr *msg)
-{
-	struct blob_attr *tb[__EVENT_MAX];
-	char *event_str;
-	struct endpt_event *ev;
-	int line;
-
-	blobmsg_parse(asterisk_event_policy, __EVENT_MAX,
-				  tb, blob_data(msg), blob_len(msg));
-
-	if (!tb[EVENT_LINE_ID] || !tb[EVENT_TYPE])
-		return UBUS_STATUS_INVALID_ARGUMENT;
-
-	line = blobmsg_get_u32(tb[EVENT_LINE_ID]);
-
-	event_str = blobmsg_get_string(tb[EVENT_TYPE]);
-
-	/* Check if event is valid */
-	for (ev = event_map; ev->event != EVENT_LAST; ev++) {
-		if (strncmp(ev->name, event_str, strlen(ev->name)) == 0)
-			break;
-	}
-	if (ev->event == EVENT_LAST) {
-		ast_log(LOG_DEBUG, "Unknown event: %s\n", event_str);
-		return UBUS_STATUS_INVALID_ARGUMENT;
-	}
-	ev->line = line;
-
-	ast_log(LOG_DEBUG, "event: %s, line: %d\n", ev->name, ev->line);
-	if(iflist && cur_tech)
-		brcm_process_event(ev);
-
-	return UBUS_STATUS_OK;
-}
-
-// Reception of RPC call
-// ubus call asterisk call_status '{ "extension" : X }' or ubus call asterisk call_status '{ "line" : X }'
-static int asterisk_call_status(struct ubus_context *ctx, struct ubus_object *obj,
-				   struct ubus_request_data *req, const char *method,
-				   struct blob_attr *msg)
-{
-	struct blob_attr *tb[__EVENT_MAX];
-	enum ubus_msg_status res = UBUS_STATUS_UNKNOWN_ERROR;
-	struct blob_buf blob;
-	int extension = -1;
-	int line = -1;
-	char sipAccount[6];
-
-	blobmsg_parse(asterisk_call_status_policy, __CALL_STATUS_MAX,
-				  tb, blob_data(msg), blob_len(msg));
-	memset(&blob, 0, sizeof(blob));
-
-	if(blob_buf_init(&blob, 0))
-		return UBUS_STATUS_UNKNOWN_ERROR;
-
-	if (tb[CALL_STATUS_EXTENSION_ID]) {
-		extension = blobmsg_get_u32(tb[CALL_STATUS_EXTENSION_ID]);
-		struct brcm_pvt *p = iflist;
-
-		while(p) {
-			if (extension == p->line_id) {
-				blobmsg_add_u32(&blob, "extension", p->line_id);
-				blobmsg_add_string(&blob, "call_status", strlen(p->extensionCallStatus) ? p->extensionCallStatus : "Idle");
-				res = UBUS_STATUS_OK;
-				break;
-			}
-			p = brcm_get_next_pvt(p);
-		}
-	} else if (tb[CALL_STATUS_LINE_ID]) {
-		line = blobmsg_get_u32(tb[CALL_STATUS_LINE_ID]);
-		if (line >=0) {
-			snprintf(sipAccount, sizeof(sipAccount), "sip%d", line);
-			getLineState(sipAccount, lineCallStatus);
-			blobmsg_add_u32(&blob, "line", line);
-			blobmsg_add_string(&blob, "call_status", strlen(lineCallStatus) ? lineCallStatus : "Idle");
-			res = UBUS_STATUS_OK;
-		} else {
-			return UBUS_STATUS_INVALID_ARGUMENT;
-		}
-	} else {
-		return UBUS_STATUS_INVALID_ARGUMENT;
-	}
-
-	ubus_send_reply(ctx, req, blob.head);
-	blob_buf_free(&blob);
-	return res;
-}
-
-static struct ubus_method asterisk_methods[] = {
-	UBUS_METHOD("event", asterisk_event, asterisk_event_policy),
-	UBUS_METHOD("call_status", asterisk_call_status, asterisk_call_status_policy),
-};
-
-static struct ubus_object_type asterisk_obj_type = UBUS_OBJECT_TYPE("asterisk", asterisk_methods);
-
-static struct ubus_object asterisk_obj = {
-	.name = "asterisk",
-	.type = &asterisk_obj_type,
-	.methods = asterisk_methods,
-	.n_methods = ARRAY_SIZE(asterisk_methods),
-};
-
-/* Process ubus events by ubus stack */
-static void ubus_stream_handler(pe_stream_t *stream __attribute__((unused)), pe_event_t *event __attribute__((unused))) {
-	ubus_handle_event(ctx);
-}
-
-static int ubus_init(void) {
-	pe_stream_t *ubus_stream;
-
-	base = pe_base_new();
-	if (base < 0)
-		exit_failure("pe_base_new\n");
-	
-	ctx = ubus_connect(NULL);
-	if (!ctx) return -1;
-
-	/* Register event handlers (not calls) for:
-	 * { "ubus.object.add": {"id":123, "path":"foo"} } */
-	memset(&ObjAddListener, 0, sizeof(ObjAddListener));
-	ObjAddListener.cb = ubus_event_new_obj;
-	if(ubus_register_event_handler(ctx, &ObjAddListener,
-			ubusStrObjAdd) != UBUS_STATUS_OK) {
-		printf("Error registering ubus event handler %s", ubusStrObjAdd);
-		return -1;
-	}
-
-	memset(&ObjRmListener, 0, sizeof(ObjRmListener));
-	ObjRmListener.cb = ubus_event_new_obj;
-	if(ubus_register_event_handler(ctx, &ObjRmListener,
-			ubusStrObjRm) != UBUS_STATUS_OK) {
-		printf("Error registering ubus event handler %s", ubusStrObjRm);
-		return -1;
-	}
-
-	/* Lookup path to Endptmngr AFTER registration of ubus object
-	 * event handler above. It's no error if lookup fails. */
-	if(ubus_lookup_id(ctx, endpt_ubus_path,
-			(uint32_t*) &endpt_id) != UBUS_STATUS_OK) {
-		endpt_id = 0;
-	}
-
-	if (ubus_add_object(ctx, &asterisk_obj) != UBUS_STATUS_OK) {
-		printf("Failed to register asterisk object");
-		return -1;
-	}
-
-	/* Listen for data on ubus socket in our main event loop. */
-	ubus_stream = pe_stream_new(ctx->sock.fd);
-	pe_stream_add_handler(ubus_stream, 0, ubus_stream_handler);
-	pe_base_add_stream(base, ubus_stream);
-
-	return 0;
-}
-
-// pthread wrapper for lib picoevent dispatcher
-static void *pe_base_run(void *unused) {
-	int delay;
-
-	ast_verbose("thread %d started\n", ast_get_tid());
-	for (delay = 0; delay < 5 && (!iflist || !cur_tech); delay++)
-		sleep(1);
-	pe_base_dispatch(base);
-
-	return NULL;
-}
-
-static int load_module(void)
-{
-	struct ast_config *cfg;
-	int result, try;
-
-	ast_verbose("thread %d is loading the module...\n", ast_get_tid());
-
-	if (!(default_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
-		return AST_MODULE_LOAD_DECLINE;
-	}
-
-	if (!(brcm_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
-		ao2_ref(default_cap, -1);
-		return AST_MODULE_LOAD_DECLINE;
-	}
-
-	ast_format_cap_append_by_type(brcm_tech.capabilities, AST_MEDIA_TYPE_AUDIO);
-	ast_format_cap_append(default_cap, ast_format_alaw, 0);
-	
-	// Init UBUS and wait for endptmngr to start
-	if(ubus_init()) goto err;
-
-	/* Create audio fifos. Both ends open in R/W mode to become
-	 * independent of daemon startup order and peer restart
-	 * recovery. However, later each end use unidirectional flow. */
-	result = mkfifo(audio_tx_str, 0666);
-	if ((result == -1) && (errno != EEXIST)) exit_failure("Failed to create tx pipe");
-	audio_tx_fd = open(audio_tx_str, O_RDWR|O_LARGEFILE|O_NONBLOCK);
-	if(audio_tx_fd == -1) exit_failure("Failed to open tx pipe");
-	audio_tx_bus = pe_bus_new(audio_tx_fd);
-	if (!audio_tx_bus) exit_failure("Failed to create audio_tx bus");
-	result = mkfifo(audio_rx_str, 0666);
-	if ((result == -1) && (errno != EEXIST)) exit_failure("Failed to create rx pipe");
-	audio_rx_fd = open(audio_rx_str, O_RDWR|O_LARGEFILE|O_NONBLOCK);
-	if(audio_rx_fd == -1) exit_failure("Failed to open rx pipe");
-	audio_rx_stream = pe_stream_new(audio_rx_fd);
-	pe_stream_add_handler(audio_rx_stream, PE_MAX_EVENT_SIZE, audio_rx_stream_handler);
-	pe_base_add_stream(base, audio_rx_stream);
-
-	audio_rx_bus = pe_bus_new(-1);
-	if (!audio_rx_bus) exit_failure("Failed to create audio_rx bus");
-	pe_bus_add_handler(audio_rx_bus, audio_packet_handler);
-
-	/* endpt_get_count() invokes synchronous ubus call and MUST be called before creating the ubus thread.
-	 * Otherwise it may cause the process crash or hang */
-	for (try = 0; try < 20 && num_endpoints == -1; try++) {
-		if(endpt_get_count()) {
-			ast_log(LOG_DEBUG, "Waiting for endptmngr...\n");
-			sleep(1);
-		}
-	}
-	if (num_endpoints == -1) {
-		ast_log(LOG_ERROR, "endptmngr is not up and running.\n");
-		goto err;
-	}
-
-	/* Run pe_base_dispatch in separate thread. */
-	if (ast_pthread_create_background(&ubus_thread, NULL, pe_base_run, NULL) < 0) {
-		ast_log(LOG_ERROR, "Unable to start ubus thread.\n");
-		goto err;
-	}
-
-	registration_change_sub = calloc(num_endpoints, sizeof(struct stasis_subscription *));
-
-	/* Setup scheduler thread */
-	if (!(sched = ast_sched_context_create())) {
-		ast_log(LOG_ERROR, "Unable to create scheduler thread/context. Aborting.\n");
-		goto err;
-	}
-
-	if (ast_mutex_lock(&iflock)) {
-		/* It's a little silly to lock it, but we mind as well just to be sure */
-		ast_log(LOG_ERROR, "Unable to lock interface list???\n");
-		goto err;
-	}
-
-	/* Load settings file and read default section */
-	if ((result = load_common_settings(&cfg)) != 0) {
-		goto err;
-	}
-
-	load_settings(cfg);
-	brcm_create_pvts(iflist, 0);
-	brcm_assign_line_id(iflist);
-
-	ast_mutex_unlock(&iflock);
-
-	/* Make sure we can register our channel */
-	cur_tech = (struct ast_channel_tech *) &brcm_tech;
-	if (ast_channel_register(cur_tech)) { 
-		ast_log(LOG_ERROR, "Unable to register channel class 'Brcm'\n");
-		ast_config_destroy(cfg);
-		unload_module();
-		goto err;
-	}
-
-	/* Register all channel CLI functions */
-	ast_cli_register_multiple(cli_brcm, ARRAY_LEN(cli_brcm));
-	ast_config_destroy(cfg);
-
-    if (ast_sched_start_thread(sched)) {
-		ast_sched_context_destroy(sched);
-		sched = NULL;
-		goto err;
-	}
-
-	ast_debug(3, "The module is loaded successfully\n");
-	return AST_MODULE_LOAD_SUCCESS;
-
- err:
-	ao2_ref(default_cap, -1);
-	return AST_MODULE_LOAD_FAILURE;
-}
-
-static int brcm_signal_callwaiting(const struct brcm_pvt *p)
-{
-	endpt_signal(p->line_id, "callwt", "on", NULL);
-	brcm_send_ubus_event("CALLWAITING",p->line_id);
-	return 0;
-}
-
-static int brcm_stop_callwaiting(const struct brcm_pvt *p)
-{
-	endpt_signal(p->line_id, "callwt", "off", NULL);
-	brcm_send_ubus_event("CALLWAITING_STOPPED", p->line_id);
-	return 0;
-}
-
-static int brcm_signal_ringing(struct brcm_pvt *p)
-{
-	if (channel_config[p->line_id].ringsignal) {
-		endpt_signal(p->line_id, "ringing", "on", NULL);
-	}
-	return 0;
-}
-
-
-static int brcm_stop_ringing(struct brcm_pvt *p)
-{
-	ast_log(LOG_ERROR, "brcm_stop_ringing()\n");
-	if (channel_config[p->line_id].ringsignal) {
-		endpt_signal(p->line_id, "ringing", "off", NULL);
-	}
-
-	return 0;
-}
-
-/* Prepare endpoint for ringing. Caller ID signal pending. */
-static int brcm_signal_ringing_callerid_pending(struct brcm_pvt *p)
-{
-	if (channel_config[p->line_id].ringsignal) {
-		endpt_signal(p->line_id, "callid_ringing", "on", NULL);
-	}
-
-	return 0;
-}
-
-static int brcm_stop_ringing_callerid_pending(struct brcm_pvt *p)
-{
-	if (channel_config[p->line_id].ringsignal) {
-		endpt_signal(p->line_id, "callid_ringing", "off", NULL);
-	}
-
-	return 0;
-}
-
-/*
- * Send caller id message to endpoint.
- * MMDDHHMM, number, name
- * 'O' in number or name => not available
- * 'P' in number or name => presentation not allowed
- */
-static int brcm_signal_callerid(struct ast_channel *chan, struct brcm_subchannel *sub)
-{
-	if (channel_config[sub->parent->line_id].ringsignal) {
-		CLID_STRING clid_string;
-		struct timeval utc_time;
-		struct ast_tm local_time;
-		char number[CLID_MAX_NUMBER] = "";
-		char name[CLID_MAX_NAME] = "";
-
-		/* Add datetime to caller id string, format: MMDDHHMM */
-		utc_time = ast_tvnow();
-		ast_localtime(&utc_time, &local_time, NULL);
-		sprintf(clid_string.date,
-			"%02d%02d%02d%02d, ",
-			local_time.tm_mon + 1,
-			local_time.tm_mday,
-			local_time.tm_hour,
-			local_time.tm_min);
-
-		/* Get connected line identity if valid and presentation is allowed */
-		if (chan) {
-			if ((ast_party_id_presentation(&ast_channel_connected(chan)->id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) { // Caller id presentation is allowed
-				// Caller name is valid
-				if (ast_channel_connected(chan)->id.name.valid) {
-					strncpy(name, ast_channel_connected(chan)->id.name.str, sizeof(name) - 1);
-				}
-
-				// Caller number is valid
-				if (ast_channel_connected(chan)->id.number.valid) {
-					strncpy(number, ast_channel_connected(chan)->id.number.str, sizeof(number) - 1);
-
-					// If anonymous/unsubscribed number we marked caller name as private "P"
-					if (strcasecmp("anonymous", ast_channel_connected(chan)->id.number.str) == 0 ||
-						strcasecmp("unsubscribed", ast_channel_connected(chan)->id.number.str) == 0) {
-						strcpy(number, "P");
-						strcpy(name, "P");
-					} else if (strcasecmp("unavailable",ast_channel_connected(chan)->id.number.str) ==0 ) {
-						// If unavailable number we mark caller name as not available "O"
-						strcpy(number, "O");
-						strcpy(name, "O");
-					}
-				} else {
-					strcpy(number, "O");
-				}
-			} else {
-				/* Caller id presentation is not allowed */
-				strcpy(number, "P");
-				strcpy(name, "P");
-			}
-		} else {
-			// Name and number not available.
-			strcpy(number, "O");
-			strcpy(name, "O");
-		}
-
-		/* Add number and name to caller id string, format: number,"name" */
-		int str_length = 0;
-		strncpy(&clid_string.number_name[str_length], number, CLID_MAX_NUMBER);
-		str_length = strlen(number);
-		clid_string.number_name[str_length++] = ',';
-		clid_string.number_name[str_length++] = '"';
-		strncpy(&clid_string.number_name[str_length], name, CLID_MAX_NAME);
-		str_length = strlen(clid_string.number_name);
-		clid_string.number_name[str_length++] = '"';
-		clid_string.number_name[str_length++] = '\0';
-
-		ast_debug(2, "CLIP info: caller number [%s], caller name [%s], final string [%s]\n", number, name, (char *)&clid_string);
-		endpt_signal(sub->parent->line_id, "callid", "on", (char *)&clid_string);
-		return 0;
-	}
-
-	return 0;
-}
-
-static int brcm_create_connection(struct brcm_subchannel *sub) {
-	if (!sub->connection_init) {
-		/* generate random nr for rtp header */
-		sub->ssrc = rand();
-
-		ast_debug(1, "Creating virtual Asterisk connection for pvt line_id=%i connection_id=%d\n", sub->parent->line_id, sub->connection_id);
-		sub->connection_init = 1;
-		sub->jitter_count = 0;
-		sub->farEndInterrivalJitter = 0;
-
-		if (sub->owner) {
-			sub->call_id = ast_channel_callid(sub->owner);
-		} else {
-			sub->call_id = CALLID_OBTAINING;
-		}
-
-		if(!brcm_in_onhold(sub->parent) && !brcm_in_call(sub->parent)) {		// Is there another connection already?
-			ast_debug(1, "Creating real endpoint connection for pvt line_id=%i, connection_id: %d, call_id: %d\n", sub->parent->line_id, sub->connection_id, sub->call_id);
-			endpt_connection(sub->parent->line_id, sub->call_id, "create");
-		} else if (get_callid_state(sub->call_id) == CALLID_ESTABLISHED) {
-			ast_debug(1, "Updating real endpoint connection for pvt line_id=%i, connection_id: %d, call_id: %d\n", sub->parent->line_id, sub->connection_id, sub->call_id);
-			endpt_connection(sub->parent->line_id, sub->call_id, "update");
-		}
-	}
-
-	return 0;
-}
-
-static int brcm_mute_connection(struct brcm_subchannel *sub)
-{
-	/* Workaround for AA. Unmuting is not working. Throw away packets in packets thread instead */
-	return 0;
-}
-
-static int brcm_unmute_connection(struct brcm_subchannel *sub)
-{
-	/* Workaround for AA. Unmuting is not working. Throw away packets in packets thread instead */
-	return 0;
-}
-
-/* Put all subchannels in conferencing mode */
-static int brcm_create_conference(struct brcm_pvt *p)
-{
-	struct brcm_subchannel *second, *onhold;
-	struct ast_bridge *onholdBridge, *secondBridge;
-	struct ast_channel *chanToKick[1];
-	struct ast_frame astFrame;
-	int res;
-
-	memset(&astFrame, 0, sizeof(astFrame));
-	astFrame.src = "TELCHAN";
-	// Second call from initiator.
-	second = brcm_get_active_subchannel(p);
-	if(!second || !second->owner) return -1;
-	// Second bridge. Initiator + second remote call.
-	secondBridge = ast_channel_internal_bridge(second->owner);
-	if(!secondBridge) return -1;
-
-	// First call from initiator (is onhold).
-	onhold = brcm_get_onhold_subchannel(p);
-	if(!onhold || !onhold->owner) return -1;
-
-	ast_log(LOG_NOTICE, "Starting conference for pvt line_id=%i connection_id=%d\n",
-		onhold->parent->line_id, onhold->connection_id);
-
-	/* First bridge. Initiator + first (active but
-	 * waiting in background) remote call. */
-	onholdBridge = ast_channel_internal_bridge(onhold->owner);
-	if(!onholdBridge) return -1;
-
-	/* Put second initiator call onhold and unhold the first initiator
-	 * call. The other way around would be better, but for some reason
-	 * it doesn't work... If doing so, the second call get one way
-	 * audio only. */
-	second->conference_initiator = 0;
-	second->conference_id = strdup(secondBridge->uniqueid);
-	brcm_mute_connection(second);
-	ast_queue_hold(second->owner, NULL);
-	second->channel_state = ONHOLD;
-	onhold->conference_id = strdup(onholdBridge->uniqueid);
-	onhold->conference_initiator = 1;
-	brcm_unmute_connection(onhold);
-	ast_queue_unhold(second->owner);
-	onhold->channel_state = INCALL;
-	sched_yield();
-
-	// Move second call into first bridge and wait for it to finish.
-	chanToKick[0] = second->owner;
-        
-        pvt_lock(second->parent, "moving call to first bridge");
-        if(onholdBridge && secondBridge)
-	res = ast_bridge_merge(onholdBridge, secondBridge, 0, chanToKick, 1);
-	while(ast_bridge_find_by_id(second->conference_id)) sched_yield();
-        pvt_unlock(second->parent);
-
-        // SIP calls need unhold sent to the bridge as well.
-	astFrame.frametype = AST_FRAME_CONTROL;
-	astFrame.subclass.integer = AST_CONTROL_UNHOLD;
-	ast_bridge_queue_everyone_else(onholdBridge, NULL, &astFrame);
-
-        ast_log(LOG_NOTICE,"Conference started \n");
-	return res;
-}
-
-static int brcm_stop_conference(struct brcm_subchannel *p)
-{
-	struct ast_bridge *confBridge;
-	struct brcm_pvt *pvt;
-
-	pvt = p->parent;
-	if (p->connection_init && p->owner) {
-		ast_debug(1, "Ending conference for pvt line_id=%i connection_id=%d\n",
-			p->parent->line_id, p->connection_id);
-
-		// Force end of the conference if it's still active.
-		confBridge = ast_bridge_find_by_id(p->conference_id);
-		if(!confBridge) return -1;
-
-		if(ao2_ref(confBridge, +1) >= 0 && confBridge->uniqueid &&
-				confBridge->technology) {
-			ast_bridge_destroy(confBridge, AST_CAUSE_NORMAL_CLEARING);
-		}
-		ao2_ref(confBridge, -1);
-	}
-	brcm_send_ubus_event("CONFERENCE_STOPPED",pvt->line_id);
-	return 0;
-}
-
-static void brcm_attended_call_transfer(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner)
-{
-	struct brcm_pvt *p = sub->parent;
-
-	if( channel_config[p->line_id].flashSpec == FLASH_SPEC_ETSI ||
-	    channel_config[p->line_id].flashSpec == FLASH_SPEC_UK && ((sub_peer->conf_timer_id != -1) || (sub->conf_timer_id != -1))) {
-		ast_log(LOG_NOTICE ,"Setting up attended call transfer \n");
-		if(sub_peer->conf_timer_id != -1)
-			if (ast_sched_del(sched, sub_peer->conf_timer_id)) {
-				ast_log(LOG_WARNING, "Failed to remove scheduled conference setup timer\n");
-		}
-		sub_peer->conf_timer_id = -1;
-		if(sub->conf_timer_id != -1)
-			if (ast_sched_del(sched, sub->conf_timer_id)) {
-				ast_log(LOG_WARNING, "Failed to remove scheduled conference setup timer\n");
-		}
-		sub->conf_timer_id = -1;
-
-		if (sub->channel_state == INCALL && sub_peer->channel_state == ONHOLD &&
-				owner && peer_owner) {
-			struct ast_channel *bridged_chan_inactive = ast_channel_bridge_peer(peer_owner);
-			struct ast_channel *bridged_chan_active = ast_channel_bridge_peer(owner);
-			char dest[AST_CHANNEL_NAME * 2] = { '\0', };
-
-			if (bridged_chan_inactive && bridged_chan_active) {
-				// Hold the transfer target by default unless being configured no
-				if (hold_target_before_refer)
-					ast_queue_hold(owner, NULL);
-
-				// Start the transfer by sending REFER to the transferee
-				snprintf(dest, sizeof(dest) - 1, "%s?Replaces=%s",
-						ast_channel_exten(owner), ast_channel_name(bridged_chan_active));
-				ast_debug(1, "Start transfer to [%s] on channel %s\n", dest, ast_channel_name(bridged_chan_active));
-				int res = -1;
-				ast_channel_lock(bridged_chan_inactive);
-				if (!ast_test_flag(ast_channel_flags(bridged_chan_inactive), AST_FLAG_ZOMBIE) &&
-						!ast_check_hangup(bridged_chan_inactive)) {
-					if (ast_channel_tech(bridged_chan_inactive)->transfer) {
-						res = ast_channel_tech(bridged_chan_inactive)->transfer(bridged_chan_inactive, dest);
-						if (res == 0)
-							res = 1;
-					} else
-						res = 0;
-				}
-				ast_channel_unlock(bridged_chan_inactive);
-				if (res < 0) {
-					ast_log(LOG_ERROR, "ast_transfer() failed\n");
-				} else if (res == 0) {
-					ast_log(LOG_ERROR, "ast_transfer() is not supported on the peer channel\n");
-				} else {
-					sub->channel_state = TRANSFERING;
-				}
-			} else {
-				ast_log(LOG_ERROR, "can't get the peer channel\n");
-			}
-		}
-	}
-	else
-		ast_log(LOG_ERROR,"Late R4 ,Ignoring since conference should be set up by now \n");
-}
-
-static void brcm_unattended_call_transfer(struct brcm_subchannel *sub, struct brcm_subchannel *sub_peer,
-		struct ast_channel *owner, struct ast_channel *peer_owner)
-{
-	struct brcm_pvt *p = sub->parent;
-
-	ast_log(LOG_ERROR ,"flashSpec  sub_peer->conf_timer_id: %d, sub->conf_timer_id: %d\n", sub_peer->conf_timer_id, sub->conf_timer_id);
-	if((sub_peer->conf_timer_id != -1) || (sub->conf_timer_id != -1)) {
-		ast_log(LOG_NOTICE ,"Setting up unattended call transfer \n");
-		if(sub->conf_timer_id != -1) {
-			if (ast_sched_del(sched, sub->conf_timer_id))
-				ast_log(LOG_ERROR, "Failed to remove scheduled conference setup timer\n");
-			ast_debug(4, "sub->conf_timer_id deleted\n");
-		}
-		sub->conf_timer_id = -1;
-		if(sub_peer->conf_timer_id != -1) {
-			if (ast_sched_del(sched, sub_peer->conf_timer_id))
-				ast_log(LOG_ERROR, "Failed to remove scheduled conference setup timer\n");
-			ast_debug(4, "sub_peer->conf_timer_id deleted\n");
-		}
-		sub_peer->conf_timer_id = -1;
-
-		channel_settings *s = &channel_config[p->line_id];
-		if (!s->calleridenable) {
-			p->tech->stop_ringing(p);
-		} else {
-			p->tech->stop_ringing_callerid_pending(p);
-		}
-
-		// unattended call transfer: cancel the the call to transfer target
-		if (sub->owner && sub_peer->owner) {
-			strncpy(sub_peer->blind_xfer_target, ast_channel_exten(owner), sizeof(sub->blind_xfer_target) - 1);
-			ast_queue_control(sub->owner, AST_CONTROL_HANGUP);
-			ast_queue_unhold(sub_peer->owner);
-			sub_peer->channel_state = TRANSFERING;
-		}
-	}
-	else
-		ast_log(LOG_ERROR,"Late R5 ,Ignoring since conference should be set up by now \n");
-}
-
-static int brcm_close_connection(struct brcm_subchannel *sub)
-{
-	struct brcm_pvt *p = sub->parent;
-
-	if (sub->connection_init) {
-		if (!brcm_in_onhold(p) && !brcm_in_call(p) && !brcm_in_dialing(p) && !brcm_in_ringback(p) &&
-			!brcm_in_callwaiting(p) && !brcm_in_transferring(p)) { // Does the line have another call?
-			ast_debug(1, "Closing real endpoint connection line_id: %d, connection_id=%d, call_id: %d\n", p->line_id, sub->connection_id, sub->call_id);
-			endpt_connection(p->line_id, sub->call_id, "destroy");
-		} else {
-			ast_debug(1, "Releasing connection for pvt line_id=%i connection_id=%d, call_id: %d\n",
-				sub->parent->line_id, sub->connection_id, sub->call_id);
-			endpt_connection(p->line_id, sub->call_id, "release");
-		}
-		sub->connection_init = 0;
-		sub->codec = -1;
-		sub->call_id = CALLID_INVALID;
-		ast_debug(1, "Virtual Asterisk connection %d/%d destroyed\n", p->line_id, sub->connection_id);
-	}
-
-	return 0;
-}
-
-
-/* Generate rtp payload, 12 bytes of header and 160 bytes of ulaw payload */
-static void brcm_generate_rtp_packet(struct brcm_subchannel *sub, uint8_t *packet_buf, int type, int marker, int dtmf_timestamp, int seqno) {
-	unsigned short* packet_buf16 = (unsigned short*)packet_buf;
-	unsigned int*   packet_buf32 = (unsigned int*)packet_buf;
-
-	//Generate the rtp header, packet is zero from the start, that fact is used
-	packet_buf[0] |= 0x80; //Set version 2 of header
-	//Padding 0
-	//Extension 0
-	//CSRC count 0
-	packet_buf[1] = type;
-	packet_buf[1] |= marker?0x80:0x00;
-	packet_buf16[1] = htons(seqno); //Add sequence number
-	packet_buf32[1] = htonl(sub->time_stamp);	//Add timestamp
-	sub->time_stamp += sub->period*8;
-	packet_buf32[2] = sub->ssrc;	//Random SSRC
-}
-
-static void brcm_interpret_rtcp_packet(struct brcm_subchannel *p, uint8_t *rtcp_frame, uint32_t rtcp_size) {
-	unsigned int *rtcp_word = (unsigned int *)(rtcp_frame); // 32 bits packet
-	unsigned int packetwords = rtcp_size / 4; // number of packets
-	unsigned int position = 0;
-	unsigned int pt;
-
-	while (position < packetwords) {
-		unsigned int temp_word = ntohl(rtcp_word[position]);
-		pt = (temp_word >> 16) & 0xFF;
-		switch (pt) {
-			case RTCP_SR:
-				p->jitter_count++;
-				p->farEndInterrivalJitter += ntohl(rtcp_word[position+10]);
-				/* Intentional fall through */
-			case RTCP_RR:
-			case RTCP_SDES:
-			case RTCP_XR:
-				//replacing ssrc
-				rtcp_word[position + 1] = p->ssrc;
-				break;
-			default:
-				break;
-			}
-		position++;
-	}
-}
-
-static void brcm_dialtone_set(struct brcm_pvt *p, dialtone_state state)
-{
-	ast_debug(3, "Old dialtone: %s, new dialtone: %s\n",
-			dialtone_map[p->dialtone].str, dialtone_map[state].str);
-
-	if (state != p->dialtone) {
-		ast_debug(2, "Changing dialtone for pvt %d from '%s' to '%s'\n",
-			p->line_id,
-			dialtone_map[p->dialtone].str,
-			dialtone_map[state].str);
-		p->dialtone = state;
-		brcm_signal_dialtone(p);
-	}
-}
-
-static const char *feature_access_code_string(char *buffer, unsigned int buffer_length)
-{
-	struct feature_access_code *current;
-
-	if (AST_LIST_EMPTY(&feature_access_codes)) {
-		strncpy(buffer, "(empty)", buffer_length);
-		return buffer;
-	}
-
-	buffer[0] = '\0';
-	int write_length = 0;
-	AST_LIST_TRAVERSE(&feature_access_codes, current, list) {
-		int rv = snprintf(buffer + write_length, buffer_length - write_length, "%s ", current->code);
-		if (rv <= 0) {
-			break;
-		}
-		write_length += rv;
-	}
-
-	return buffer;
-}
-
-static int feature_access_code_add(const char *code)
-{
-	struct feature_access_code *fac;
-
-	if (ast_strlen_zero(code)) {
-		ast_log(LOG_WARNING, "Zero length FAC\n");
-		return 1;
-	}
-
-	if (!(fac = ast_calloc(1, sizeof(*fac)))) {
-		ast_log(LOG_WARNING, "FAC alloc failed\n");
-		return 1;
-	}
-
-	ast_copy_string(fac->code, code, sizeof(fac->code));
-	ast_log(LOG_DEBUG, "Adding FAC: [%s]\n", fac->code);
-
-	AST_LIST_INSERT_TAIL(&feature_access_codes, fac, list);
-	return 0;
-}
-
-static int feature_access_code_clear(void)
-{
-	struct feature_access_code *fac;
-
-	while ((fac = AST_LIST_REMOVE_HEAD(&feature_access_codes, list))) {
-		ast_free(fac);
-	}
-	return 0;
-}
-
-static int feature_access_code_match(char *sequence)
-{
-	struct feature_access_code *current;
-	int retval = -1;
-
-	AST_LIST_TRAVERSE(&feature_access_codes, current, list) {
-		char *seq = sequence;
-		char *fac = current->code;
-
-		int res = -1;
-		for (; *seq && *fac; seq++, fac++) {
-			if (*fac == '.') {
-				/* Perfect match */
-				return 0;
-			}
-			else if (*seq == *fac) {
-				/* Partial match */
-				res = 1;
-			}
-			else {
-				/* No match */
-				res = -1;
-				break;
-			}
-		}
-
-		if (res == 1 && *seq == *fac) {
-			/* Perfect match */
-			return 0;
-		}
-
-		if (res != -1) {
-			retval = res;
-		}
-	}
-
-	return retval;
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Broadcom SLIC channel");
diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h
deleted file mode 100644
index c592e0a246..0000000000
--- a/channels/chan_brcm.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/* Inteno AB, Stockholm, Sweden
- * Channel for Broadcom FXS ports
- */
-
-#ifndef CHAN_BRCM_H
-#define CHAN_BRCM_H
-
-/* Change this value when needed */
-#define CHANNEL_VERSION "1.2"
-
-#define DEFAULT_CALLER_ID "Unknown"
-#define PHONE_MAX_BUF 480
-#define CALL_STATUS_MAX_LEN 14
-
-#define TIMEMSEC 1000
-
-#define PCMU 0
-#define G726 2
-#define G723 4
-#define PCMA 8
-#define G729 18
-#define G722 9
-#define DTMF_PAYLOAD 101
-#define DTMF 128
-#define RTCP_SR      200
-#define RTCP_RR      201
-#define RTCP_SDES    202
-#define RTCP_XR      207
-
-#define CN 13
-
-#define NOT_INITIALIZED -1
-//#define EPSTATUS_DRIVER_ERROR -1
-#define MAX_NUM_LINEID 30
-#define PACKET_BUFFER_SIZE 1024
-#define NUM_SUBCHANNELS 2
-
-#define BEGIN 0
-#define CONT  1
-#define END   2
-
-enum brcm_channel_state {
-	ONHOOK,
-	OFFHOOK,
-	DIALING,
-	CALLING,
-	INCALL,
-	ANSWER,
-	CALLENDED,
-	RINGING,
-	CALLWAITING,
-	ONHOLD,
-	TRANSFERING,
-	RINGBACK,
-	AWAITONHOOK,
-	ALLOCATED,
-};
-
-enum LINE_EVENT {																// Events from low level line (endpoint etc.)
-	EVENT_DTMF0,
-	EVENT_DTMF1,
-	EVENT_DTMF2,
-	EVENT_DTMF3,
-	EVENT_DTMF4,
-	EVENT_DTMF5,
-	EVENT_DTMF6,
-	EVENT_DTMF7,
-	EVENT_DTMF8,
-	EVENT_DTMF9,
-	EVENT_DTMFA,
-	EVENT_DTMFB,
-	EVENT_DTMFC,
-	EVENT_DTMFD,
-	EVENT_DTMFH,
-	EVENT_DTMFS,
-	EVENT_OFFHOOK,
-	EVENT_ONHOOK,
-	EVENT_FLASH,
-	EVENT_CALL_REJECT,
-	EVENT_DECT_UNAVAILABLE,
-	EVENT_SWITCH,
-	EVENT_JOIN,
-	EVENT_RELEASE,
-	EVENT_LAST,
-};
-
-enum endpoint_type {
-	FXS,
-	FXO,
-	DECT,
-};
-
-enum CALL_DIRECTION {
-	INCOMING_CALL,
-	OUTGOING_CALL,
-};
-
-typedef enum dialtone_state {
-	DIALTONE_OFF = 0,
-	DIALTONE_ON,
-	DIALTONE_CONGESTION,
-	DIALTONE_SPECIAL_CONDITION,
-	DIALTONE_UNOBTAINABLE,
-	DIALTONE_HOWLER,
-	DIALTONE_UNKNOWN,
-	DIALTONE_MWI_OFF,
-	DIALTONE_LAST,
-} dialtone_state;
-
-typedef enum callid_state {
-	CALLID_INVALID = -1,
-	CALLID_OBTAINING = 0,
-	CALLID_ESTABLISHED = 1
-} callid_state;
-
-struct brcm_subchannel {
-	int id;
-	int call_id;			/* The call_id of connection assigned by pjsip */
-	struct ast_channel *owner;	/* Channel we belong to, possibly NULL */
-	int connection_id;		/* Current connection id, may be -1 */
-	enum brcm_channel_state channel_state;	/* Channel states */
-	enum CALL_DIRECTION call_direction;		// Direction of call for the subchannel : 0 = incoming, 1 = outgoing
-	unsigned int connection_init;	/* State for endpoint id connection initialization */
-	struct ast_frame fr;		/* Frame */
-	unsigned int time_stamp;	/* Endpoint RTP time stamp state */
-	unsigned int period;		/* Endpoint RTP period */
-	unsigned int ssrc;		/* Endpoint RTP synchronization source */
-	int codec;			/* Used codec */
-	struct brcm_pvt *parent;	/* brcm_line owning this subchannel */
-	int cw_timer_id;		/* Current call waiting timer id, -1 if no active timer */
-	int cwBeep_timer_id;		/* Current call waiting beep timer id, -1 if no active timer */
-	int r4_hangup_timer_id;		/* Current R4 hangup timer id, -1 if no active timer */
-	int onhold_hangup_timer_id;	/* Current onhold hangup timer id, -1 if no active timer */
-	int conference_initiator;       /* True if this subchannel is the original leg in a 3-way conference */
-	char *conference_id;            /* uuid of the conference initiated by this subchannel */
-	int conf_timer_id;              /* Current conference call timer id, -1 if no active timer */
-	rtp_statistics rtp_stats;	/* RTP statistics for currently hanging up channel */
-	unsigned int jitter_count;
-	unsigned long int farEndInterrivalJitter;
-	char blind_xfer_target[32];	/* Transfer target for unattended call transfer */
-};
-
-
-struct brcm_channel_tech {
-	int (* signal_ringing)(struct brcm_pvt *p);
-	int (* signal_ringing_callerid_pending)(struct brcm_pvt *p);
-	int (* signal_callerid)(struct ast_channel *chan, struct brcm_subchannel *s);
-	int (* stop_ringing)(struct brcm_pvt *p);
-	int (* stop_ringing_callerid_pending)(struct brcm_pvt *p);
-	int (* release)(struct brcm_pvt *p);
-};
-
-
-struct brcm_pvt {
-	ast_mutex_t lock;
-	int fd;							/* Raw file descriptor for this device */
-	int line_id;				/* Maps to the correct port */
-	char dtmfbuf[AST_MAX_EXTENSION];/* DTMF buffer per channel */
-	int dtmf_len;					/* Length of DTMF buffer */
-	int dtmf_first;					/* DTMF control state, button pushes generate 2 events, one on button down and one on button up */
-	struct ast_format_cap * lastformat;            /* Last output format */
-	struct ast_format_cap * lastinput;             /* Last input format */
-	struct brcm_pvt *next;			/* Next channel in list */
-	char offset[AST_FRIENDLY_OFFSET];
-	char buf[PHONE_MAX_BUF];					/* Static buffer for reading frames */
-	char context_direct[AST_MAX_EXTENSION];
-	char context[AST_MAX_EXTENSION];
-	char obuf[PHONE_MAX_BUF * 2];
-	char ext[AST_MAX_EXTENSION];
-	char language[MAX_LANGUAGE];
-	char cid_num[AST_MAX_EXTENSION];
-	char cid_name[AST_MAX_EXTENSION];
-	char extensionCallStatus[CALL_STATUS_MAX_LEN];
-
-	struct brcm_subchannel *sub[NUM_SUBCHANNELS];	/* List of sub-channels, needed for callwaiting and 3-way support */
-	int hf_detected;			/* Hook flash detected */
-	dialtone_state dialtone;		/* Set by manager command */
-	struct brcm_channel_tech *tech;
-
-	int interdigit_timer_id;		/* Id of timer that tracks interdigit timeout */
-	int autodial_timer_id;			/* Id of timer that tracks autodial timeout */
-	int dialtone_timeout_timer_id;	/* Id of timer that tracks dialtone timeout */
-	int onhold_hangup_timer_id;		/* Id of timer that tracks onhold hangup timeout */
-};
-
-enum rtp_type {
-	BRCM_UNKNOWN,
-	BRCM_AUDIO,
-	BRCM_RTCP_SR,
-	BRCM_RTCP_RR
-};
-
-
-
-/* Mapping of DTMF to char/name/intval */
-typedef struct DTMF_CHARNAME_MAP
-{
-	enum LINE_EVENT	event;
-	char	name[12];
-	char	c;
-	int		i;
-} DTMF_CHARNAME_MAP;
-
-
-typedef enum flash_spec {
-	FLASH_SPEC_UK = 0,
-	FLASH_SPEC_ETSI,
-} flash_spec;
-
-typedef struct DIALTONE_MAP
-{
-	dialtone_state	state;
-	char		str[24];
-} DIALTONE_MAP;
-
-static const DIALTONE_MAP dialtone_map[] =
-{
-	{DIALTONE_OFF,		"off"},
-	{DIALTONE_ON,		"on"},
-	{DIALTONE_CONGESTION,	"congestion"},
-	{DIALTONE_SPECIAL_CONDITION, "special"},
-	{DIALTONE_UNOBTAINABLE, "number unobtainable"},
-	{DIALTONE_HOWLER, "howler"},
-	{DIALTONE_UNKNOWN,	"unknown"},
-	{DIALTONE_LAST,		"-"},
-};
-
-/* Struct for individual endpoint settings */
-typedef struct {
-	int enabled;
-	char language[MAX_LANGUAGE];
-	char cid_num[AST_MAX_EXTENSION];
-	char cid_name[AST_MAX_EXTENSION];
-	char context_direct[AST_MAX_EXTENSION]; //Context that will be checked for exact matches
-	char context[AST_MAX_EXTENSION]; //Default context for dialtone mode
-	char autodial_ext[AST_MAX_EXTENSION];
-	int autodial_timeoutmsec;
-	int ringsignal;
-	int timeoutmsec;
-        int interdigitopenmsec;
-        int minimumnumberdigits;
-        char terminationdigit;
-	int period;
-	int hangup_xfer;
-	int dialtone_timeoutmsec;
-	int offhook_nu_timeoutmsec;
-	int offhook_silence_timeoutmsec;
-	int do_not_disturb;
-	int anonymouscallenable;
-        int calleridenable;
-        int calleridnameenable;
-	flash_spec flashSpec;
-	int mwi_enabled;
-} channel_settings;
-
-
-/* Caller ID */
-#define CLID_MAX_DATE	10
-#define CLID_MAX_NUMBER	21
-#define CLID_MAX_NAME	16
-typedef struct CLID_STRING
-{
-	char date[CLID_MAX_DATE];
-	char number_name[CLID_MAX_NUMBER + CLID_MAX_NAME + 4]; // 4 = comma, quotation marks and null terminator
-} CLID_STRING;
-
-
-/* Global jitterbuffer configuration - by default, jb is disabled */
-static struct ast_jb_conf default_jbconf =
-{
-	.flags = 0,
-	.max_size = -1,
-	.resync_threshold = -1,
-	.impl = "",
-	.target_extra = -1,
-};
-
-
-#define DEFAULT_CALL_WAITING_TIMEOUT 20 // In seconds
-#define DEFAULT_CALL_WAITING_BEEP_FREQ 5 // In seconds
-
-#define DEFAULT_R4_HANGUP_TIMEOUT 5000 // In milliseconds
-#define DEFAULT_ONHOLD_HANGUP_TIMEOUT 20 // In seconds
-
-
-#endif /* CHAN_BRCM_H */
diff --git a/configs/brcm.conf.sample b/configs/brcm.conf.sample
deleted file mode 100644
index fb80497c1a..0000000000
--- a/configs/brcm.conf.sample
+++ /dev/null
@@ -1,50 +0,0 @@
-;
-; Linux Telephony Interface
-;
-; Configuration file
-;
-[interfaces]
-;
-; Select a mode, either the phone jack provides dialtone, reads digits,
-; then starts PBX with the given extension (dialtone mode), or
-; immediately provides the PBX without reading any digits or providing
-; any dialtone (this is the immediate mode, the default).  Also, you
-; can set the mode to "fxo" if you have a linejack to make it operate
-; properly.
-;
-mode=immediate
-;mode=dialtone
-;mode=fxo
-;
-; You can decide which format to use by default, "g723.1" or "slinear".
-; XXX Be careful, sometimes the card causes kernel panics when running
-; in signed linear mode for some reason... XXX
-;
-;format=slinear
-format=g723.1
-;
-; And set the echo cancellation to "off", "low", "medium", and "high".
-; This is not supported on all phones.
-;
-echocancel=medium
-;
-; You can optionally use VAD/CNG silence supression
-;
-;silencesupression=yes
-;
-; List all devices we can use.  Contexts may also be specified
-;
-;context=local
-;
-; You can set txgain and rxgain for each device in the same way as context.
-; If you want to change default gain value (1.0 =~ 100%) for device, simple
-; add txgain or rxgain line before device line. But rememeber, if you change
-; volume all cards listed below will be affected by these values. You can
-; use float values (1.0, 0.5, 2.0) or percentage values (100%, 150%, 50%).
-;
-;txgain=100%
-;rxgain=1.0
-device => /dev/bcmendpoint0
-
-
-
diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h
index 32509bdd2f..d421e36a56 100644
--- a/include/asterisk/cdr.h
+++ b/include/asterisk/cdr.h
@@ -271,7 +271,7 @@ struct ast_cdr_config {
 	} batch_settings;
 };
 
-/*! \brief Struct for rtp statistics get from brcm */
+/*! \brief Struct for rtp statistics get from voicemngr */
 typedef struct {
 	uint16_t localBurstDensity;
 	uint16_t remoteBurstDensity;
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 60b03244c7..2843de513f 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -597,7 +597,7 @@ typedef struct {
 	const char *value;
 } ast_chan_write_info_t;
 
-/*! \brief Struct for rtp statistics get from brcm */
+/*! \brief Struct for rtp statistics get from voicemngr */
 typedef struct {
 	uint16_t localBurstDensity;
 	uint16_t remoteBurstDensity;
-- 
GitLab