zephyr/net/bluetooth/buf.c
Johan Hedberg ea11d4b5cd Bluetooth: Add helper macros for accessing Bluetooth user data
To avoid unnecessary stack variables and to simplify code, add helper
macros to access the Bluetooth specific ACL and HCI user data that's
part of the buffers.

Change-Id: Idc337537721115c4091982c04f8a05bbbf0d5a19
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-02-05 20:24:39 -05:00

119 lines
3 KiB
C

/* buf.c - Bluetooth buffer management */
/*
* Copyright (c) 2015 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <nanokernel.h>
#include <toolchain.h>
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <atomic.h>
#include <misc/byteorder.h>
#include <bluetooth/log.h>
#include <bluetooth/hci.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/buf.h>
#include "hci_core.h"
#if !defined(CONFIG_BLUETOOTH_DEBUG_BUF)
#undef BT_DBG
#define BT_DBG(fmt, ...)
#endif
/* Available (free) buffers queues */
static struct nano_fifo avail_hci;
static NET_BUF_POOL(hci_pool, 8, BT_BUF_MAX_DATA, &avail_hci, NULL,
sizeof(struct bt_hci_data));
#if defined(CONFIG_BLUETOOTH_CONN)
static void report_completed_packet(struct net_buf *buf)
{
struct bt_hci_cp_host_num_completed_packets *cp;
struct bt_hci_handle_count *hc;
BT_DBG("Reporting completed packet for handle %u\n",
bt_acl(buf)->handle);
buf = bt_hci_cmd_create(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS,
sizeof(*cp) + sizeof(*hc));
if (!buf) {
BT_ERR("Unable to allocate new HCI command\n");
return;
}
cp = net_buf_add(buf, sizeof(*cp));
cp->num_handles = sys_cpu_to_le16(1);
hc = net_buf_add(buf, sizeof(*hc));
hc->handle = sys_cpu_to_le16(bt_acl(buf)->handle);
hc->count = sys_cpu_to_le16(1);
bt_hci_cmd_send(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS, buf);
}
static struct nano_fifo avail_acl_in;
static struct nano_fifo avail_acl_out;
static NET_BUF_POOL(acl_in_pool, BT_BUF_ACL_IN_MAX, BT_BUF_MAX_DATA,
&avail_acl_in, report_completed_packet,
sizeof(struct bt_acl_data));
static NET_BUF_POOL(acl_out_pool, BT_BUF_ACL_OUT_MAX, BT_BUF_MAX_DATA,
&avail_acl_out, NULL, sizeof(struct bt_acl_data));
#endif /* CONFIG_BLUETOOTH_CONN */
struct net_buf *bt_buf_get(enum bt_buf_type type, size_t reserve_head)
{
struct net_buf *buf;
switch (type) {
case BT_CMD:
case BT_EVT:
buf = net_buf_get(&avail_hci, reserve_head);
break;
#if defined(CONFIG_BLUETOOTH_CONN)
case BT_ACL_IN:
buf = net_buf_get(&avail_acl_in, reserve_head);
break;
case BT_ACL_OUT:
buf = net_buf_get(&avail_acl_out, reserve_head);
break;
#endif /* CONFIG_BLUETOOTH_CONN */
default:
return NULL;
}
if (buf) {
uint8_t *buf_type = net_buf_user_data(buf);
*buf_type = type;
}
return buf;
}
int bt_buf_init(void)
{
#if defined(CONFIG_BLUETOOTH_CONN)
net_buf_pool_init(acl_in_pool);
net_buf_pool_init(acl_out_pool);
#endif /* CONFIG_BLUETOOTH_CONN */
net_buf_pool_init(hci_pool);
return 0;
}