The ll/ folder contains a full implementation of a BLE Link Layer interfacing with a baseband and a radio through radio.h. The current code implements most Bluetooth 4.2 features and is currently functional and tested with nRF5x ICs from Nordic Semiconductor. Jira: ZEP-702 Origin: Original Change-Id: Ib79cd97142d1a72c99dcf2a88116ac97ddd90a2b Signed-off-by: Vinayak Chettimada <vinayak.kariappa.chettimada@nordicsemi.no> Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
255 lines
8.3 KiB
C
255 lines
8.3 KiB
C
/*
|
|
* Copyright (c) 2016 Nordic Semiconductor ASA
|
|
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef _CTRL_H_
|
|
#define _CTRL_H_
|
|
|
|
/*****************************************************************************
|
|
* Zephyr Kconfig defined
|
|
****************************************************************************/
|
|
#ifdef CONFIG_BLUETOOTH_MAX_CONN
|
|
#define RADIO_CONNECTION_CONTEXT_MAX CONFIG_BLUETOOTH_MAX_CONN
|
|
#else
|
|
#define RADIO_CONNECTION_CONTEXT_MAX 0
|
|
#endif
|
|
|
|
#ifdef CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH
|
|
#define RADIO_LL_LENGTH_OCTETS_RX_MAX \
|
|
CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH
|
|
#endif
|
|
|
|
#ifdef CONFIG_BLUETOOTH_CONTROLLER_RX_BUFFERS
|
|
#define RADIO_PACKET_COUNT_RX_MAX \
|
|
CONFIG_BLUETOOTH_CONTROLLER_RX_BUFFERS
|
|
#endif
|
|
|
|
#ifdef CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFERS
|
|
#define RADIO_PACKET_COUNT_TX_MAX \
|
|
CONFIG_BLUETOOTH_CONTROLLER_TX_BUFFERS
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* Timer Resources (Controller defined)
|
|
****************************************************************************/
|
|
#define RADIO_TICKER_ID_EVENT 0
|
|
#define RADIO_TICKER_ID_MARKER_0 1
|
|
#define RADIO_TICKER_ID_PRE_EMPT 2
|
|
#define RADIO_TICKER_ID_ADV_STOP 3
|
|
#define RADIO_TICKER_ID_OBS_STOP 4
|
|
#define RADIO_TICKER_ID_ADV 5
|
|
#define RADIO_TICKER_ID_OBS 6
|
|
#define RADIO_TICKER_ID_FIRST_CONNECTION 7
|
|
|
|
#define RADIO_TICKER_INSTANCE_ID_RADIO 0
|
|
#define RADIO_TICKER_INSTANCE_ID_APP 1
|
|
|
|
#define RADIO_TICKER_USERS 3
|
|
|
|
#define RADIO_TICKER_USER_ID_WORKER 0
|
|
#define RADIO_TICKER_USER_ID_JOB 1
|
|
#define RADIO_TICKER_USER_ID_APP 2
|
|
|
|
#define RADIO_TICKER_USER_WORKER_OPS (7 + 1)
|
|
#define RADIO_TICKER_USER_JOB_OPS (2 + 1)
|
|
#define RADIO_TICKER_USER_APP_OPS (1 + 1)
|
|
#define RADIO_TICKER_USER_OPS (RADIO_TICKER_USER_WORKER_OPS \
|
|
+ RADIO_TICKER_USER_JOB_OPS \
|
|
+ RADIO_TICKER_USER_APP_OPS \
|
|
)
|
|
|
|
#define RADIO_TICKER_NODES (RADIO_TICKER_ID_FIRST_CONNECTION \
|
|
+ RADIO_CONNECTION_CONTEXT_MAX \
|
|
)
|
|
|
|
/*****************************************************************************
|
|
* Controller Interface Defines
|
|
****************************************************************************/
|
|
#define RADIO_BLE_VERSION_NUMBER (0x08)
|
|
#define RADIO_BLE_COMPANY_ID (0xFFFF)
|
|
#define RADIO_BLE_SUB_VERSION_NUMBER (0xFFFF)
|
|
#define RADIO_BLE_FEATURES (0x1F) /* LE Ping, Slave Initiated
|
|
* Feature request, Extended
|
|
* Reject Indication, Conn Param
|
|
* Req Procedure, LE encryption.
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* Controller Reference Defines (compile time override-able)
|
|
****************************************************************************/
|
|
/* Minimum LL Payload support (Dont change). */
|
|
#define RADIO_LL_LENGTH_OCTETS_RX_MIN 27
|
|
#define RADIO_LL_LENGTH_TIME_RX_MIN (((RADIO_LL_LENGTH_OCTETS_RX_MIN) \
|
|
+ 14) * 8 \
|
|
)
|
|
|
|
/* Maximum LL Payload support (27 to 251). */
|
|
#ifndef RADIO_LL_LENGTH_OCTETS_RX_MAX
|
|
#define RADIO_LL_LENGTH_OCTETS_RX_MAX 251
|
|
#endif
|
|
#define RADIO_LL_LENGTH_TIME_RX_MAX (((RADIO_LL_LENGTH_OCTETS_RX_MAX) \
|
|
+ 14) * 8 \
|
|
)
|
|
/* Implementation default L2CAP MTU */
|
|
#ifndef RADIO_L2CAP_MTU_MAX
|
|
#define RADIO_L2CAP_MTU_MAX (RADIO_LL_LENGTH_OCTETS_RX_MAX - 4)
|
|
#endif
|
|
|
|
/* Maximise L2CAP MTU to LL data PDU size */
|
|
#if (RADIO_L2CAP_MTU_MAX < (RADIO_LL_LENGTH_OCTETS_RX_MAX - 4))
|
|
#undef RADIO_L2CAP_MTU_MAX
|
|
#define RADIO_L2CAP_MTU_MAX (RADIO_LL_LENGTH_OCTETS_RX_MAX - 4)
|
|
#endif
|
|
|
|
/* Maximum LL PDU Receive pool size. */
|
|
#ifndef RADIO_PACKET_COUNT_RX_MAX
|
|
#define RADIO_PACKET_COUNT_RX ((RADIO_L2CAP_MTU_MAX + \
|
|
RADIO_LL_LENGTH_OCTETS_RX_MAX \
|
|
+ 3) \
|
|
/ \
|
|
RADIO_LL_LENGTH_OCTETS_RX_MAX \
|
|
)
|
|
#define RADIO_PACKET_COUNT_RX_MAX (RADIO_PACKET_COUNT_RX + \
|
|
((RADIO_CONNECTION_CONTEXT_MAX - 1) * \
|
|
(RADIO_PACKET_COUNT_RX - 1)) \
|
|
)
|
|
#endif /* RADIO_PACKET_COUNT_RX_MAX */
|
|
|
|
/* Maximum LL PDU Transmit pool size and application tx count. */
|
|
#ifndef RADIO_PACKET_COUNT_TX_MAX
|
|
#define RADIO_PACKET_COUNT_APP_TX_MAX (RADIO_CONNECTION_CONTEXT_MAX)
|
|
#define RADIO_PACKET_COUNT_TX_MAX (RADIO_PACKET_COUNT_RX_MAX + \
|
|
RADIO_PACKET_COUNT_APP_TX_MAX \
|
|
)
|
|
#else
|
|
#define RADIO_PACKET_COUNT_APP_TX_MAX (RADIO_PACKET_COUNT_TX_MAX)
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
* Controller Interface Structures
|
|
****************************************************************************/
|
|
struct radio_adv_data {
|
|
uint8_t data[DOUBLE_BUFFER_SIZE][RADIO_ACPDU_SIZE_MAX];
|
|
uint8_t first;
|
|
uint8_t last;
|
|
};
|
|
|
|
struct __packed radio_le_conn_cmplt {
|
|
uint8_t status;
|
|
uint8_t role;
|
|
uint8_t peer_addr_type;
|
|
uint8_t peer_addr[BDADDR_SIZE];
|
|
uint8_t own_addr_type;
|
|
uint8_t own_addr[BDADDR_SIZE];
|
|
uint8_t peer_irk_index;
|
|
uint16_t interval;
|
|
uint16_t latency;
|
|
uint16_t timeout;
|
|
uint8_t mca;
|
|
};
|
|
|
|
struct __packed radio_le_conn_update_cmplt {
|
|
uint8_t status;
|
|
uint16_t interval;
|
|
uint16_t latency;
|
|
uint16_t timeout;
|
|
};
|
|
|
|
struct radio_pdu_node_tx {
|
|
void *next;
|
|
uint8_t pdu_data[1];
|
|
};
|
|
|
|
enum radio_pdu_node_rx_type {
|
|
NODE_RX_TYPE_NONE,
|
|
NODE_RX_TYPE_DC_PDU,
|
|
NODE_RX_TYPE_PROFILE,
|
|
NODE_RX_TYPE_REPORT,
|
|
NODE_RX_TYPE_CONNECTION,
|
|
NODE_RX_TYPE_TERMINATE,
|
|
NODE_RX_TYPE_CONN_UPDATE,
|
|
NODE_RX_TYPE_ENC_REFRESH,
|
|
NODE_RX_TYPE_APTO,
|
|
NODE_RX_TYPE_RSSI,
|
|
};
|
|
|
|
struct radio_pdu_node_rx_hdr {
|
|
enum radio_pdu_node_rx_type type;
|
|
uint16_t handle;
|
|
union {
|
|
void *next;
|
|
void *link;
|
|
uint8_t packet_release_last;
|
|
} onion;
|
|
};
|
|
|
|
struct radio_pdu_node_rx {
|
|
struct radio_pdu_node_rx_hdr hdr;
|
|
uint8_t pdu_data[1];
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* Controller Interface Functions
|
|
****************************************************************************/
|
|
uint32_t radio_init(uint8_t sca, uint8_t connection_count_max,
|
|
uint8_t rx_count_max, uint8_t tx_count_max,
|
|
uint16_t data_octets_max, uint8_t *mem_radio,
|
|
uint16_t mem_size);
|
|
void radio_ticks_active_to_start_set(uint32_t ticks_active_to_start);
|
|
struct radio_adv_data *radio_adv_data_get(void);
|
|
struct radio_adv_data *radio_scan_data_get(void);
|
|
void radio_filter_clear(void);
|
|
uint32_t radio_filter_add(uint8_t addr_type, uint8_t *addr);
|
|
void radio_irk_clear(void);
|
|
uint32_t radio_irk_add(uint8_t *irk);
|
|
uint32_t radio_adv_enable(uint16_t interval, uint8_t chl_map,
|
|
uint8_t filter_policy);
|
|
uint32_t radio_adv_disable(void);
|
|
uint32_t radio_scan_enable(uint8_t scan_type, uint8_t init_addr_type,
|
|
uint8_t *init_addr, uint16_t interval,
|
|
uint16_t window, uint8_t filter_policy);
|
|
uint32_t radio_scan_disable(void);
|
|
uint32_t radio_connect_enable(uint8_t adv_addr_type, uint8_t *adv_addr,
|
|
uint16_t interval, uint16_t latency,
|
|
uint16_t timeout);
|
|
uint32_t radio_connect_disable(void);
|
|
uint32_t radio_conn_update(uint16_t handle, uint8_t cmd, uint8_t status,
|
|
uint16_t interval, uint16_t latency,
|
|
uint16_t timeout);
|
|
uint32_t radio_chm_update(uint8_t *chm);
|
|
uint32_t radio_chm_get(uint16_t handle, uint8_t *chm);
|
|
uint32_t radio_enc_req_send(uint16_t handle, uint8_t *rand, uint8_t *ediv,
|
|
uint8_t *ltk);
|
|
uint32_t radio_start_enc_req_send(uint16_t handle, uint8_t err_code,
|
|
uint8_t const *const ltk);
|
|
uint32_t radio_feature_req_send(uint16_t handle);
|
|
uint32_t radio_version_ind_send(uint16_t handle);
|
|
uint32_t radio_terminate_ind_send(uint16_t handle, uint8_t reason);
|
|
uint32_t radio_length_req_send(uint16_t handle, uint16_t tx_octets);
|
|
uint8_t radio_rx_get(struct radio_pdu_node_rx **radio_pdu_node_rx,
|
|
uint16_t *handle);
|
|
void radio_rx_dequeue(void);
|
|
void radio_rx_mem_release(struct radio_pdu_node_rx **radio_pdu_node_rx);
|
|
uint8_t radio_rx_fc_set(uint16_t handle, uint8_t fc);
|
|
struct radio_pdu_node_tx *radio_tx_mem_acquire(void);
|
|
void radio_tx_mem_release(struct radio_pdu_node_tx *pdu_data_node_tx);
|
|
uint32_t radio_tx_mem_enqueue(uint16_t handle,
|
|
struct radio_pdu_node_tx *pdu_data_node_tx);
|
|
|
|
extern void radio_active_callback(uint8_t active);
|
|
extern void radio_event_callback(void);
|
|
|
|
#endif
|