<commit_before>/*
 * Copyright (c) 2016-2018 Nordic Semiconductor ASA
 * Copyright (c) 2016 <NAME>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stddef.h>
#include <zephyr/types.h>
#include <string.h>
#include <version.h>

#include <soc.h>
#include <toolchain.h>
#include <errno.h>
#include <atomic.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_vs.h>
#include <bluetooth/buf.h>
#include <bluetooth/bluetooth.h>
#include <drivers/bluetooth/hci_driver.h>
#include <misc/byteorder.h>
#include <misc/util.h>

#include "util/util.h"
#include "util/memq.h"
#include "hal/ecb.h"
#include "hal/ccm.h"
#include "ll_sw/pdu.h"
#include "ll_sw/lll.h"
#include "ll_sw/lll_conn.h"
#include "ll_sw/ull_conn_types.h"
#include "ll.h"
#include "ll_feat.h"
#include "hci_internal.h"

#if defined(CONFIG_BT_HCI_MESH_EXT)
#include "ll_sw/ll_mesh.h"
#endif /* CONFIG_BT_HCI_MESH_EXT */

#if defined(CONFIG_BT_CTLR_DTM_HCI)
#include "ll_sw/ll_test.h"
#endif /* CONFIG_BT_CTLR_DTM_HCI */

#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_hci
#include "common/log.h"
#include "hal/debug.h"

/* opcode of the HCI command currently being processed. The opcode is stored
 * by hci_cmd_handle() and then used during the creation of cmd complete and
 * cmd status events to avoid passing it up the call chain.
 */
static u16_t _opcode;

#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
/* Scan duplicate filter */
struct dup {
	u8_t         mask;
	bt_addr_le_t addr;
};
static struct dup dup_filter[CONFIG_BT_CTLR_DUP_FILTER_LEN];
static s32_t dup_count;
static u32_t dup_curr;
#endif

#if defined(CONFIG_BT_HCI_MESH_EXT)
struct scan_filter {
	u8_t count;
	u8_t lengths[CONFIG_BT_CTLR_MESH_SF_PATTERNS];
	u8_t patterns[CONFIG_BT_CTLR_MESH_SF_PATTERNS]
		     [BT_HCI_MESH_PATTERN_LEN_MAX];
};

static struct scan_filter scan_filters[CONFIG_BT_CTLR_MESH_SCAN_FILTERS];
static u8_t sf_curr;
#endif

#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
s32_t    hci_hbuf_total;
u32_t    hci_hbuf_sent;
u32_t    hci_hbuf_acked;
u16_t    hci_hbuf_pend[CONFIG_BT_MAX_CONN];
atomic_t hci_state_mask;
static struct k_poll_signal *hbuf_signal;
#endif

#if defined(CONFIG_BT_CONN)
static u32_t conn_count;
#endif

#define DEFAULT_EVENT_MASK           0x1fffffffffff
#define DEFAULT_EVENT_MASK_PAGE_2    0x0
#define DEFAULT_LE_EVENT_MASK 0x1f

static u64_t event_mask = DEFAULT_EVENT_MASK;
static u64_t event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
static u64_t le_event_mask = DEFAULT_LE_EVENT_MASK;

#if defined(CONFIG_BT_CONN)
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
			     struct net_buf *buf);
#endif /* CONFIG_BT_CONN */

static void evt_create(struct net_buf *buf, u8_t evt, u8_t len)
{
	struct bt_hci_evt_hdr *hdr;

	hdr = net_buf_add(buf, sizeof(*hdr));
	hdr->evt = evt;
	hdr->len = len;
}

static void *cmd_complete(struct net_buf **buf, u8_t plen)
{
	struct bt_hci_evt_cmd_complete *cc;

	*buf = bt_buf_get_cmd_complete(K_FOREVER);

	evt_create(*buf, BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen);

	cc = net_buf_add(*buf, sizeof(*cc));
	cc->ncmd = 1;
	cc->opcode = sys_cpu_to_le16(_opcode);

	return net_buf_add(*buf, plen);
}

#if defined(CONFIG_BT_CONN)
static struct net_buf *cmd_status(u8_t status)
{
	struct bt_hci_evt_cmd_status *cs;
	struct net_buf *buf;

	buf = bt_buf_get_cmd_complete(K_FOREVER);
	evt_create(buf, BT_HCI_EVT_CMD_STATUS, sizeof(*cs));

	cs = net_buf_add(buf, sizeof(*cs));
	cs->status = status;
	cs->ncmd = 1;
	cs->opcode = sys_cpu_to_le16(_opcode);

	return buf;
}
#endif

static void *meta_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
{
	struct bt_hci_evt_le_meta_event *me;

	evt_create(buf, BT_HCI_EVT_LE_META_EVENT, sizeof(*me) + melen);
	me = net_buf_add(buf, sizeof(*me));
	me->subevent = subevt;

	return net_buf_add(buf, melen);
}

#if defined(CONFIG_BT_HCI_MESH_EXT)
static void *mesh_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
{
	struct bt_hci_evt_mesh *me;

	evt_create(buf, BT_HCI_EVT_VENDOR, sizeof(*me) + melen);
	me = net_buf_add(buf, sizeof(*me));
	me->prefix = BT_HCI_MESH_EVT_PREFIX;
	me->subevent = subevt;

	return net_buf_add(buf, melen);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */

#if defined(CONFIG_BT_CONN)
static void disconnect(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_disconnect *cmd = (void *)buf->data;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);
	status = ll_terminate_ind_send(handle, cmd->reason);

	*evt = cmd_status(status);
}

static void read_remote_ver_info(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_read_remote_version_info *cmd = (void *)buf->data;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);
	status = ll_version_ind_send(handle);

	*evt = cmd_status(status);
}
#endif /* CONFIG_BT_CONN */

static int link_control_cmd_handle(u16_t  ocf, struct net_buf *cmd,
				   struct net_buf **evt)
{
	switch (ocf) {
#if defined(CONFIG_BT_CONN)
	case BT_OCF(BT_HCI_OP_DISCONNECT):
		disconnect(cmd, evt);
		break;
	case BT_OCF(BT_HCI_OP_READ_REMOTE_VERSION_INFO):
		read_remote_ver_info(cmd, evt);
		break;
#endif /* CONFIG_BT_CONN */
	default:
		return -EINVAL;
	}

	return 0;
}

static void set_event_mask(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_set_event_mask *cmd = (void *)buf->data;
	struct bt_hci_evt_cc_status *ccst;

	event_mask = sys_get_le64(cmd->events);

	ccst = cmd_complete(evt, sizeof(*ccst));
	ccst->status = 0x00;
}

static void set_event_mask_page_2(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_set_event_mask_page_2 *cmd = (void *)buf->data;
	struct bt_hci_evt_cc_status *ccst;

	event_mask_page_2 = sys_get_le64(cmd->events_page_2);

	ccst = cmd_complete(evt, sizeof(*ccst));
	ccst->status = 0x00;
}

static void reset(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_evt_cc_status *ccst;

#if defined(CONFIG_BT_HCI_MESH_EXT)
	int i;

	for (i = 0; i < ARRAY_SIZE(scan_filters); i++) {
		scan_filters[i].count = 0;
	}
	sf_curr = 0xFF;
#endif

#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
	dup_count = -1;
#endif

	/* reset event masks */
	event_mask = DEFAULT_EVENT_MASK;
	event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
	le_event_mask = DEFAULT_LE_EVENT_MASK;

	if (buf) {
		ll_reset();
		ccst = cmd_complete(evt, sizeof(*ccst));
		ccst->status = 0x00;
	}

#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
	hci_hbuf_total = 0;
	hci_hbuf_sent = 0U;
	hci_hbuf_acked = 0U;
	(void)memset(hci_hbuf_pend, 0, sizeof(hci_hbuf_pend));
	conn_count = 0U;
	if (buf) {
		atomic_set_bit(&hci_state_mask, HCI_STATE_BIT_RESET);
		k_poll_signal_raise(hbuf_signal, 0x0);
	}
#endif
}

#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
static void set_ctl_to_host_flow(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_set_ctl_to_host_flow *cmd = (void *)buf->data;
	u8_t flow_enable = cmd->flow_enable;
	struct bt_hci_evt_cc_status *ccst;

	ccst = cmd_complete(evt, sizeof(*ccst));

	/* require host buffer size before enabling flow control, and
	 * disallow if any connections are up
	 */
	if (!hci_hbuf_total || conn_count) {
		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
		return;
	} else {
		ccst->status = 0x00;
	}

	switch (flow_enable) {
	case BT_HCI_CTL_TO_HOST_FLOW_DISABLE:
		if (hci_hbuf_total < 0) {
			/* already disabled */
			return;
		}
		break;
	case BT_HCI_CTL_TO_HOST_FLOW_ENABLE:
		if (hci_hbuf_total > 0) {
			/* already enabled */
			return;
		}
		break;
	default:
		ccst->status = BT_HCI_ERR_INVALID_PARAM;
		return;
	}

	hci_hbuf_sent = 0U;
	hci_hbuf_acked = 0U;
	(void)memset(hci_hbuf_pend, 0, sizeof(hci_hbuf_pend));
	hci_hbuf_total = -hci_hbuf_total;
}

static void host_buffer_size(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_host_buffer_size *cmd = (void *)buf->data;
	u16_t acl_pkts = sys_le16_to_cpu(cmd->acl_pkts);
	u16_t acl_mtu = sys_le16_to_cpu(cmd->acl_mtu);
	struct bt_hci_evt_cc_status *ccst;

	ccst = cmd_complete(evt, sizeof(*ccst));

	if (hci_hbuf_total) {
		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
		return;
	}
	/* fragmentation from controller to host not supported, require
	 * ACL MTU to be at least the LL MTU
	 */
	if (acl_mtu < LL_LENGTH_OCTETS_RX_MAX) {
		ccst->status = BT_HCI_ERR_INVALID_PARAM;
		return;
	}

	BT_DBG("FC: host buf size: %d", acl_pkts);
	hci_hbuf_total = -acl_pkts;
}

static void host_num_completed_packets(struct net_buf *buf,
				       struct net_buf **evt)
{
	struct bt_hci_cp_host_num_completed_packets *cmd = (void *)buf->data;
	struct bt_hci_evt_cc_status *ccst;
	u32_t count = 0U;
	int i;

	/* special case, no event returned except for error conditions */
	if (hci_hbuf_total <= 0) {
		ccst = cmd_complete(evt, sizeof(*ccst));
		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
		return;
	} else if (!conn_count) {
		ccst = cmd_complete(evt, sizeof(*ccst));
		ccst->status = BT_HCI_ERR_INVALID_PARAM;
		return;
	}

	/* leave *evt == NULL so no event is generated */
	for (i = 0; i < cmd->num_handles; i++) {
		u16_t h = sys_le16_to_cpu(cmd->h[i].handle);
		u16_t c = sys_le16_to_cpu(cmd->h[i].count);

		if ((h >= ARRAY_SIZE(hci_hbuf_pend)) ||
		    (c > hci_hbuf_pend[h])) {
			ccst = cmd_complete(evt, sizeof(*ccst));
			ccst->status = BT_HCI_ERR_INVALID_PARAM;
			return;
		}

		hci_hbuf_pend[h] -= c;
		count += c;
	}

	BT_DBG("FC: acked: %d", count);
	hci_hbuf_acked += count;
	k_poll_signal_raise(hbuf_signal, 0x0);
}
#endif

#if defined(CONFIG_BT_CTLR_LE_PING)
static void read_auth_payload_timeout(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_read_auth_payload_timeout *cmd = (void *)buf->data;
	struct bt_hci_rp_read_auth_payload_timeout *rp;
	u16_t auth_payload_timeout;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);

	status = ll_apto_get(handle, &auth_payload_timeout);

	rp = cmd_complete(evt, sizeof(*rp));
	rp->status = status;
	rp->handle = sys_cpu_to_le16(handle);
	rp->auth_payload_timeout = sys_cpu_to_le16(auth_payload_timeout);
}

static void write_auth_payload_timeout(struct net_buf *buf,
				       struct net_buf **evt)
{
	struct bt_hci_cp_write_auth_payload_timeout *cmd = (void *)buf->data;
	struct bt_hci_rp_write_auth_payload_timeout *rp;
	u16_t auth_payload_timeout;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);
	auth_payload_timeout = sys_le16_to_cpu(cmd->auth_payload_timeout);

	status = ll_apto_set(handle, auth_payload_timeout);

	rp = cmd_complete(evt, sizeof(*rp));
	rp->status = status;
	rp->handle = sys_cpu_to_le16(handle);
}
#endif /* CONFIG_BT_CTLR_LE_PING */

static void read_tx_power_level(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_read_tx_power_level *cmd = (void *)buf->data;
	struct bt_hci_rp_read_tx_power_level *rp;
	u16_t handle;
	u8_t status;
	u8_t type;

	handle = sys_le16_to_cpu(cmd->handle);
	type = cmd->type;

	rp = cmd_complete(evt, sizeof(*rp));

	status = ll_tx_pwr_lvl_get(handle, type, &rp->tx_power_level);

	rp->status = status;
	rp->handle = sys_cpu_to_le16(handle);
}

static int ctrl_bb_cmd_handle(u16_t  ocf, struct net_buf *cmd,
			      struct net_buf **evt)
{
	switch (ocf) {
	case BT_OCF(BT_HCI_OP_SET_EVENT_MASK):
		set_event_mask(cmd, evt);
		break;

	case BT_OCF(BT_HCI_OP_RESET):
		reset(cmd, evt);
		break;

	case BT_OCF(BT_HCI_OP_SET_EVENT_MASK_PAGE_2):
		set_event_mask_page_2(cmd, evt);
		break;

	case BT_OCF(BT_HCI_OP_READ_TX_POWER_LEVEL):
		read_tx_power_level(cmd, evt);
		break;<commit_msg>Bluetooth: controller: Read Tx Power Level depends on Connections<commit_after>/*
 * Copyright (c) 2016-2018 Nordic Semiconductor ASA
 * Copyright (c) 2016 <NAME>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stddef.h>
#include <zephyr/types.h>
#include <string.h>
#include <version.h>

#include <soc.h>
#include <toolchain.h>
#include <errno.h>
#include <atomic.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_vs.h>
#include <bluetooth/buf.h>
#include <bluetooth/bluetooth.h>
#include <drivers/bluetooth/hci_driver.h>
#include <misc/byteorder.h>
#include <misc/util.h>

#include "util/util.h"
#include "util/memq.h"
#include "hal/ecb.h"
#include "hal/ccm.h"
#include "ll_sw/pdu.h"
#include "ll_sw/lll.h"
#include "ll_sw/lll_conn.h"
#include "ll_sw/ull_conn_types.h"
#include "ll.h"
#include "ll_feat.h"
#include "hci_internal.h"

#if defined(CONFIG_BT_HCI_MESH_EXT)
#include "ll_sw/ll_mesh.h"
#endif /* CONFIG_BT_HCI_MESH_EXT */

#if defined(CONFIG_BT_CTLR_DTM_HCI)
#include "ll_sw/ll_test.h"
#endif /* CONFIG_BT_CTLR_DTM_HCI */

#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_hci
#include "common/log.h"
#include "hal/debug.h"

/* opcode of the HCI command currently being processed. The opcode is stored
 * by hci_cmd_handle() and then used during the creation of cmd complete and
 * cmd status events to avoid passing it up the call chain.
 */
static u16_t _opcode;

#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
/* Scan duplicate filter */
struct dup {
	u8_t         mask;
	bt_addr_le_t addr;
};
static struct dup dup_filter[CONFIG_BT_CTLR_DUP_FILTER_LEN];
static s32_t dup_count;
static u32_t dup_curr;
#endif

#if defined(CONFIG_BT_HCI_MESH_EXT)
struct scan_filter {
	u8_t count;
	u8_t lengths[CONFIG_BT_CTLR_MESH_SF_PATTERNS];
	u8_t patterns[CONFIG_BT_CTLR_MESH_SF_PATTERNS]
		     [BT_HCI_MESH_PATTERN_LEN_MAX];
};

static struct scan_filter scan_filters[CONFIG_BT_CTLR_MESH_SCAN_FILTERS];
static u8_t sf_curr;
#endif

#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
s32_t    hci_hbuf_total;
u32_t    hci_hbuf_sent;
u32_t    hci_hbuf_acked;
u16_t    hci_hbuf_pend[CONFIG_BT_MAX_CONN];
atomic_t hci_state_mask;
static struct k_poll_signal *hbuf_signal;
#endif

#if defined(CONFIG_BT_CONN)
static u32_t conn_count;
#endif

#define DEFAULT_EVENT_MASK           0x1fffffffffff
#define DEFAULT_EVENT_MASK_PAGE_2    0x0
#define DEFAULT_LE_EVENT_MASK 0x1f

static u64_t event_mask = DEFAULT_EVENT_MASK;
static u64_t event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
static u64_t le_event_mask = DEFAULT_LE_EVENT_MASK;

#if defined(CONFIG_BT_CONN)
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
			     struct net_buf *buf);
#endif /* CONFIG_BT_CONN */

static void evt_create(struct net_buf *buf, u8_t evt, u8_t len)
{
	struct bt_hci_evt_hdr *hdr;

	hdr = net_buf_add(buf, sizeof(*hdr));
	hdr->evt = evt;
	hdr->len = len;
}

static void *cmd_complete(struct net_buf **buf, u8_t plen)
{
	struct bt_hci_evt_cmd_complete *cc;

	*buf = bt_buf_get_cmd_complete(K_FOREVER);

	evt_create(*buf, BT_HCI_EVT_CMD_COMPLETE, sizeof(*cc) + plen);

	cc = net_buf_add(*buf, sizeof(*cc));
	cc->ncmd = 1;
	cc->opcode = sys_cpu_to_le16(_opcode);

	return net_buf_add(*buf, plen);
}

#if defined(CONFIG_BT_CONN)
static struct net_buf *cmd_status(u8_t status)
{
	struct bt_hci_evt_cmd_status *cs;
	struct net_buf *buf;

	buf = bt_buf_get_cmd_complete(K_FOREVER);
	evt_create(buf, BT_HCI_EVT_CMD_STATUS, sizeof(*cs));

	cs = net_buf_add(buf, sizeof(*cs));
	cs->status = status;
	cs->ncmd = 1;
	cs->opcode = sys_cpu_to_le16(_opcode);

	return buf;
}
#endif

static void *meta_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
{
	struct bt_hci_evt_le_meta_event *me;

	evt_create(buf, BT_HCI_EVT_LE_META_EVENT, sizeof(*me) + melen);
	me = net_buf_add(buf, sizeof(*me));
	me->subevent = subevt;

	return net_buf_add(buf, melen);
}

#if defined(CONFIG_BT_HCI_MESH_EXT)
static void *mesh_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
{
	struct bt_hci_evt_mesh *me;

	evt_create(buf, BT_HCI_EVT_VENDOR, sizeof(*me) + melen);
	me = net_buf_add(buf, sizeof(*me));
	me->prefix = BT_HCI_MESH_EVT_PREFIX;
	me->subevent = subevt;

	return net_buf_add(buf, melen);
}
#endif /* CONFIG_BT_HCI_MESH_EXT */

#if defined(CONFIG_BT_CONN)
static void disconnect(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_disconnect *cmd = (void *)buf->data;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);
	status = ll_terminate_ind_send(handle, cmd->reason);

	*evt = cmd_status(status);
}

static void read_remote_ver_info(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_read_remote_version_info *cmd = (void *)buf->data;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);
	status = ll_version_ind_send(handle);

	*evt = cmd_status(status);
}
#endif /* CONFIG_BT_CONN */

static int link_control_cmd_handle(u16_t  ocf, struct net_buf *cmd,
				   struct net_buf **evt)
{
	switch (ocf) {
#if defined(CONFIG_BT_CONN)
	case BT_OCF(BT_HCI_OP_DISCONNECT):
		disconnect(cmd, evt);
		break;
	case BT_OCF(BT_HCI_OP_READ_REMOTE_VERSION_INFO):
		read_remote_ver_info(cmd, evt);
		break;
#endif /* CONFIG_BT_CONN */
	default:
		return -EINVAL;
	}

	return 0;
}

static void set_event_mask(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_set_event_mask *cmd = (void *)buf->data;
	struct bt_hci_evt_cc_status *ccst;

	event_mask = sys_get_le64(cmd->events);

	ccst = cmd_complete(evt, sizeof(*ccst));
	ccst->status = 0x00;
}

static void set_event_mask_page_2(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_set_event_mask_page_2 *cmd = (void *)buf->data;
	struct bt_hci_evt_cc_status *ccst;

	event_mask_page_2 = sys_get_le64(cmd->events_page_2);

	ccst = cmd_complete(evt, sizeof(*ccst));
	ccst->status = 0x00;
}

static void reset(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_evt_cc_status *ccst;

#if defined(CONFIG_BT_HCI_MESH_EXT)
	int i;

	for (i = 0; i < ARRAY_SIZE(scan_filters); i++) {
		scan_filters[i].count = 0;
	}
	sf_curr = 0xFF;
#endif

#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
	dup_count = -1;
#endif

	/* reset event masks */
	event_mask = DEFAULT_EVENT_MASK;
	event_mask_page_2 = DEFAULT_EVENT_MASK_PAGE_2;
	le_event_mask = DEFAULT_LE_EVENT_MASK;

	if (buf) {
		ll_reset();
		ccst = cmd_complete(evt, sizeof(*ccst));
		ccst->status = 0x00;
	}

#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
	hci_hbuf_total = 0;
	hci_hbuf_sent = 0U;
	hci_hbuf_acked = 0U;
	(void)memset(hci_hbuf_pend, 0, sizeof(hci_hbuf_pend));
	conn_count = 0U;
	if (buf) {
		atomic_set_bit(&hci_state_mask, HCI_STATE_BIT_RESET);
		k_poll_signal_raise(hbuf_signal, 0x0);
	}
#endif
}

#if defined(CONFIG_BT_HCI_ACL_FLOW_CONTROL)
static void set_ctl_to_host_flow(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_set_ctl_to_host_flow *cmd = (void *)buf->data;
	u8_t flow_enable = cmd->flow_enable;
	struct bt_hci_evt_cc_status *ccst;

	ccst = cmd_complete(evt, sizeof(*ccst));

	/* require host buffer size before enabling flow control, and
	 * disallow if any connections are up
	 */
	if (!hci_hbuf_total || conn_count) {
		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
		return;
	} else {
		ccst->status = 0x00;
	}

	switch (flow_enable) {
	case BT_HCI_CTL_TO_HOST_FLOW_DISABLE:
		if (hci_hbuf_total < 0) {
			/* already disabled */
			return;
		}
		break;
	case BT_HCI_CTL_TO_HOST_FLOW_ENABLE:
		if (hci_hbuf_total > 0) {
			/* already enabled */
			return;
		}
		break;
	default:
		ccst->status = BT_HCI_ERR_INVALID_PARAM;
		return;
	}

	hci_hbuf_sent = 0U;
	hci_hbuf_acked = 0U;
	(void)memset(hci_hbuf_pend, 0, sizeof(hci_hbuf_pend));
	hci_hbuf_total = -hci_hbuf_total;
}

static void host_buffer_size(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_host_buffer_size *cmd = (void *)buf->data;
	u16_t acl_pkts = sys_le16_to_cpu(cmd->acl_pkts);
	u16_t acl_mtu = sys_le16_to_cpu(cmd->acl_mtu);
	struct bt_hci_evt_cc_status *ccst;

	ccst = cmd_complete(evt, sizeof(*ccst));

	if (hci_hbuf_total) {
		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
		return;
	}
	/* fragmentation from controller to host not supported, require
	 * ACL MTU to be at least the LL MTU
	 */
	if (acl_mtu < LL_LENGTH_OCTETS_RX_MAX) {
		ccst->status = BT_HCI_ERR_INVALID_PARAM;
		return;
	}

	BT_DBG("FC: host buf size: %d", acl_pkts);
	hci_hbuf_total = -acl_pkts;
}

static void host_num_completed_packets(struct net_buf *buf,
				       struct net_buf **evt)
{
	struct bt_hci_cp_host_num_completed_packets *cmd = (void *)buf->data;
	struct bt_hci_evt_cc_status *ccst;
	u32_t count = 0U;
	int i;

	/* special case, no event returned except for error conditions */
	if (hci_hbuf_total <= 0) {
		ccst = cmd_complete(evt, sizeof(*ccst));
		ccst->status = BT_HCI_ERR_CMD_DISALLOWED;
		return;
	} else if (!conn_count) {
		ccst = cmd_complete(evt, sizeof(*ccst));
		ccst->status = BT_HCI_ERR_INVALID_PARAM;
		return;
	}

	/* leave *evt == NULL so no event is generated */
	for (i = 0; i < cmd->num_handles; i++) {
		u16_t h = sys_le16_to_cpu(cmd->h[i].handle);
		u16_t c = sys_le16_to_cpu(cmd->h[i].count);

		if ((h >= ARRAY_SIZE(hci_hbuf_pend)) ||
		    (c > hci_hbuf_pend[h])) {
			ccst = cmd_complete(evt, sizeof(*ccst));
			ccst->status = BT_HCI_ERR_INVALID_PARAM;
			return;
		}

		hci_hbuf_pend[h] -= c;
		count += c;
	}

	BT_DBG("FC: acked: %d", count);
	hci_hbuf_acked += count;
	k_poll_signal_raise(hbuf_signal, 0x0);
}
#endif

#if defined(CONFIG_BT_CTLR_LE_PING)
static void read_auth_payload_timeout(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_read_auth_payload_timeout *cmd = (void *)buf->data;
	struct bt_hci_rp_read_auth_payload_timeout *rp;
	u16_t auth_payload_timeout;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);

	status = ll_apto_get(handle, &auth_payload_timeout);

	rp = cmd_complete(evt, sizeof(*rp));
	rp->status = status;
	rp->handle = sys_cpu_to_le16(handle);
	rp->auth_payload_timeout = sys_cpu_to_le16(auth_payload_timeout);
}

static void write_auth_payload_timeout(struct net_buf *buf,
				       struct net_buf **evt)
{
	struct bt_hci_cp_write_auth_payload_timeout *cmd = (void *)buf->data;
	struct bt_hci_rp_write_auth_payload_timeout *rp;
	u16_t auth_payload_timeout;
	u16_t handle;
	u8_t status;

	handle = sys_le16_to_cpu(cmd->handle);
	auth_payload_timeout = sys_le16_to_cpu(cmd->auth_payload_timeout);

	status = ll_apto_set(handle, auth_payload_timeout);

	rp = cmd_complete(evt, sizeof(*rp));
	rp->status = status;
	rp->handle = sys_cpu_to_le16(handle);
}
#endif /* CONFIG_BT_CTLR_LE_PING */

#if defined(CONFIG_BT_CONN)
static void read_tx_power_level(struct net_buf *buf, struct net_buf **evt)
{
	struct bt_hci_cp_read_tx_power_level *cmd = (void *)buf->data;
	struct bt_hci_rp_read_tx_power_level *rp;
	u16_t handle;
	u8_t status;
	u8_t type;

	handle = sys_le16_to_cpu(cmd->handle);
	type = cmd->type;

	rp = cmd_complete(evt, sizeof(*rp));

	status = ll_tx_pwr_lvl_get(handle, type, &rp->tx_power_level);

	rp->status = status;
	rp->handle = sys_cpu_to_le16(handle);
}
#endif /* CONFIG_BT_CONN */

static int ctrl_bb_cmd_handle(u16_t  ocf, struct net_buf *cmd,
			      struct net_buf **evt)
{
	switch (ocf) {
	case BT_OCF(BT_HCI_OP_SET_EVENT_MASK):
		set_event_mask(cmd, evt);
		break;

	case BT_OCF(BT_HCI_OP_RESET):
		reset(cmd, evt);
		break;

	case BT_OCF(BT_HCI_OP_SET_EVENT_MASK_PAGE_2):
		set_event_mask_page_2(cmd, evt);
		break;

#if defined(CONFIG_BT_CONN)
	case BT_OCF(BT_HCI_OP_READ_TX_POWER_LEVEL):
		read_tx_power_level(cmd, evt);
		break;
#endif /* CONFIG_BT_CONN */
{'fraction_non_alphanumeric': 0.1165665534952555, 'fraction_numerical': 0.01540872290415252, 'mean_word_length': 5.397939292676135, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 155, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5510290', 'n_tokens_mistral': 10108, 'n_tokens_neox': 9875, 'n_words': 1875}