zephyr/subsys/bluetooth/host/classic/rfcomm.c

1795 lines
43 KiB
C
Raw Normal View History

/* rfcomm.c - RFCOMM handling */
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <string.h>
#include <errno.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/util.h>
#include <zephyr/debug/stack.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/l2cap.h>
#include <zephyr/bluetooth/classic/rfcomm.h>
#include "host/hci_core.h"
#include "host/conn_internal.h"
#include "l2cap_br_internal.h"
#include "rfcomm_internal.h"
#define LOG_LEVEL CONFIG_BT_RFCOMM_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_rfcomm);
#define RFCOMM_CHANNEL_START 0x01
#define RFCOMM_CHANNEL_END 0x1e
#define RFCOMM_MIN_MTU BT_RFCOMM_SIG_MIN_MTU
#define RFCOMM_DEFAULT_MTU 127
Bluetooth: Refactor bluetooth buffer configuration for simplification Refactor and simplify the bluetooth buffer configurations to improve the easy of configurations and eliminate invalid ones. By moving configurations out of host and controller specific configurations and into a common one it becomes easier to configure the host and controller separately as the same configurations can be used as would be for a combined build. All HCI configurations are now given exluding the matching HCI header, which eases the configuration as the application don't have to know the different header sizes. The BT_RX_BUF_LEN is split into ACL and Event, as well as the suprising use of Command size. BT_L2CAP_RX_MTU is removed as the stack does not support reassembling of HCI ACL data to larger L2CAP PDUs. The application will have to set ACL RX size and account for the L2CAP PDU header itself. BT_EATT_RX_MTU was removed as it is only used for setting a different default value for another option which leads to the stuck kconfig symbol problem. The configurations can be updated according to the table below: ** New configuration | ** Old configuration All configurations BT_BUF_ACL_RX_SIZE | BT_L2CAP_RX_MTU + 4 BT_BUF_ACL_RX_SIZE | BT_RX_BUF_LEN - 4 BT_BUF_EVT_RX_SIZE | BT_RX_BUF_LEN - 2 BT_BUF_CMD_TX_SIZE | BT_RX_BUF_LEN - 3 BT_BUF_CMD_TX_COUNT | BT_HCI_CMD_COUNT BT_BUF_EVT_RX_COUNT | BT_RX_BUF_COUNT BT_BUF_ACL_RX_COUNT | BT_RX_BUF_COUNT BT_BUF_ACL_RX_COUNT | BT_ACL_RX_COUNT BT_BUF_EVT_DISCARDABLE_SIZE | BT_DISCARDABLE_BUF_SIZE - 2 BT_BUF_EVT_DISCARDABLE_COUNT | BT_DISCARDABLE_BUF_COUNT Controller-build BT_BUF_ACL_TX_SIZE | BT_CTLR_TX_BUFFERS_SIZE BT_BUF_ACL_TX_COUNT | BT_CTLR_TX_BUFFER HCI-bridge BT_BUF_ACL_TX_SIZE | BT_HCI_ACL_DATA_SIZE BT_BUF_ACL_TX_COUNT | 6 Fixed invalid configurations setting either BT_L2CAP_RX_MTU or BT_CTLR_DATA_LENGTH_MAX larger than BT_RX_BUF_LEN could lead to buffer overruns. Fix advertising report max data length calculation. This always used the BT_DISCARDABLE_BUF_SIZE macro but this feature can be turned off and advertising reports will be allocated from the RX buffer in that case. Also controller-build does not have this buffer (in hci_raw.c). Also the wrong HCI header was used in the calculation, HCI event header should have been used instead of HCI ACL header. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
2021-04-27 10:38:23 +02:00
#define RFCOMM_MAX_CREDITS (CONFIG_BT_BUF_ACL_RX_COUNT - 1)
#define RFCOMM_CREDITS_THRESHOLD (RFCOMM_MAX_CREDITS / 2)
#define RFCOMM_DEFAULT_CREDIT RFCOMM_MAX_CREDITS
#define RFCOMM_CONN_TIMEOUT K_SECONDS(60)
#define RFCOMM_DISC_TIMEOUT K_SECONDS(20)
#define RFCOMM_IDLE_TIMEOUT K_SECONDS(2)
#define DLC_RTX(_w) CONTAINER_OF(k_work_delayable_from_work(_w), \
struct bt_rfcomm_dlc, rtx_work)
#define SESSION_RTX(_w) CONTAINER_OF(k_work_delayable_from_work(_w), \
struct bt_rfcomm_session, rtx_work)
static struct bt_rfcomm_server *servers;
/* Pool for dummy buffers to wake up the tx threads */
NET_BUF_POOL_DEFINE(dummy_pool, CONFIG_BT_MAX_CONN, 0, 0, NULL);
#define RFCOMM_SESSION(_ch) CONTAINER_OF(_ch, \
struct bt_rfcomm_session, br_chan.chan)
static struct bt_rfcomm_session bt_rfcomm_pool[CONFIG_BT_MAX_CONN];
/* reversed, 8-bit, poly=0x07 */
static const uint8_t rfcomm_crc_table[256] = {
0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75,
0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69,
0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d,
0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51,
0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05,
0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19,
0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d,
0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21,
0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95,
0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89,
0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad,
0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1,
0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5,
0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9,
0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd,
0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1,
0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
};
static uint8_t rfcomm_calc_fcs(uint16_t len, const uint8_t *data)
{
uint8_t fcs = 0xff;
while (len--) {
fcs = rfcomm_crc_table[fcs ^ *data++];
}
/* Ones compliment */
return (0xff - fcs);
}
static bool rfcomm_check_fcs(uint16_t len, const uint8_t *data,
uint8_t recvd_fcs)
{
uint8_t fcs = 0xff;
while (len--) {
fcs = rfcomm_crc_table[fcs ^ *data++];
}
/* Ones compliment */
fcs = rfcomm_crc_table[fcs ^ recvd_fcs];
/*0xCF is the reversed order of 11110011.*/
return (fcs == 0xcf);
}
static struct bt_rfcomm_dlc *rfcomm_dlcs_lookup_dlci(struct bt_rfcomm_dlc *dlcs,
uint8_t dlci)
{
for (; dlcs; dlcs = dlcs->_next) {
if (dlcs->dlci == dlci) {
return dlcs;
}
}
return NULL;
}
static struct bt_rfcomm_dlc *rfcomm_dlcs_remove_dlci(struct bt_rfcomm_dlc *dlcs,
uint8_t dlci)
{
struct bt_rfcomm_dlc *tmp;
if (!dlcs) {
return NULL;
}
/* If first node is the one to be removed */
if (dlcs->dlci == dlci) {
dlcs->session->dlcs = dlcs->_next;
return dlcs;
}
for (tmp = dlcs, dlcs = dlcs->_next; dlcs; dlcs = dlcs->_next) {
if (dlcs->dlci == dlci) {
tmp->_next = dlcs->_next;
return dlcs;
}
tmp = dlcs;
}
return NULL;
}
static struct bt_rfcomm_server *rfcomm_server_lookup_channel(uint8_t channel)
{
struct bt_rfcomm_server *server;
for (server = servers; server; server = server->_next) {
if (server->channel == channel) {
return server;
}
}
return NULL;
}
static struct bt_rfcomm_session *
rfcomm_sessions_lookup_bt_conn(struct bt_conn *conn)
{
int i;
for (i = 0; i < ARRAY_SIZE(bt_rfcomm_pool); i++) {
struct bt_rfcomm_session *session = &bt_rfcomm_pool[i];
if (session->br_chan.chan.conn == conn) {
return session;
}
}
return NULL;
}
int bt_rfcomm_server_register(struct bt_rfcomm_server *server)
{
if (server->channel < RFCOMM_CHANNEL_START ||
server->channel > RFCOMM_CHANNEL_END || !server->accept) {
return -EINVAL;
}
/* Check if given channel is already in use */
if (rfcomm_server_lookup_channel(server->channel)) {
LOG_DBG("Channel already registered");
return -EADDRINUSE;
}
LOG_DBG("Channel 0x%02x", server->channel);
server->_next = servers;
servers = server;
return 0;
}
static void rfcomm_dlc_tx_give_credits(struct bt_rfcomm_dlc *dlc,
uint8_t credits)
{
LOG_DBG("dlc %p credits %u", dlc, credits);
while (credits--) {
k_sem_give(&dlc->tx_credits);
}
LOG_DBG("dlc %p updated credits %u", dlc, k_sem_count_get(&dlc->tx_credits));
}
static void rfcomm_dlc_destroy(struct bt_rfcomm_dlc *dlc)
{
LOG_DBG("dlc %p", dlc);
k_work_cancel_delayable(&dlc->rtx_work);
dlc->state = BT_RFCOMM_STATE_IDLE;
dlc->session = NULL;
if (dlc->ops && dlc->ops->disconnected) {
dlc->ops->disconnected(dlc);
}
}
static void rfcomm_dlc_disconnect(struct bt_rfcomm_dlc *dlc)
{
uint8_t old_state = dlc->state;
LOG_DBG("dlc %p", dlc);
if (dlc->state == BT_RFCOMM_STATE_DISCONNECTED) {
return;
}
dlc->state = BT_RFCOMM_STATE_DISCONNECTED;
switch (old_state) {
case BT_RFCOMM_STATE_CONNECTED:
/* Queue a dummy buffer to wake up and stop the
* tx thread for states where it was running.
*/
k_fifo_put(&dlc->tx_queue, net_buf_alloc(&dummy_pool, K_NO_WAIT));
/* There could be a writer waiting for credits so return a
* dummy credit to wake it up.
*/
rfcomm_dlc_tx_give_credits(dlc, 1);
k_sem_give(&dlc->session->fc);
break;
default:
rfcomm_dlc_destroy(dlc);
break;
}
}
static void rfcomm_session_disconnected(struct bt_rfcomm_session *session)
{
struct bt_rfcomm_dlc *dlc;
LOG_DBG("Session %p", session);
if (session->state == BT_RFCOMM_STATE_DISCONNECTED) {
return;
}
for (dlc = session->dlcs; dlc;) {
struct bt_rfcomm_dlc *next;
/* prefetch since disconnected callback may cleanup */
next = dlc->_next;
dlc->_next = NULL;
rfcomm_dlc_disconnect(dlc);
dlc = next;
}
session->state = BT_RFCOMM_STATE_DISCONNECTED;
session->dlcs = NULL;
}
net: buf: Redesigned pool & buffer allocation API Until now it has been necessary to separately define a k_fifo and an array of buffers when creating net_buf pools. This has been a bit of an inconvenience as well as blurred the line of what exactly constitutes the "pool". This patch removes the NET_BUF_POOL() macro and replaces it with a NET_BUF_POOL_DEFINE() macro that internally expands into the buffer array and new net_buf_pool struct with a given name: NET_BUF_POOL_DEFINE(pool_name, ...); Having a dedicated context struct for the pool has the added benefit that we can start moving there net_buf members that have the same value for all buffers from the same pool. The first such member that gets moved is the destroy callback, thus shrinking net_buf by four bytes. Another potential candidate is the user_data_size, however right not that's left out since it would just leave 2 bytes of padding in net_buf (i.e. not influence its size). Another common value is buf->size, however that one is also used by net_buf_simple and can therefore not be moved. This patch also splits getting buffers from a FIFO and allocating a new buffer from a pool into two separate APIs: net_buf_get and net_buf_alloc, thus simplifying the APIs and their usage. There is no separate 'reserve_head' parameter anymore when allocating, rather the user is expected to call net_buf_reserve() afterwards if something else than 0 headroom is desired. Change-Id: Id91b1e5c2be2deb1274dde47f5edebfe29af383a Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-10-18 23:24:51 +03:00
struct net_buf *bt_rfcomm_create_pdu(struct net_buf_pool *pool)
{
/* Length in RFCOMM header can be 2 bytes depending on length of user
* data
*/
net: buf: Redesigned pool & buffer allocation API Until now it has been necessary to separately define a k_fifo and an array of buffers when creating net_buf pools. This has been a bit of an inconvenience as well as blurred the line of what exactly constitutes the "pool". This patch removes the NET_BUF_POOL() macro and replaces it with a NET_BUF_POOL_DEFINE() macro that internally expands into the buffer array and new net_buf_pool struct with a given name: NET_BUF_POOL_DEFINE(pool_name, ...); Having a dedicated context struct for the pool has the added benefit that we can start moving there net_buf members that have the same value for all buffers from the same pool. The first such member that gets moved is the destroy callback, thus shrinking net_buf by four bytes. Another potential candidate is the user_data_size, however right not that's left out since it would just leave 2 bytes of padding in net_buf (i.e. not influence its size). Another common value is buf->size, however that one is also used by net_buf_simple and can therefore not be moved. This patch also splits getting buffers from a FIFO and allocating a new buffer from a pool into two separate APIs: net_buf_get and net_buf_alloc, thus simplifying the APIs and their usage. There is no separate 'reserve_head' parameter anymore when allocating, rather the user is expected to call net_buf_reserve() afterwards if something else than 0 headroom is desired. Change-Id: Id91b1e5c2be2deb1274dde47f5edebfe29af383a Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-10-18 23:24:51 +03:00
return bt_conn_create_pdu(pool,
sizeof(struct bt_l2cap_hdr) +
sizeof(struct bt_rfcomm_hdr) + 1);
}
static int rfcomm_send_cb(struct bt_rfcomm_session *session, struct net_buf *buf,
bt_conn_tx_cb_t cb, void *user_data)
{
int err;
err = bt_l2cap_br_chan_send_cb(&session->br_chan.chan, buf, cb, user_data);
if (err < 0) {
net_buf_unref(buf);
}
return err;
}
static int rfcomm_send(struct bt_rfcomm_session *session, struct net_buf *buf)
{
return rfcomm_send_cb(session, buf, NULL, NULL);
}
static int rfcomm_send_sabm(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_hdr *hdr;
struct net_buf *buf;
uint8_t cr, fcs;
buf = bt_l2cap_create_pdu(NULL, 0);
hdr = net_buf_add(buf, sizeof(*hdr));
cr = BT_RFCOMM_CMD_CR(session->role);
hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_SABM, BT_RFCOMM_PF_NON_UIH);
hdr->length = BT_RFCOMM_SET_LEN_8(0);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static int rfcomm_send_disc(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_hdr *hdr;
struct net_buf *buf;
uint8_t fcs, cr;
LOG_DBG("dlci %d", dlci);
buf = bt_l2cap_create_pdu(NULL, 0);
hdr = net_buf_add(buf, sizeof(*hdr));
cr = BT_RFCOMM_RESP_CR(session->role);
hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_DISC, BT_RFCOMM_PF_NON_UIH);
hdr->length = BT_RFCOMM_SET_LEN_8(0);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static void rfcomm_session_disconnect(struct bt_rfcomm_session *session)
{
if (session->dlcs) {
return;
}
session->state = BT_RFCOMM_STATE_DISCONNECTING;
rfcomm_send_disc(session, 0);
k_work_reschedule(&session->rtx_work, RFCOMM_DISC_TIMEOUT);
}
static struct net_buf *rfcomm_make_uih_msg(struct bt_rfcomm_session *session,
uint8_t cr, uint8_t type,
uint8_t len)
{
struct bt_rfcomm_hdr *hdr;
struct bt_rfcomm_msg_hdr *msg_hdr;
struct net_buf *buf;
uint8_t hdr_cr;
buf = bt_l2cap_create_pdu(NULL, 0);
hdr = net_buf_add(buf, sizeof(*hdr));
hdr_cr = BT_RFCOMM_UIH_CR(session->role);
hdr->address = BT_RFCOMM_SET_ADDR(0, hdr_cr);
hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_UIH, BT_RFCOMM_PF_UIH);
hdr->length = BT_RFCOMM_SET_LEN_8(sizeof(*msg_hdr) + len);
msg_hdr = net_buf_add(buf, sizeof(*msg_hdr));
msg_hdr->type = BT_RFCOMM_SET_MSG_TYPE(type, cr);
msg_hdr->len = BT_RFCOMM_SET_LEN_8(len);
return buf;
}
static void rfcomm_connected(struct bt_l2cap_chan *chan)
{
struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
LOG_DBG("Session %p", session);
/* Need to include UIH header and FCS*/
session->mtu = MIN(session->br_chan.rx.mtu,
session->br_chan.tx.mtu) -
BT_RFCOMM_HDR_SIZE + BT_RFCOMM_FCS_SIZE;
if (session->state == BT_RFCOMM_STATE_CONNECTING) {
rfcomm_send_sabm(session, 0);
}
}
static void rfcomm_disconnected(struct bt_l2cap_chan *chan)
{
struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
LOG_DBG("Session %p", session);
k_work_cancel_delayable(&session->rtx_work);
rfcomm_session_disconnected(session);
session->state = BT_RFCOMM_STATE_IDLE;
}
static void rfcomm_dlc_rtx_timeout(struct k_work *work)
{
struct bt_rfcomm_dlc *dlc = DLC_RTX(work);
struct bt_rfcomm_session *session = dlc->session;
LOG_WRN("dlc %p state %d timeout", dlc, dlc->state);
rfcomm_dlcs_remove_dlci(session->dlcs, dlc->dlci);
rfcomm_dlc_disconnect(dlc);
rfcomm_session_disconnect(session);
}
static void rfcomm_dlc_init(struct bt_rfcomm_dlc *dlc,
struct bt_rfcomm_session *session,
uint8_t dlci,
bt_rfcomm_role_t role)
{
LOG_DBG("dlc %p", dlc);
dlc->dlci = dlci;
dlc->session = session;
dlc->rx_credit = RFCOMM_DEFAULT_CREDIT;
dlc->state = BT_RFCOMM_STATE_INIT;
dlc->role = role;
k_work_init_delayable(&dlc->rtx_work, rfcomm_dlc_rtx_timeout);
/* Start a conn timer which includes auth as well */
k_work_schedule(&dlc->rtx_work, RFCOMM_CONN_TIMEOUT);
dlc->_next = session->dlcs;
session->dlcs = dlc;
}
static struct bt_rfcomm_dlc *rfcomm_dlc_accept(struct bt_rfcomm_session *session,
uint8_t dlci)
{
struct bt_rfcomm_server *server;
struct bt_rfcomm_dlc *dlc;
uint8_t channel;
channel = BT_RFCOMM_GET_CHANNEL(dlci);
server = rfcomm_server_lookup_channel(channel);
if (!server) {
LOG_ERR("Server Channel not registered");
return NULL;
}
if (server->accept(session->br_chan.chan.conn, &dlc) < 0) {
LOG_DBG("Incoming connection rejected");
return NULL;
}
if (!BT_RFCOMM_CHECK_MTU(dlc->mtu)) {
rfcomm_dlc_destroy(dlc);
return NULL;
}
rfcomm_dlc_init(dlc, session, dlci, BT_RFCOMM_ROLE_ACCEPTOR);
dlc->mtu = MIN(dlc->mtu, session->mtu);
return dlc;
}
static int rfcomm_send_dm(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_hdr *hdr;
struct net_buf *buf;
uint8_t fcs, cr;
LOG_DBG("dlci %d", dlci);
buf = bt_l2cap_create_pdu(NULL, 0);
hdr = net_buf_add(buf, sizeof(*hdr));
cr = BT_RFCOMM_RESP_CR(session->role);
hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
/* For DM PF bit is not relevant, we set it 1 */
hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_DM, BT_RFCOMM_PF_NON_UIH);
hdr->length = BT_RFCOMM_SET_LEN_8(0);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static void rfcomm_check_fc(struct bt_rfcomm_dlc *dlc)
{
LOG_DBG("%p", dlc);
LOG_DBG("Wait for credits or MSC FC %p", dlc);
/* Wait for credits or MSC FC */
k_sem_take(&dlc->tx_credits, K_FOREVER);
if (dlc->session->cfc == BT_RFCOMM_CFC_SUPPORTED) {
return;
}
k_sem_take(&dlc->session->fc, K_FOREVER);
/* Give the sems immediately so that sem will be available for all
* the bufs in the queue. It will be blocked only once all the bufs
* are sent (which will preempt this thread) and FCOFF / FC bit
* with 1, is received.
*/
k_sem_give(&dlc->session->fc);
k_sem_give(&dlc->tx_credits);
}
static void bt_rfcomm_tx_destroy(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
{
LOG_DBG("dlc %p, buf %p", dlc, buf);
if ((buf == NULL) || (buf->len == 0)) {
return;
}
if (dlc && dlc->ops && dlc->ops->sent) {
dlc->ops->sent(dlc, -ESHUTDOWN);
}
}
static void rfcomm_sent(struct bt_conn *conn, void *user_data, int err)
{
struct bt_rfcomm_dlc *dlc;
LOG_DBG("conn %p", conn);
if (user_data == NULL) {
return;
}
dlc = (struct bt_rfcomm_dlc *)user_data;
if (dlc && dlc->ops && dlc->ops->sent) {
dlc->ops->sent(dlc, err);
}
}
static void rfcomm_dlc_tx_thread(void *p1, void *p2, void *p3)
{
struct bt_rfcomm_dlc *dlc = p1;
k_timeout_t timeout = K_FOREVER;
struct net_buf *buf;
LOG_DBG("Started for dlc %p", dlc);
while (dlc->state == BT_RFCOMM_STATE_CONNECTED ||
dlc->state == BT_RFCOMM_STATE_USER_DISCONNECT) {
/* Get next packet for dlc */
LOG_DBG("Wait for buf %p", dlc);
buf = k_fifo_get(&dlc->tx_queue, timeout);
/* If its dummy buffer or non user disconnect then break */
if ((dlc->state != BT_RFCOMM_STATE_CONNECTED &&
dlc->state != BT_RFCOMM_STATE_USER_DISCONNECT) ||
!buf || !buf->len) {
if (buf) {
bt_rfcomm_tx_destroy(dlc, buf);
net_buf_unref(buf);
}
break;
}
rfcomm_check_fc(dlc);
if (dlc->state != BT_RFCOMM_STATE_CONNECTED &&
dlc->state != BT_RFCOMM_STATE_USER_DISCONNECT) {
bt_rfcomm_tx_destroy(dlc, buf);
net_buf_unref(buf);
break;
}
if (rfcomm_send_cb(dlc->session, buf, rfcomm_sent, dlc) < 0) {
/* This fails only if channel is disconnected */
dlc->state = BT_RFCOMM_STATE_DISCONNECTED;
bt_rfcomm_tx_destroy(dlc, buf);
break;
}
if (dlc->state == BT_RFCOMM_STATE_USER_DISCONNECT) {
timeout = K_NO_WAIT;
}
}
LOG_DBG("dlc %p disconnected - cleaning up", dlc);
/* Give back any allocated buffers */
while ((buf = k_fifo_get(&dlc->tx_queue, K_NO_WAIT))) {
bt_rfcomm_tx_destroy(dlc, buf);
net_buf_unref(buf);
}
if (dlc->state == BT_RFCOMM_STATE_USER_DISCONNECT) {
dlc->state = BT_RFCOMM_STATE_DISCONNECTING;
}
if (dlc->state == BT_RFCOMM_STATE_DISCONNECTING) {
rfcomm_send_disc(dlc->session, dlc->dlci);
k_work_reschedule(&dlc->rtx_work, RFCOMM_DISC_TIMEOUT);
} else {
rfcomm_dlc_destroy(dlc);
}
LOG_DBG("dlc %p exiting", dlc);
}
static int rfcomm_send_ua(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_hdr *hdr;
struct net_buf *buf;
uint8_t cr, fcs;
buf = bt_l2cap_create_pdu(NULL, 0);
hdr = net_buf_add(buf, sizeof(*hdr));
cr = BT_RFCOMM_RESP_CR(session->role);
hdr->address = BT_RFCOMM_SET_ADDR(dlci, cr);
hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_UA, BT_RFCOMM_PF_NON_UIH);
hdr->length = BT_RFCOMM_SET_LEN_8(0);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_NON_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static int rfcomm_send_msc(struct bt_rfcomm_dlc *dlc, uint8_t cr,
uint8_t v24_signal)
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
{
struct bt_rfcomm_msc *msc;
struct net_buf *buf;
uint8_t fcs;
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
buf = rfcomm_make_uih_msg(dlc->session, cr, BT_RFCOMM_MSC,
sizeof(*msc));
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
msc = net_buf_add(buf, sizeof(*msc));
/* cr bit should be always 1 in MSC */
msc->dlci = BT_RFCOMM_SET_ADDR(dlc->dlci, 1);
msc->v24_signal = v24_signal;
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(dlc->session, buf);
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
}
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->session, 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 rfcomm_send(dlc->session, 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));
net_buf_add_mem(buf, rpn, sizeof(*rpn));
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static int rfcomm_send_test(struct bt_rfcomm_session *session, uint8_t cr,
uint8_t *pattern, uint8_t len)
{
struct net_buf *buf;
uint8_t fcs;
buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_TEST, len);
net_buf_add_mem(buf, pattern, len);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static int rfcomm_send_nsc(struct bt_rfcomm_session *session, uint8_t cmd_type)
{
struct net_buf *buf;
uint8_t fcs;
buf = rfcomm_make_uih_msg(session, BT_RFCOMM_MSG_RESP_CR,
BT_RFCOMM_NSC, sizeof(cmd_type));
net_buf_add_u8(buf, cmd_type);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static int rfcomm_send_fcon(struct bt_rfcomm_session *session, uint8_t cr)
{
struct net_buf *buf;
uint8_t fcs;
buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_FCON, 0);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static int rfcomm_send_fcoff(struct bt_rfcomm_session *session, uint8_t cr)
{
struct net_buf *buf;
uint8_t fcs;
buf = rfcomm_make_uih_msg(session, cr, BT_RFCOMM_FCOFF, 0);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(session, buf);
}
static void rfcomm_dlc_connected(struct bt_rfcomm_dlc *dlc)
{
dlc->state = BT_RFCOMM_STATE_CONNECTED;
rfcomm_send_msc(dlc, BT_RFCOMM_MSG_CMD_CR, BT_RFCOMM_DEFAULT_V24_SIG);
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
if (dlc->session->cfc == BT_RFCOMM_CFC_UNKNOWN) {
/* This means PN negotiation is not done for this session and
* can happen only for 1.0b device.
*/
dlc->session->cfc = BT_RFCOMM_CFC_NOT_SUPPORTED;
}
if (dlc->session->cfc == BT_RFCOMM_CFC_NOT_SUPPORTED) {
LOG_DBG("CFC not supported %p", dlc);
rfcomm_send_fcon(dlc->session, BT_RFCOMM_MSG_CMD_CR);
/* Use tx_credits as binary sem for MSC FC */
k_sem_init(&dlc->tx_credits, 0, 1);
}
/* Cancel conn timer */
k_work_cancel_delayable(&dlc->rtx_work);
k_fifo_init(&dlc->tx_queue);
k_thread_create(&dlc->tx_thread, dlc->stack,
K_KERNEL_STACK_SIZEOF(dlc->stack),
rfcomm_dlc_tx_thread, dlc, NULL, NULL, K_PRIO_COOP(7),
0, K_NO_WAIT);
k_thread_name_set(&dlc->tx_thread, "BT DLC");
if (dlc->ops && dlc->ops->connected) {
dlc->ops->connected(dlc);
}
}
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
enum security_result {
RFCOMM_SECURITY_PASSED,
RFCOMM_SECURITY_REJECT,
RFCOMM_SECURITY_PENDING
};
static enum security_result rfcomm_dlc_security(struct bt_rfcomm_dlc *dlc)
{
struct bt_conn *conn = dlc->session->br_chan.chan.conn;
LOG_DBG("dlc %p", dlc);
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
/* If current security level is greater than or equal to required
* security level then return SUCCESS.
* For SSP devices the current security will be at least MEDIUM
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
* since L2CAP is enforcing it
*/
if (conn->sec_level >= dlc->required_sec_level) {
return RFCOMM_SECURITY_PASSED;
}
if (!bt_conn_set_security(conn, dlc->required_sec_level)) {
/*
* General Bonding refers to the process of performing bonding
* during connection setup or channel establishment procedures
* as a precursor to accessing a service.
* For current case, it is dedicated bonding.
*/
atomic_set_bit(conn->flags, BT_CONN_BR_GENERAL_BONDING);
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
/* If Security elevation is initiated or in progress */
return RFCOMM_SECURITY_PENDING;
}
/* Security request failed */
return RFCOMM_SECURITY_REJECT;
}
static void rfcomm_dlc_drop(struct bt_rfcomm_dlc *dlc)
{
LOG_DBG("dlc %p", dlc);
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
rfcomm_dlcs_remove_dlci(dlc->session->dlcs, dlc->dlci);
rfcomm_dlc_destroy(dlc);
}
static int rfcomm_dlc_close(struct bt_rfcomm_dlc *dlc)
{
LOG_DBG("dlc %p", dlc);
switch (dlc->state) {
case BT_RFCOMM_STATE_SECURITY_PENDING:
if (dlc->role == BT_RFCOMM_ROLE_ACCEPTOR) {
rfcomm_send_dm(dlc->session, dlc->dlci);
}
__fallthrough;
case BT_RFCOMM_STATE_INIT:
rfcomm_dlc_drop(dlc);
break;
case BT_RFCOMM_STATE_CONNECTING:
case BT_RFCOMM_STATE_CONFIG:
dlc->state = BT_RFCOMM_STATE_DISCONNECTING;
rfcomm_send_disc(dlc->session, dlc->dlci);
k_work_reschedule(&dlc->rtx_work, RFCOMM_DISC_TIMEOUT);
break;
case BT_RFCOMM_STATE_CONNECTED:
dlc->state = BT_RFCOMM_STATE_DISCONNECTING;
/* Queue a dummy buffer to wake up and stop the
* tx thread.
*/
k_fifo_put(&dlc->tx_queue,
net: buf: Redesigned pool & buffer allocation API Until now it has been necessary to separately define a k_fifo and an array of buffers when creating net_buf pools. This has been a bit of an inconvenience as well as blurred the line of what exactly constitutes the "pool". This patch removes the NET_BUF_POOL() macro and replaces it with a NET_BUF_POOL_DEFINE() macro that internally expands into the buffer array and new net_buf_pool struct with a given name: NET_BUF_POOL_DEFINE(pool_name, ...); Having a dedicated context struct for the pool has the added benefit that we can start moving there net_buf members that have the same value for all buffers from the same pool. The first such member that gets moved is the destroy callback, thus shrinking net_buf by four bytes. Another potential candidate is the user_data_size, however right not that's left out since it would just leave 2 bytes of padding in net_buf (i.e. not influence its size). Another common value is buf->size, however that one is also used by net_buf_simple and can therefore not be moved. This patch also splits getting buffers from a FIFO and allocating a new buffer from a pool into two separate APIs: net_buf_get and net_buf_alloc, thus simplifying the APIs and their usage. There is no separate 'reserve_head' parameter anymore when allocating, rather the user is expected to call net_buf_reserve() afterwards if something else than 0 headroom is desired. Change-Id: Id91b1e5c2be2deb1274dde47f5edebfe29af383a Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-10-18 23:24:51 +03:00
net_buf_alloc(&dummy_pool, K_NO_WAIT));
/* There could be a writer waiting for credits so return a
* dummy credit to wake it up.
*/
rfcomm_dlc_tx_give_credits(dlc, 1);
break;
case BT_RFCOMM_STATE_DISCONNECTING:
case BT_RFCOMM_STATE_DISCONNECTED:
break;
case BT_RFCOMM_STATE_IDLE:
default:
return -EINVAL;
}
return 0;
}
static void rfcomm_handle_sabm(struct bt_rfcomm_session *session, uint8_t dlci)
{
if (!dlci) {
if (rfcomm_send_ua(session, dlci) < 0) {
return;
}
session->state = BT_RFCOMM_STATE_CONNECTED;
} else {
struct bt_rfcomm_dlc *dlc;
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
enum security_result result;
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
if (!dlc) {
dlc = rfcomm_dlc_accept(session, dlci);
if (!dlc) {
rfcomm_send_dm(session, dlci);
return;
}
}
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
result = rfcomm_dlc_security(dlc);
switch (result) {
case RFCOMM_SECURITY_PENDING:
dlc->state = BT_RFCOMM_STATE_SECURITY_PENDING;
return;
case RFCOMM_SECURITY_PASSED:
break;
case RFCOMM_SECURITY_REJECT:
default:
rfcomm_send_dm(session, dlci);
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
rfcomm_dlc_drop(dlc);
return;
}
if (rfcomm_send_ua(session, dlci) < 0) {
return;
}
/* Cancel idle timer if any */
k_work_cancel_delayable(&session->rtx_work);
rfcomm_dlc_connected(dlc);
}
}
static int rfcomm_send_pn(struct bt_rfcomm_dlc *dlc, uint8_t cr)
{
struct bt_rfcomm_pn *pn;
struct net_buf *buf;
uint8_t fcs;
buf = rfcomm_make_uih_msg(dlc->session, cr, BT_RFCOMM_PN, sizeof(*pn));
LOG_DBG("mtu %x", dlc->mtu);
pn = net_buf_add(buf, sizeof(*pn));
pn->dlci = dlc->dlci;
pn->mtu = sys_cpu_to_le16(dlc->mtu);
if (dlc->state == BT_RFCOMM_STATE_CONFIG &&
(dlc->session->cfc == BT_RFCOMM_CFC_UNKNOWN ||
dlc->session->cfc == BT_RFCOMM_CFC_SUPPORTED)) {
pn->credits = dlc->rx_credit;
if (cr) {
pn->flow_ctrl = BT_RFCOMM_PN_CFC_CMD;
} else {
pn->flow_ctrl = BT_RFCOMM_PN_CFC_RESP;
}
} else {
/* If PN comes in already opened dlc or cfc not supported
* these should be 0
*/
pn->credits = 0U;
pn->flow_ctrl = 0U;
}
pn->max_retrans = 0U;
pn->ack_timer = 0U;
pn->priority = 0U;
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(dlc->session, buf);
}
static int rfcomm_send_credit(struct bt_rfcomm_dlc *dlc, uint8_t credits)
{
struct bt_rfcomm_hdr *hdr;
struct net_buf *buf;
uint8_t fcs, cr;
LOG_DBG("Dlc %p credits %d", dlc, credits);
buf = bt_l2cap_create_pdu(NULL, 0);
hdr = net_buf_add(buf, sizeof(*hdr));
cr = BT_RFCOMM_UIH_CR(dlc->session->role);
hdr->address = BT_RFCOMM_SET_ADDR(dlc->dlci, cr);
hdr->control = BT_RFCOMM_SET_CTRL(BT_RFCOMM_UIH,
BT_RFCOMM_PF_UIH_CREDIT);
hdr->length = BT_RFCOMM_SET_LEN_8(0);
net_buf_add_u8(buf, credits);
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
return rfcomm_send(dlc->session, buf);
}
static int rfcomm_dlc_start(struct bt_rfcomm_dlc *dlc)
2016-10-24 22:09:27 +05:30
{
enum security_result result;
LOG_DBG("dlc %p", dlc);
2016-10-24 22:09:27 +05:30
result = rfcomm_dlc_security(dlc);
switch (result) {
case RFCOMM_SECURITY_PASSED:
dlc->mtu = MIN(dlc->mtu, dlc->session->mtu);
dlc->state = BT_RFCOMM_STATE_CONFIG;
rfcomm_send_pn(dlc, BT_RFCOMM_MSG_CMD_CR);
break;
case RFCOMM_SECURITY_PENDING:
dlc->state = BT_RFCOMM_STATE_SECURITY_PENDING;
break;
case RFCOMM_SECURITY_REJECT:
default:
return -EIO;
}
return 0;
2016-10-24 22:09:27 +05:30
}
static void rfcomm_handle_ua(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_dlc *dlc, *next;
int err;
2016-10-24 22:09:27 +05:30
if (!dlci) {
switch (session->state) {
case BT_RFCOMM_STATE_CONNECTING:
session->state = BT_RFCOMM_STATE_CONNECTED;
for (dlc = session->dlcs; dlc; dlc = next) {
next = dlc->_next;
if (dlc->role == BT_RFCOMM_ROLE_INITIATOR &&
dlc->state == BT_RFCOMM_STATE_INIT) {
if (rfcomm_dlc_start(dlc) < 0) {
rfcomm_dlc_drop(dlc);
}
}
2016-10-24 22:09:27 +05:30
}
/* Disconnect session if there is no dlcs left */
rfcomm_session_disconnect(session);
break;
case BT_RFCOMM_STATE_DISCONNECTING:
session->state = BT_RFCOMM_STATE_DISCONNECTED;
/* Cancel disc timer */
k_work_cancel_delayable(&session->rtx_work);
err = bt_l2cap_chan_disconnect(&session->br_chan.chan);
if (err < 0) {
session->state = BT_RFCOMM_STATE_IDLE;
}
break;
default:
break;
2016-10-24 22:09:27 +05:30
}
} else {
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
if (!dlc) {
return;
}
switch (dlc->state) {
case BT_RFCOMM_STATE_CONNECTING:
2016-10-24 22:09:27 +05:30
rfcomm_dlc_connected(dlc);
break;
case BT_RFCOMM_STATE_DISCONNECTING:
rfcomm_dlc_drop(dlc);
rfcomm_session_disconnect(session);
break;
default:
break;
2016-10-24 22:09:27 +05:30
}
}
}
static void rfcomm_handle_dm(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_dlc *dlc;
LOG_DBG("dlci %d", dlci);
dlc = rfcomm_dlcs_remove_dlci(session->dlcs, dlci);
if (!dlc) {
return;
}
rfcomm_dlc_disconnect(dlc);
rfcomm_session_disconnect(session);
}
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
static void rfcomm_handle_msc(struct bt_rfcomm_session *session,
struct net_buf *buf, uint8_t cr)
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
{
struct bt_rfcomm_msc *msc = (void *)buf->data;
struct bt_rfcomm_dlc *dlc;
uint8_t dlci = BT_RFCOMM_GET_DLCI(msc->dlci);
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
LOG_DBG("dlci %d", dlci);
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
if (!dlc) {
return;
}
if (cr == BT_RFCOMM_MSG_RESP_CR) {
return;
}
if (dlc->session->cfc == BT_RFCOMM_CFC_NOT_SUPPORTED) {
/* Only FC bit affects the flow on RFCOMM level */
if (BT_RFCOMM_GET_FC(msc->v24_signal)) {
/* If FC bit is 1 the device is unable to accept frames.
* Take the semaphore with timeout K_NO_WAIT so that
* dlc thread will be blocked when it tries sem_take
* before sending the data. K_NO_WAIT timeout will make
* sure that RX thread will not be blocked while taking
* the semaphore.
*/
k_sem_take(&dlc->tx_credits, K_NO_WAIT);
} else {
/* Give the sem so that it will unblock the waiting dlc
* thread in sem_take().
*/
k_sem_give(&dlc->tx_credits);
}
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
}
rfcomm_send_msc(dlc, BT_RFCOMM_MSG_RESP_CR, msc->v24_signal);
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
}
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;
LOG_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_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;
LOG_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 != 1U) {
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)
{
struct bt_rfcomm_pn *pn = (void *)buf->data;
struct bt_rfcomm_dlc *dlc;
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, pn->dlci);
if (!dlc) {
/* Ignore if it is a response */
if (!cr) {
return;
}
if (!BT_RFCOMM_CHECK_MTU(pn->mtu)) {
LOG_ERR("Invalid mtu %d", pn->mtu);
rfcomm_send_dm(session, pn->dlci);
return;
}
dlc = rfcomm_dlc_accept(session, pn->dlci);
if (!dlc) {
rfcomm_send_dm(session, pn->dlci);
return;
}
LOG_DBG("Incoming connection accepted dlc %p", dlc);
dlc->mtu = MIN(dlc->mtu, sys_le16_to_cpu(pn->mtu));
if (pn->flow_ctrl == BT_RFCOMM_PN_CFC_CMD) {
if (session->cfc == BT_RFCOMM_CFC_UNKNOWN) {
session->cfc = BT_RFCOMM_CFC_SUPPORTED;
}
k_sem_init(&dlc->tx_credits, 0, K_SEM_MAX_LIMIT);
rfcomm_dlc_tx_give_credits(dlc, pn->credits);
} else {
session->cfc = BT_RFCOMM_CFC_NOT_SUPPORTED;
}
dlc->state = BT_RFCOMM_STATE_CONFIG;
rfcomm_send_pn(dlc, BT_RFCOMM_MSG_RESP_CR);
/* Cancel idle timer if any */
k_work_cancel_delayable(&session->rtx_work);
} else {
/* If its a command */
if (cr) {
if (!BT_RFCOMM_CHECK_MTU(pn->mtu)) {
LOG_ERR("Invalid mtu %d", pn->mtu);
rfcomm_dlc_close(dlc);
return;
}
dlc->mtu = MIN(dlc->mtu, sys_le16_to_cpu(pn->mtu));
rfcomm_send_pn(dlc, BT_RFCOMM_MSG_RESP_CR);
2016-10-24 22:09:27 +05:30
} else {
if (dlc->state != BT_RFCOMM_STATE_CONFIG) {
return;
}
dlc->mtu = MIN(dlc->mtu, sys_le16_to_cpu(pn->mtu));
if (pn->flow_ctrl == BT_RFCOMM_PN_CFC_RESP) {
if (session->cfc == BT_RFCOMM_CFC_UNKNOWN) {
session->cfc = BT_RFCOMM_CFC_SUPPORTED;
}
k_sem_init(&dlc->tx_credits, 0, K_SEM_MAX_LIMIT);
rfcomm_dlc_tx_give_credits(dlc, pn->credits);
} else {
session->cfc = BT_RFCOMM_CFC_NOT_SUPPORTED;
}
2016-10-24 22:09:27 +05:30
dlc->state = BT_RFCOMM_STATE_CONNECTING;
rfcomm_send_sabm(session, dlc->dlci);
}
}
}
static void rfcomm_handle_disc(struct bt_rfcomm_session *session, uint8_t dlci)
{
struct bt_rfcomm_dlc *dlc;
LOG_DBG("Dlci %d", dlci);
if (dlci) {
dlc = rfcomm_dlcs_remove_dlci(session->dlcs, dlci);
if (!dlc) {
rfcomm_send_dm(session, dlci);
return;
}
rfcomm_send_ua(session, dlci);
rfcomm_dlc_disconnect(dlc);
if (!session->dlcs) {
/* Start a session idle timer */
k_work_reschedule(&dlc->session->rtx_work,
RFCOMM_IDLE_TIMEOUT);
}
} else {
/* Cancel idle timer */
k_work_cancel_delayable(&session->rtx_work);
rfcomm_send_ua(session, 0);
rfcomm_session_disconnected(session);
}
}
static void rfcomm_handle_msg(struct bt_rfcomm_session *session,
struct net_buf *buf)
{
struct bt_rfcomm_msg_hdr *hdr;
uint8_t msg_type, len, cr;
if (buf->len < sizeof(*hdr)) {
LOG_ERR("Too small RFCOMM message");
return;
}
hdr = net_buf_pull_mem(buf, sizeof(*hdr));
msg_type = BT_RFCOMM_GET_MSG_TYPE(hdr->type);
cr = BT_RFCOMM_GET_MSG_CR(hdr->type);
len = BT_RFCOMM_GET_LEN(hdr->len);
LOG_DBG("msg type %x cr %x", msg_type, cr);
switch (msg_type) {
case BT_RFCOMM_PN:
rfcomm_handle_pn(session, buf, cr);
break;
Bluetooth: RFCOMM: Perform MSC transaction after dlc MSC (Modem status command) is used to convey RS-232 control and break signals. This shall be sent prior to any user data after dlc. Remote also would have sent it which is handled in this patch This has meaning only if a port emulation entity is there on top (which is not there in zephyr right now). So currently v24 signal is hard coded like below. DV = 1 IC = 0 RTR = 1 RTC = 1 FC = 0 EXT = 0 < 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command CMD (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 < 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 > 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: Modem Status Command RSP (0x38) Length: 2 dlci 2 fc 0 rtc 1 rtr 1 ic 0 dv 1 Change-Id: Iab06f12de2f2357485309eb622c8c5e13db7011c Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-08-22 18:17:29 +05:30
case BT_RFCOMM_MSC:
rfcomm_handle_msc(session, buf, cr);
break;
case BT_RFCOMM_RLS:
rfcomm_handle_rls(session, buf, cr);
break;
case BT_RFCOMM_RPN:
rfcomm_handle_rpn(session, buf, cr);
break;
case BT_RFCOMM_TEST:
if (!cr) {
break;
}
rfcomm_send_test(session, BT_RFCOMM_MSG_RESP_CR, buf->data,
buf->len - 1);
break;
case BT_RFCOMM_FCON:
if (session->cfc == BT_RFCOMM_CFC_SUPPORTED) {
LOG_ERR("FCON received when CFC is supported ");
return;
}
if (!cr) {
break;
}
/* Give the sem so that it will unblock the waiting dlc threads
* of this session in sem_take().
*/
k_sem_give(&session->fc);
rfcomm_send_fcon(session, BT_RFCOMM_MSG_RESP_CR);
break;
case BT_RFCOMM_FCOFF:
if (session->cfc == BT_RFCOMM_CFC_SUPPORTED) {
LOG_ERR("FCOFF received when CFC is supported ");
return;
}
if (!cr) {
break;
}
/* Take the semaphore with timeout K_NO_WAIT so that all the
* dlc threads in this session will be blocked when it tries
* sem_take before sending the data. K_NO_WAIT timeout will
* make sure that RX thread will not be blocked while taking
* the semaphore.
*/
k_sem_take(&session->fc, K_NO_WAIT);
rfcomm_send_fcoff(session, BT_RFCOMM_MSG_RESP_CR);
break;
default:
LOG_WRN("Unknown/Unsupported RFCOMM Msg type 0x%02x", msg_type);
rfcomm_send_nsc(session, hdr->type);
break;
}
}
static void rfcomm_dlc_update_credits(struct bt_rfcomm_dlc *dlc)
{
uint8_t credits;
if (dlc->session->cfc == BT_RFCOMM_CFC_NOT_SUPPORTED) {
return;
}
LOG_DBG("dlc %p credits %u", dlc, dlc->rx_credit);
/* Only give more credits if it went below the defined threshold */
if (dlc->rx_credit > RFCOMM_CREDITS_THRESHOLD) {
return;
}
/* Restore credits */
credits = RFCOMM_MAX_CREDITS - dlc->rx_credit;
dlc->rx_credit += credits;
rfcomm_send_credit(dlc, credits);
}
static void rfcomm_handle_data(struct bt_rfcomm_session *session,
struct net_buf *buf, uint8_t dlci, uint8_t pf)
{
struct bt_rfcomm_dlc *dlc;
LOG_DBG("dlci %d, pf %d", dlci, pf);
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
if (!dlc) {
LOG_ERR("Data recvd in non existing DLC");
rfcomm_send_dm(session, dlci);
return;
}
LOG_DBG("dlc %p rx credit %d", dlc, dlc->rx_credit);
if (dlc->state != BT_RFCOMM_STATE_CONNECTED) {
return;
}
if (pf == BT_RFCOMM_PF_UIH_CREDIT) {
if (buf->len == 0) {
LOG_WRN("Data recvd is invalid");
return;
}
rfcomm_dlc_tx_give_credits(dlc, net_buf_pull_u8(buf));
}
if (buf->len > BT_RFCOMM_FCS_SIZE) {
if (dlc->session->cfc == BT_RFCOMM_CFC_SUPPORTED &&
!dlc->rx_credit) {
LOG_ERR("Data recvd when rx credit is 0");
rfcomm_dlc_close(dlc);
return;
}
/* Remove FCS */
buf->len -= BT_RFCOMM_FCS_SIZE;
if (dlc->ops && dlc->ops->recv) {
dlc->ops->recv(dlc, buf);
}
dlc->rx_credit--;
rfcomm_dlc_update_credits(dlc);
}
}
int bt_rfcomm_dlc_send(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
{
uint8_t fcs, cr;
if (!buf) {
return -EINVAL;
}
LOG_DBG("dlc %p tx credit %d", dlc, k_sem_count_get(&dlc->tx_credits));
if (dlc->state != BT_RFCOMM_STATE_CONNECTED) {
return -ENOTCONN;
}
if (buf->len > dlc->mtu) {
return -EMSGSIZE;
}
/* length */
if (buf->len > BT_RFCOMM_MAX_LEN_8) {
/* Length is 2 byte */
net_buf_push_le16(buf, BT_RFCOMM_SET_LEN_16(buf->len));
} else {
net_buf_push_u8(buf, BT_RFCOMM_SET_LEN_8(buf->len));
}
/* control */
net_buf_push_u8(buf, BT_RFCOMM_SET_CTRL(BT_RFCOMM_UIH,
BT_RFCOMM_PF_UIH_NO_CREDIT));
/* address */
cr = BT_RFCOMM_UIH_CR(dlc->session->role);
net_buf_push_u8(buf, BT_RFCOMM_SET_ADDR(dlc->dlci, cr));
fcs = rfcomm_calc_fcs(BT_RFCOMM_FCS_LEN_UIH, buf->data);
net_buf_add_u8(buf, fcs);
k_fifo_put(&dlc->tx_queue, buf);
return buf->len;
}
static int rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
struct bt_rfcomm_hdr *hdr = (void *)buf->data;
struct bt_rfcomm_hdr_ext *hdr_ext = (void *)buf->data;
uint8_t dlci, frame_type, fcs, fcs_len;
uint16_t msg_len;
uint16_t hdr_len;
/* Need to consider FCS also*/
if (buf->len < (sizeof(*hdr) + sizeof(fcs))) {
LOG_ERR("Too small RFCOMM Frame");
return 0;
}
dlci = BT_RFCOMM_GET_DLCI(hdr->address);
frame_type = BT_RFCOMM_GET_FRAME_TYPE(hdr->control);
LOG_DBG("session %p dlci %x type %x", session, dlci, frame_type);
if (BT_RFCOMM_LEN_EXTENDED(hdr->length)) {
msg_len = BT_RFCOMM_GET_LEN_EXTENDED(hdr_ext->hdr.length, hdr_ext->second_length);
hdr_len = sizeof(*hdr_ext);
} else {
msg_len = BT_RFCOMM_GET_LEN(hdr->length);
hdr_len = sizeof(*hdr);
}
if (buf->len < (hdr_len + msg_len + sizeof(fcs))) {
LOG_ERR("Too small RFCOMM information (%d < %d)", buf->len,
hdr_len + msg_len + sizeof(fcs));
return 0;
}
fcs_len = (frame_type == BT_RFCOMM_UIH) ? BT_RFCOMM_FCS_LEN_UIH : hdr_len;
fcs = *(net_buf_tail(buf) - sizeof(fcs));
if (!rfcomm_check_fcs(fcs_len, buf->data, fcs)) {
LOG_ERR("FCS check failed");
return 0;
}
net_buf_pull(buf, hdr_len);
switch (frame_type) {
case BT_RFCOMM_SABM:
rfcomm_handle_sabm(session, dlci);
break;
case BT_RFCOMM_UIH:
if (!dlci) {
rfcomm_handle_msg(session, buf);
} else {
rfcomm_handle_data(session, buf, dlci, BT_RFCOMM_GET_PF(hdr->control));
}
break;
case BT_RFCOMM_DISC:
rfcomm_handle_disc(session, dlci);
break;
case BT_RFCOMM_UA:
rfcomm_handle_ua(session, dlci);
break;
case BT_RFCOMM_DM:
rfcomm_handle_dm(session, dlci);
break;
default:
LOG_WRN("Unknown/Unsupported RFCOMM Frame type 0x%02x", frame_type);
break;
}
return 0;
}
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
static void rfcomm_encrypt_change(struct bt_l2cap_chan *chan,
uint8_t hci_status)
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
{
struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
struct bt_conn *conn = chan->conn;
struct bt_rfcomm_dlc *dlc, *next;
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
LOG_DBG("session %p status 0x%02x encr 0x%02x", session, hci_status, conn->encrypt);
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
for (dlc = session->dlcs; dlc; dlc = next) {
next = dlc->_next;
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
if (dlc->state != BT_RFCOMM_STATE_SECURITY_PENDING) {
continue;
}
if (hci_status || !conn->encrypt ||
conn->sec_level < dlc->required_sec_level) {
rfcomm_dlc_close(dlc);
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
continue;
}
if (dlc->role == BT_RFCOMM_ROLE_ACCEPTOR) {
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
rfcomm_send_ua(session, dlc->dlci);
rfcomm_dlc_connected(dlc);
} else {
dlc->mtu = MIN(dlc->mtu, session->mtu);
dlc->state = BT_RFCOMM_STATE_CONFIG;
rfcomm_send_pn(dlc, BT_RFCOMM_MSG_CMD_CR);
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
}
}
}
static void rfcomm_session_rtx_timeout(struct k_work *work)
{
struct bt_rfcomm_session *session = SESSION_RTX(work);
LOG_WRN("session %p state %d timeout", session, session->state);
switch (session->state) {
case BT_RFCOMM_STATE_CONNECTED:
rfcomm_session_disconnect(session);
break;
case BT_RFCOMM_STATE_DISCONNECTING:
session->state = BT_RFCOMM_STATE_DISCONNECTED;
if (bt_l2cap_chan_disconnect(&session->br_chan.chan) < 0) {
session->state = BT_RFCOMM_STATE_IDLE;
}
break;
}
}
static struct bt_rfcomm_session *rfcomm_session_new(bt_rfcomm_role_t role)
{
int i;
static const struct bt_l2cap_chan_ops ops = {
.connected = rfcomm_connected,
.disconnected = rfcomm_disconnected,
.recv = rfcomm_recv,
Bluetooth: RFCOMM: Handle security for incoming connections Added required_sec_level in dlc struct so that user can set it. If current security level is greater than or equal to the required security level then connection will be accepted right away, otherwise security elevation will be reqiested and connection will be accepted once it is done. > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 256 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Request (0x31) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) < HCI Command: IO Capability Request Reply (0x01|0x002b) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: Command Complete (0x0e) plen 10 IO Capability Request Reply (0x01|0x002b) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: IO Capability Response (0x32) plen 9 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) IO capability: DisplayYesNo (0x01) OOB data: Authentication data not present (0x00) Authentication: Dedicated Bonding - MITM required (0x03) > HCI Event: User Confirmation Request (0x33) plen 10 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Passkey: 104251 < HCI Command: User Confirmation Request Reply (0x01|0x002c) plen 6 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Command Complete (0x0e) plen 10 User Confirmation Request Reply (0x01|0x002c) ncmd 1 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Simple Pairing Complete (0x36) plen 7 Status: Success (0x00) Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) > HCI Event: Link Key Notification (0x18) plen 23 Address: A0:A8:CD:40:99:98 (OUI A0-A8-CD) Link key: 7c5e5bbc67268293202913902fd0d5fe Key type: Authenticated Combination key from P-192 (0x05) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 256 > HCI Event: Encryption Key Refresh Complete (0x30) plen 3 Status: Success (0x00) Handle: 256 < HCI Command: Set Connection Encryption (0x01|0x0013) plen 3 Handle: 256 Encryption: Enabled (0x01) > HCI Event: Command Status (0x0f) plen 4 Set Connection Encryption (0x01|0x0013) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 256 Encryption: Enabled with E0 (0x01) < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: Ia01f2984dda77d58b724f869eb526734f1846ad6 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
2016-10-03 21:03:52 +05:30
.encrypt_change = rfcomm_encrypt_change,
};
for (i = 0; i < ARRAY_SIZE(bt_rfcomm_pool); i++) {
struct bt_rfcomm_session *session = &bt_rfcomm_pool[i];
if (session->br_chan.chan.conn) {
continue;
}
LOG_DBG("session %p initialized", session);
session->br_chan.chan.ops = &ops;
session->br_chan.rx.mtu = CONFIG_BT_RFCOMM_L2CAP_MTU;
session->state = BT_RFCOMM_STATE_INIT;
session->role = role;
session->cfc = BT_RFCOMM_CFC_UNKNOWN;
k_work_init_delayable(&session->rtx_work,
rfcomm_session_rtx_timeout);
k_sem_init(&session->fc, 0, 1);
return session;
}
return NULL;
}
int bt_rfcomm_dlc_connect(struct bt_conn *conn, struct bt_rfcomm_dlc *dlc,
uint8_t channel)
{
struct bt_rfcomm_session *session;
struct bt_l2cap_chan *chan;
uint8_t dlci;
int ret;
LOG_DBG("conn %p dlc %p channel %d", conn, dlc, channel);
if (!dlc) {
return -EINVAL;
}
if (!conn || conn->state != BT_CONN_CONNECTED) {
return -ENOTCONN;
}
if (channel < RFCOMM_CHANNEL_START || channel > RFCOMM_CHANNEL_END) {
return -EINVAL;
}
2016-10-24 22:09:27 +05:30
if (!BT_RFCOMM_CHECK_MTU(dlc->mtu)) {
return -EINVAL;
}
session = rfcomm_sessions_lookup_bt_conn(conn);
if (!session) {
session = rfcomm_session_new(BT_RFCOMM_ROLE_INITIATOR);
if (!session) {
return -ENOMEM;
}
}
2016-10-24 22:09:27 +05:30
dlci = BT_RFCOMM_DLCI(session->role, channel);
if (rfcomm_dlcs_lookup_dlci(session->dlcs, dlci)) {
return -EBUSY;
}
rfcomm_dlc_init(dlc, session, dlci, BT_RFCOMM_ROLE_INITIATOR);
switch (session->state) {
case BT_RFCOMM_STATE_INIT:
if (session->role == BT_RFCOMM_ROLE_ACCEPTOR) {
/* There is an ongoing incoming conn */
break;
}
chan = &session->br_chan.chan;
BR_CHAN(chan)->required_sec_level = dlc->required_sec_level;
ret = bt_l2cap_chan_connect(conn, chan, BT_L2CAP_PSM_RFCOMM);
if (ret < 0) {
session->state = BT_RFCOMM_STATE_IDLE;
2016-10-24 22:09:27 +05:30
goto fail;
}
session->state = BT_RFCOMM_STATE_CONNECTING;
break;
case BT_RFCOMM_STATE_CONNECTING:
break;
case BT_RFCOMM_STATE_CONNECTED:
ret = rfcomm_dlc_start(dlc);
if (ret < 0) {
goto fail;
}
/* Cancel idle timer if any */
k_work_cancel_delayable(&session->rtx_work);
break;
default:
LOG_ERR("Invalid session state %d", session->state);
2016-10-24 22:09:27 +05:30
ret = -EINVAL;
goto fail;
}
return 0;
2016-10-24 22:09:27 +05:30
fail:
rfcomm_dlcs_remove_dlci(session->dlcs, dlc->dlci);
dlc->state = BT_RFCOMM_STATE_IDLE;
dlc->session = NULL;
return ret;
}
int bt_rfcomm_dlc_disconnect(struct bt_rfcomm_dlc *dlc)
{
LOG_DBG("dlc %p", dlc);
if (!dlc) {
return -EINVAL;
}
if (dlc->state == BT_RFCOMM_STATE_CONNECTED) {
/* This is to handle user initiated disconnect to send pending
* bufs in the queue before disconnecting
* Queue a dummy buffer (in case if queue is empty) to wake up
* and stop the tx thread.
*/
dlc->state = BT_RFCOMM_STATE_USER_DISCONNECT;
k_fifo_put(&dlc->tx_queue,
net: buf: Redesigned pool & buffer allocation API Until now it has been necessary to separately define a k_fifo and an array of buffers when creating net_buf pools. This has been a bit of an inconvenience as well as blurred the line of what exactly constitutes the "pool". This patch removes the NET_BUF_POOL() macro and replaces it with a NET_BUF_POOL_DEFINE() macro that internally expands into the buffer array and new net_buf_pool struct with a given name: NET_BUF_POOL_DEFINE(pool_name, ...); Having a dedicated context struct for the pool has the added benefit that we can start moving there net_buf members that have the same value for all buffers from the same pool. The first such member that gets moved is the destroy callback, thus shrinking net_buf by four bytes. Another potential candidate is the user_data_size, however right not that's left out since it would just leave 2 bytes of padding in net_buf (i.e. not influence its size). Another common value is buf->size, however that one is also used by net_buf_simple and can therefore not be moved. This patch also splits getting buffers from a FIFO and allocating a new buffer from a pool into two separate APIs: net_buf_get and net_buf_alloc, thus simplifying the APIs and their usage. There is no separate 'reserve_head' parameter anymore when allocating, rather the user is expected to call net_buf_reserve() afterwards if something else than 0 headroom is desired. Change-Id: Id91b1e5c2be2deb1274dde47f5edebfe29af383a Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-10-18 23:24:51 +03:00
net_buf_alloc(&dummy_pool, K_NO_WAIT));
k_work_reschedule(&dlc->rtx_work, RFCOMM_DISC_TIMEOUT);
return 0;
}
return rfcomm_dlc_close(dlc);
}
static int rfcomm_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
struct bt_l2cap_chan **chan)
{
struct bt_rfcomm_session *session;
LOG_DBG("conn %p", conn);
session = rfcomm_session_new(BT_RFCOMM_ROLE_ACCEPTOR);
if (session) {
*chan = &session->br_chan.chan;
return 0;
}
LOG_ERR("No available RFCOMM context for conn %p", conn);
return -ENOMEM;
}
void bt_rfcomm_init(void)
{
static struct bt_l2cap_server server = {
.psm = BT_L2CAP_PSM_RFCOMM,
.accept = rfcomm_accept,
.sec_level = BT_SECURITY_L1,
};
bt_l2cap_br_server_register(&server);
}