Bluetooth: RFCOMM: Respond to RPN command
Peer sends Remote Port Negotiation command to set port communication settings. Currently we accept all the settings sent by remote. If there is only one value byte in the request then current port settings has to be returned for which we returns the default settings defined in ETSI. Note that RPN may be sent even before a dlc is opened. > ACL Data RX: Handle 256 flags 0x02 dlen 18 Channel: 64 len 14 [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: 10 FCS: 0x70 MCC Message type: Remote Port Negotiation Command CMD (0x24) Length: 8 dlci 10 br 3 db 2 sb 0 p 0 pt 0 xi 0 xo 0 rtri 0 rtro 0 rtci 0 rtco 0 xon 17 xoff 19 pm 0x3f7f < ACL Data TX: Handle 256 flags 0x00 dlen 18 Channel: 64 len 14 [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: 10 FCS: 0xaa MCC Message type: Remote Port Negotiation Command RSP (0x24) Length: 8 dlci 10 br 3 db 2 sb 0 p 0 pt 0 xi 0 xo 0 rtri 0 rtro 0 rtci 0 rtco 0 xon 17 xoff 19 pm 0x3f7f Change-Id: I73b7d8577e7e2bc3e436f4db86a91e12db440f1f Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
This commit is contained in:
parent
61f34fd966
commit
c7346c4c93
2 changed files with 92 additions and 0 deletions
|
@ -602,6 +602,22 @@ static int rfcomm_send_rls(struct bt_rfcomm_dlc *dlc, uint8_t cr,
|
|||
return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
|
||||
}
|
||||
|
||||
static int rfcomm_send_rpn(struct bt_rfcomm_session *session, uint8_t cr,
|
||||
struct bt_rfcomm_rpn *rpn)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
uint8_t fcs;
|
||||
|
||||
buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_RPN, sizeof(*rpn));
|
||||
|
||||
memcpy(net_buf_add(buf, sizeof(*rpn)), rpn, sizeof(*rpn));
|
||||
|
||||
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
|
||||
net_buf_add_u8(buf, fcs);
|
||||
|
||||
return bt_l2cap_chan_send(&session->br_chan.chan, buf);
|
||||
}
|
||||
|
||||
static void rfcomm_dlc_connected(struct bt_rfcomm_dlc *dlc)
|
||||
{
|
||||
dlc->state = BT_RFCOMM_STATE_CONNECTED;
|
||||
|
@ -938,6 +954,52 @@ static void rfcomm_handle_rls(struct bt_rfcomm_session *session,
|
|||
rfcomm_send_rls(dlc, BT_RFCOMM_MSG_RESP_CR, rls->line_status);
|
||||
}
|
||||
|
||||
static void rfcomm_handle_rpn(struct bt_rfcomm_session *session,
|
||||
struct net_buf *buf, uint8_t cr)
|
||||
{
|
||||
struct bt_rfcomm_rpn default_rpn, *rpn = (void *)buf->data;
|
||||
uint8_t dlci = BT_RFCOMM_GET_DLCI(rpn->dlci);
|
||||
uint8_t data_bits, stop_bits, parity_bits;
|
||||
/* Exclude fcs to get number of value bytes */
|
||||
uint8_t value_len = buf->len - 1;
|
||||
|
||||
BT_DBG("dlci %d", dlci);
|
||||
|
||||
if (!cr) {
|
||||
/* Ignore if its a response */
|
||||
return;
|
||||
}
|
||||
|
||||
if (value_len == sizeof(*rpn)) {
|
||||
/* Accept all the values proposed by the sender */
|
||||
rpn->param_mask = sys_cpu_to_le16(BT_RFCOMM_RPN_PARAM_MASK_ALL);
|
||||
rfcomm_send_rpn(session, BT_RFCOMM_MSG_RESP_CR, rpn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value_len != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If only one value byte then current port settings has to be returned
|
||||
* We will send default values
|
||||
*/
|
||||
default_rpn.dlci = BT_RFCOMM_SET_ADDR(dlci, 1);
|
||||
default_rpn.baud_rate = BT_RFCOMM_RPN_BAUD_RATE_9600;
|
||||
default_rpn.flow_control = BT_RFCOMM_RPN_FLOW_NONE;
|
||||
default_rpn.xoff_char = BT_RFCOMM_RPN_XOFF_CHAR;
|
||||
default_rpn.xon_char = BT_RFCOMM_RPN_XON_CHAR;
|
||||
data_bits = BT_RFCOMM_RPN_DATA_BITS_8;
|
||||
stop_bits = BT_RFCOMM_RPN_STOP_BITS_1;
|
||||
parity_bits = BT_RFCOMM_RPN_PARITY_NONE;
|
||||
default_rpn.line_settings = BT_RFCOMM_SET_LINE_SETTINGS(data_bits,
|
||||
stop_bits,
|
||||
parity_bits);
|
||||
default_rpn.param_mask = sys_cpu_to_le16(BT_RFCOMM_RPN_PARAM_MASK_ALL);
|
||||
|
||||
rfcomm_send_rpn(session, BT_RFCOMM_MSG_RESP_CR, &default_rpn);
|
||||
}
|
||||
|
||||
static void rfcomm_handle_pn(struct bt_rfcomm_session *session,
|
||||
struct net_buf *buf, uint8_t cr)
|
||||
{
|
||||
|
@ -1037,6 +1099,9 @@ static void rfcomm_handle_msg(struct bt_rfcomm_session *session,
|
|||
case BT_RFCOMM_RLS:
|
||||
rfcomm_handle_rls(session, buf, cr);
|
||||
break;
|
||||
case BT_RFCOMM_RPN:
|
||||
rfcomm_handle_rpn(session, buf, cr);
|
||||
break;
|
||||
default:
|
||||
BT_WARN("Unknown/Unsupported RFCOMM Msg type 0x%02x", msg_type);
|
||||
break;
|
||||
|
|
|
@ -83,6 +83,33 @@ struct bt_rfcomm_rls {
|
|||
uint8_t line_status;
|
||||
} __packed;
|
||||
|
||||
#define BT_RFCOMM_RPN 0x24
|
||||
struct bt_rfcomm_rpn {
|
||||
uint8_t dlci;
|
||||
uint8_t baud_rate;
|
||||
uint8_t line_settings;
|
||||
uint8_t flow_control;
|
||||
uint8_t xon_char;
|
||||
uint8_t xoff_char;
|
||||
uint16_t param_mask;
|
||||
} __packed;
|
||||
|
||||
/* Default RPN Settings */
|
||||
#define BT_RFCOMM_RPN_BAUD_RATE_9600 0x03
|
||||
#define BT_RFCOMM_RPN_DATA_BITS_8 0x03
|
||||
#define BT_RFCOMM_RPN_STOP_BITS_1 0x00
|
||||
#define BT_RFCOMM_RPN_PARITY_NONE 0x00
|
||||
#define BT_RFCOMM_RPN_FLOW_NONE 0x00
|
||||
#define BT_RFCOMM_RPN_XON_CHAR 0x11
|
||||
#define BT_RFCOMM_RPN_XOFF_CHAR 0x13
|
||||
|
||||
/* Set 1 to all the param mask except reserved */
|
||||
#define BT_RFCOMM_RPN_PARAM_MASK_ALL 0x3f7f
|
||||
|
||||
#define BT_RFCOMM_SET_LINE_SETTINGS(data, stop, parity) ((data & 0x3) | \
|
||||
((stop & 0x1) << 2) | \
|
||||
((parity & 0x7) << 3))
|
||||
|
||||
/* DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 */
|
||||
#define BT_RFCOMM_DEFAULT_V24_SIG 0x8d
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue