ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ble_hci_ra8_ble.c
Go to the documentation of this file.
1
36
37#include "ble_hci_ra8_ble.h"
38
39#include <stdint.h>
40#include <string.h>
41
43#include "ra8_attributes.h"
44#include "ra8_ble.h"
45#include "ra8_err.h"
46
47/* =============================================================================
48 * Adapter-private state
49 * =============================================================================
50 */
51
60
77
94
99typedef enum : uint8_t {
102
107typedef enum : uint32_t {
110
113
114/* =============================================================================
115 * Private callbacks: ra8_ble -> NimBLE host
116 * =============================================================================
117 */
118
145RA8_INTERNAL static void
146internal_event_cb(void* ctx, uint8_t evt_code, const uint8_t* params, uint8_t params_len)
147{
148 (void)ctx;
150 return;
151 }
152 if (params == nullptr && params_len > 0U) {
153 return;
154 }
155
156 uint8_t* hci_evt = (uint8_t*)ble_transport_alloc_evt(0);
157 if (hci_evt == nullptr) {
158 /* Transient OOM -- the controller will retry. */
159 return;
160 }
161
162 hci_evt[k_ble_hci_evt_off_code] = evt_code;
163 hci_evt[k_ble_hci_evt_off_len] = params_len;
164 if (params_len > 0U) {
165 (void)memcpy(&hci_evt[k_ble_hci_evt_off_params], params, params_len);
166 }
167
168 (void)ble_transport_to_hs_evt(hci_evt);
169}
170
194RA8_INTERNAL static void
195internal_acl_cb(void* ctx, uint16_t handle, const uint8_t* payload, uint16_t len)
196{
197 (void)ctx;
199 return;
200 }
201 if (payload == nullptr && len > 0U) {
202 return;
203 }
204
205 struct os_mbuf* om = ble_transport_alloc_acl_from_ll();
206 if (om == nullptr) {
207 return;
208 }
209
210 uint8_t hdr[k_ble_hci_acl_header_len];
211 hdr[k_ble_hci_acl_off_handle_lo] = (uint8_t)(handle & k_ble_hci_mask_byte);
213 (uint8_t)((handle >> k_ble_hci_shift_byte) & k_ble_hci_mask_byte);
214 hdr[k_ble_hci_acl_off_len_lo] = (uint8_t)(len & k_ble_hci_mask_byte);
216
217 if (os_mbuf_append(om, hdr, (uint16_t)k_ble_hci_acl_header_len) != 0) {
218 (void)os_mbuf_free_chain(om);
219 return;
220 }
221 if (len > 0U && os_mbuf_append(om, payload, len) != 0) {
222 (void)os_mbuf_free_chain(om);
223 return;
224 }
225
226 (void)ble_transport_to_hs_acl(om);
227}
228
229/* =============================================================================
230 * Public lifecycle
231 * =============================================================================
232 */
233
234/* Ble hci ra ble init -- see implementation for details. */
246
247/* Ble hci ra ble deinit -- see implementation for details. */
249{
251 (void)ra8_ble_attach_event_handler(nullptr, nullptr);
252 (void)ra8_ble_attach_acl_handler(nullptr, nullptr);
253 return k_ra8_ok;
254}
255
256/* =============================================================================
257 * NimBLE LL-side transport hooks (host -> controller)
258 * =============================================================================
259 *
260 * The NimBLE transport core calls these *_impl() entry points -- the
261 * outer ``ble_transport_to_ll_cmd`` / ``ble_transport_to_ll_acl``
262 * wrappers in libs/third_party/nimble/nimble/transport/ resolve here.
263 * ``ble_transport_ll_init`` is invoked from the upstream
264 * ``ble_transport_init`` so we use it to hot-attach our callbacks
265 * even when the app skipped the explicit ``ble_hci_ra8_ble_init``.
266 */
267
287{
289 (void)ble_hci_ra8_ble_init();
290 }
291}
292
293/* Ble transport to ll cmd impl -- see implementation for details. */
295{
296 if (buf == nullptr) {
297 return -1;
298 }
299 const uint8_t* bytes = (const uint8_t*)buf;
300 const uint16_t opcode =
301 (uint16_t)((uint16_t)bytes[0] | ((uint16_t)bytes[1] << k_ble_hci_shift_byte));
302 const uint8_t params_len = bytes[2];
303 const uint8_t* params = (params_len == 0U) ? nullptr : &bytes[3];
304
305 const ra8_err_t err = ra8_ble_hci_send_command(opcode, params, params_len);
307 return (err == k_ra8_ok) ? 0 : -1;
308}
309
310/* Ble transport to ll acl impl -- see implementation for details. */
311int ble_transport_to_ll_acl_impl(struct os_mbuf* om)
312{
313 if (om == nullptr) {
314 return -1;
315 }
316 const uint16_t total = os_mbuf_len(om);
317 if (total < (uint16_t)k_ble_hci_acl_header_len) {
318 (void)os_mbuf_free_chain(om);
319 return -1;
320 }
321 if (total > (uint16_t)k_ble_hci_ra8_ble_acl_buf_max) {
322 (void)os_mbuf_free_chain(om);
323 return -1;
324 }
325
326 uint8_t flat[k_ble_hci_ra8_ble_acl_buf_max];
327 if (os_mbuf_copydata(om, 0, (int)total, flat) != 0) {
328 (void)os_mbuf_free_chain(om);
329 return -1;
330 }
331 (void)os_mbuf_free_chain(om);
332
333 const uint16_t handle =
334 (uint16_t)((uint16_t)flat[k_ble_hci_acl_off_handle_lo] |
336 const uint16_t len =
337 (uint16_t)((uint16_t)flat[k_ble_hci_acl_off_len_lo] |
339 if ((uint16_t)(len + (uint16_t)k_ble_hci_acl_header_len) > total) {
340 return -1;
341 }
342
343 const uint8_t* payload = (len == 0U) ? nullptr : &flat[k_ble_hci_acl_off_payload];
344 const ra8_err_t err = ra8_ble_hci_send_acl_data(handle, payload, len);
345 return (err == k_ra8_ok) ? 0 : -1;
346}
347
370int ble_transport_to_ll_iso_impl(struct os_mbuf* om)
371{
372 if (om != nullptr) {
373 (void)os_mbuf_free_chain(om);
374 }
375 return 0;
376}
ble_hci_ra8_ble_acl_layout_t
Layout offsets used when packing/unpacking HCI ACL data.
@ k_ble_hci_acl_off_handle_hi
Handle high byte + flags.
@ k_ble_hci_acl_off_len_lo
Length low byte.
@ k_ble_hci_acl_header_len
Total ACL-header byte count.
@ k_ble_hci_acl_off_len_hi
Length high byte.
@ k_ble_hci_acl_off_payload
Payload start offset.
@ k_ble_hci_acl_off_handle_lo
Handle low byte.
void ble_transport_ll_init(void)
LL-side transport init hook (called by ble_transport_init).
int ble_transport_to_ll_cmd_impl(void *buf)
Controller-side handler for an HCI command from the host.
static void internal_acl_cb(void *ctx, uint16_t handle, const uint8_t *payload, uint16_t len)
Inbound ACL data callback (controller -> host).
ra8_err_t ble_hci_ra8_ble_deinit(void)
Detach the adapter from the ra8_ble HCI ring.
ble_hci_ra8_ble_bits_t
Shared bit-shift constants.
@ k_ble_hci_shift_byte
Byte shift for LE16 fold/unfold.
static void internal_event_cb(void *ctx, uint8_t evt_code, const uint8_t *params, uint8_t params_len)
Inbound HCI event callback (controller -> host).
ble_hci_ra8_ble_masks_t
Shared bit-mask constants.
@ k_ble_hci_mask_byte
Low-byte mask for 16-bit splits.
int ble_transport_to_ll_iso_impl(struct os_mbuf *om)
Stub LL-side ISO transport hook.
ble_hci_ra8_ble_state_t
Adapter lifecycle states.
@ k_ble_hci_ra8_ble_state_idle
Constructed, not yet attached.
@ k_ble_hci_ra8_ble_state_running
Callbacks attached to ra8_ble.
ra8_err_t ble_hci_ra8_ble_init(void)
Attach the adapter to the ra8_ble HCI ring.
int ble_transport_to_ll_acl_impl(struct os_mbuf *om)
Controller-side handler for an ACL packet from the host.
ble_hci_ra8_ble_evt_layout_t
Layout offsets used when packing/unpacking HCI event buffers.
@ k_ble_hci_evt_header_len
Total event-header byte count.
@ k_ble_hci_evt_off_len
Offset of the parameter-length byte.
@ k_ble_hci_evt_off_params
Offset of the parameter payload.
@ k_ble_hci_evt_off_code
Offset of the event-code byte.
Apache NimBLE HCI transport adapter against the ra8_ble HCI ring.
@ k_ble_hci_ra8_ble_acl_buf_max
Maximum HCI ACL payload byte count + 4-byte header.
Weak link stubs standing in for the NimBLE transport core.
int ble_transport_to_hs_acl(struct os_mbuf *om)
Push an ACL packet up to the host stack.
int os_mbuf_free_chain(struct os_mbuf *om)
Free every mbuf in a chain.
void ble_transport_free(void *buf)
Release a buffer obtained from ble_transport_alloc_evt().
uint16_t os_mbuf_len(const struct os_mbuf *om)
Total payload length of an mbuf chain.
int os_mbuf_copydata(const struct os_mbuf *om, int off, int len, void *dst)
Copy a byte range out of an mbuf chain.
int os_mbuf_append(struct os_mbuf *om, const void *data, uint16_t len)
Append bytes to an mbuf chain (upstream os_mbuf.h).
int ble_transport_to_hs_evt(void *buf)
Push an HCI event up to the host stack.
void * ble_transport_alloc_evt(int discardable)
Allocate an HCI event buffer (upstream ble_transport.h).
struct os_mbuf * ble_transport_alloc_acl_from_ll(void)
Allocate an ACL mbuf for the LL-to-host direction.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
BLE HCI transport seam (host-side).
ra8_err_t ra8_ble_attach_event_handler(ra8_ble_event_fn_t fn, void *ctx)
Register a handler for inbound HCI events.
Definition ra8_ble.c:274
ra8_err_t ra8_ble_attach_acl_handler(ra8_ble_acl_fn_t fn, void *ctx)
Register a handler for inbound HCI ACL data.
Definition ra8_ble.c:281
ra8_err_t ra8_ble_hci_send_command(uint16_t opcode, const uint8_t *params, uint8_t params_len)
Emit an HCI command packet.
Definition ra8_ble.c:226
ra8_err_t ra8_ble_hci_send_acl_data(uint16_t handle, const uint8_t *payload, uint16_t len)
Emit an HCI ACL data packet.
Definition ra8_ble.c:246
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
static uint32_t s_state