diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c
index 10da1da92b14c95b362a7ba486ada997029ab315..b263432fb538689f4d2a483dc1f9330db275307e 100644
--- a/channels/chan_brcm.c
+++ b/channels/chan_brcm.c
@@ -210,6 +210,8 @@ 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;
+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
 
@@ -536,7 +538,9 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat
 			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;
-			brcm_finish_transfer(ast, sub, *message);
+                        struct brcm_subchannel* peer_sub;
+                        peer_sub = brcm_subchannel_get_peer(sub);
+			brcm_finish_transfer(ast, peer_sub, *message);
 		}
 		break;
 	case AST_CONTROL_CONGESTION:
@@ -903,6 +907,13 @@ static int brcm_hangup(struct ast_channel *ast)
 		sub->cw_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->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");
@@ -1407,6 +1418,42 @@ static struct brcm_subchannel *brcm_get_onhold_subchannel(const struct brcm_pvt
 	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;
+    struct brcm_subchannel *sub_peer;
+    struct ast_channel *peer_owner;
+    struct ast_channel *owner = NULL;
+
+    sub = (struct brcm_subchannel *) data;
+    sub_peer = brcm_subchannel_get_peer(sub);
+    struct brcm_pvt *p = sub->parent;
+    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;
+    }
+    /* Setup conference if no dtmf is pressed after flash ,i.e we are not waiting for dtmf now*/
+    // Unhold inactive subchannel //
+    brcm_create_conference(p);
+    if (peer_owner) {
+        brcm_unmute_connection(sub_peer);
+        ast_queue_unhold(peer_owner);
+        send_ubus_event("UNHOLD",sub->parent->line_id);
+        sub_peer->channel_state = INCALL;
+    }
+    sub->channel_state = ONHOLD;
+    if (ast_sched_del(sched, sub->conf_timer_id)) {
+        ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n");
+    }
+    sub->cw_timer_id = -1;
+    return 0;
+}
+
 /* Hangup incoming call after call waiting times out */
 static int cwtimeout_cb(const void *data)
 {
@@ -1744,7 +1791,6 @@ static void handle_hookflash(struct brcm_subchannel *sub, struct brcm_subchannel
 	struct brcm_pvt *p = sub->parent;
 
 	ast_log(LOG_DTMF, "Hook Flash detected for phone line %d\r\n", sub->parent->line_id);
-
         struct ast_bridge *bridge;
 	struct ast_bridge_channel *bridge_channel;
 	
@@ -1763,7 +1809,6 @@ static void handle_hookflash(struct brcm_subchannel *sub, struct brcm_subchannel
 		p->hf_detected = 0;
 		return;
 	}
-
 	if (p->dtmf_first < 0) {
 		/* 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)) {
@@ -1857,7 +1902,7 @@ static void handle_hookflash(struct brcm_subchannel *sub, struct brcm_subchannel
 			   ast_queue_hold(owner, NULL);
 		        }
 		    if (sub_peer->channel_state == CALLWAITING) {
-			ast_log(LOG_NOTICE, " R2 Call waiting\n");
+			ast_log(LOG_NOTICE, " R in Call waiting\n");
 			/* Stop call waiting tone on current call */
 			brcm_stop_callwaiting(p);
 			/* Cancel timer */
@@ -1873,25 +1918,71 @@ static void handle_hookflash(struct brcm_subchannel *sub, struct brcm_subchannel
 			if (peer_owner) {
 				ast_queue_control(peer_owner, AST_CONTROL_ANSWER);
 				sub_peer->channel_state = INCALL;
+                                sub->channel_state = ONHOLD;
 			}
 		    } else if (sub_peer->channel_state == ONHOLD) {
-			ast_log(LOG_NOTICE, " R2 on hold\n");
-			/* Unhold inactive subchannel */
-                        brcm_create_conference(p);
-			if (peer_owner) {
-				brcm_unmute_connection(sub_peer);
-				ast_queue_unhold(peer_owner);
-                                send_ubus_event("UNHOLD",sub->parent->line_id);
-				sub_peer->channel_state = INCALL;
-			}
-		    }
-		   sub->channel_state = ONHOLD;
+			ast_log(LOG_NOTICE, "R on hold\n");
+			sub->conf_timer_id = ast_sched_add(sched, dtmf_wait_timer, setup_conference_call_cb, sub);
 
-              }
-              p->hf_detected = 0;
-	      return;
+                    }
+                }
         }
-	brcm_reset_dtmf_buffer(p);
+		
+        if (p->dtmf_first > 0) {
+            switch (p->dtmf_first) {
+                case '4':
+                    if (ast_sched_del(sched, sub->conf_timer_id)) {
+                        ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n");
+                    }
+                    sub_peer->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");
+                        }
+                    }
+                    break;
+
+                default:
+                    ast_log(LOG_ERROR, "Unhandled DTMF %c\n", p->dtmfbuf[0]);
+                    break;
+
+            }
+        }
+        brcm_reset_dtmf_buffer(p);
 }
 
 static void handle_dtmf(enum LINE_EVENT event,
@@ -2345,7 +2436,8 @@ static void *brcm_process_event(struct endpt_event *ev) {
 
 			sub->channel_state = ONHOOK;
 			brcm_cancel_dialing_timeouts(p);
-
+                        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;
@@ -2485,6 +2577,7 @@ static struct brcm_pvt *brcm_allocate_pvt(void)
 				sub->codec = -1;
 				sub->parent = tmp;
 				sub->cw_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
diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h
index b94d28f64b358f792027eaf08c9d194c537ae218..5e1eca20d0733d234b886497c4aaaf48d4b84cc6 100644
--- a/channels/chan_brcm.h
+++ b/channels/chan_brcm.h
@@ -111,6 +111,7 @@ struct brcm_subchannel {
 	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 */
 };