Bluetooth: RFCOMM: Respond to RLS command

If remote sends RLS command then it should be responded with the
value received.

> ACL Data RX: Handle 256 flags 0x02 dlen 12
      Channel: 64 len 8 [PSM 3 mode 0] {chan 0}
      RFCOMM: Unnumbered Info with Header Check (UIH) (0xef)
         Address: 0x03 cr 1 dlci 0x00
         Control: 0xef poll/final 0
         Length: 4
         FCS: 0x70
         MCC Message type: Remote Line Status CMD (0x14)
           Length: 2
           dlci 10 error: 5

< ACL Data TX: Handle 256 flags 0x00 dlen 12
      Channel: 64 len 8 [PSM 3 mode 0] {chan 0}
      RFCOMM: Unnumbered Info with Header Check (UIH) (0xef)
         Address: 0x01 cr 0 dlci 0x00
         Control: 0xef poll/final 0
         Length: 4
         FCS: 0xaa
         MCC Message type: Remote Line Status RSP (0x14)
           Length: 2
           dlci 10 error: 5

Change-Id: Ib70e02aede2088bca748d1eb68bee9b1bc47a65d
Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
diff --git a/subsys/bluetooth/host/rfcomm.c b/subsys/bluetooth/host/rfcomm.c
index 5795a65..594cfb1 100644
--- a/subsys/bluetooth/host/rfcomm.c
+++ b/subsys/bluetooth/host/rfcomm.c
@@ -580,6 +580,26 @@
 	return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
 }
 
+static int rfcomm_send_rls(struct bt_rfcomm_dlc *dlc, uint8_t cr,
+			   uint8_t line_status)
+{
+	struct bt_rfcomm_rls *rls;
+	struct net_buf *buf;
+	uint8_t fcs;
+
+	buf = rfcomm_make_uih_msg(dlc, cr, BT_RFCOMM_RLS, sizeof(*rls));
+
+	rls = net_buf_add(buf, sizeof(*rls));
+	/* cr bit should be always 1 in RLS */
+	rls->dlci = BT_RFCOMM_SET_ADDR(dlc->dlci, 1);
+	rls->line_status = line_status;
+
+	fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
+	net_buf_add_u8(buf, fcs);
+
+	return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
+}
+
 static void rfcomm_dlc_connected(struct bt_rfcomm_dlc *dlc)
 {
 	dlc->state = BT_RFCOMM_STATE_CONNECTED;
@@ -893,6 +913,29 @@
 	}
 }
 
+static void rfcomm_handle_rls(struct bt_rfcomm_session *session,
+			      struct net_buf *buf, uint8_t cr)
+{
+	struct bt_rfcomm_rls *rls = (void *)buf->data;
+	uint8_t dlci = BT_RFCOMM_GET_DLCI(rls->dlci);
+	struct bt_rfcomm_dlc *dlc;
+
+	BT_DBG("dlci %d", dlci);
+
+	if (!cr) {
+		/* Ignore if its a response */
+		return;
+	}
+
+	dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
+	if (!dlc) {
+		return;
+	}
+
+	/* As per the ETSI same line status has to returned in the response */
+	rfcomm_send_rls(dlc, BT_RFCOMM_MSG_RESP_CR, rls->line_status);
+}
+
 static void rfcomm_handle_pn(struct bt_rfcomm_session *session,
 			     struct net_buf *buf, uint8_t cr)
 {
@@ -989,6 +1032,9 @@
 	case BT_RFCOMM_MSC:
 		rfcomm_handle_msc(session, buf, cr);
 		break;
+	case BT_RFCOMM_RLS:
+		rfcomm_handle_rls(session, buf, cr);
+		break;
 	default:
 		BT_WARN("Unknown/Unsupported RFCOMM Msg type 0x%02x", msg_type);
 		break;
diff --git a/subsys/bluetooth/host/rfcomm_internal.h b/subsys/bluetooth/host/rfcomm_internal.h
index 9733f65..5f44946 100644
--- a/subsys/bluetooth/host/rfcomm_internal.h
+++ b/subsys/bluetooth/host/rfcomm_internal.h
@@ -77,6 +77,12 @@
 #define BT_RFCOMM_DISC  0x43
 #define BT_RFCOMM_DM    0x0f
 
+#define BT_RFCOMM_RLS   0x14
+struct bt_rfcomm_rls {
+	uint8_t  dlci;
+	uint8_t  line_status;
+} __packed;
+
 /* DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 */
 #define BT_RFCOMM_DEFAULT_V24_SIG 0x8d