The latest NBLE firmware includes a new version exchange mechanism that is independent from the RPC function definition. It also allows using firmwares that are automatically generated by the official builders without needing a local build. The upgrade of the softdevice fixes several issues in PTS tests. The major change in term of API introduced by this upgrade is that upon write requests, the offset and data of the write request must be sent back to the softdevice. Change-Id: Ie574047a09a4e6fdcbf775bc98d8a61f981cee0c Signed-off-by: Louis Caron <louis.caron@intel.com>
649 lines
17 KiB
C
649 lines
17 KiB
C
/*
|
|
* Copyright (c) 2016 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 <stdlib.h>
|
|
#include <string.h>
|
|
#include <atomic.h>
|
|
|
|
#include <bluetooth/gatt.h>
|
|
/* for bt_security_t */
|
|
#include <bluetooth/conn.h>
|
|
#include <bluetooth/log.h>
|
|
|
|
#ifdef CONFIG_PRINTK
|
|
#include <misc/printk.h>
|
|
#define PRINTK(...) printk(__VA_ARGS__)
|
|
#else
|
|
#define PRINTK(...)
|
|
#endif /* CONFIG_PRINTK */
|
|
|
|
#include "rpc.h"
|
|
#include "gap_internal.h"
|
|
#include "gatt_internal.h"
|
|
|
|
#include "rpc_functions_to_quark.h"
|
|
|
|
#if !defined(CONFIG_NBLE_DEBUG_RPC)
|
|
#undef BT_DBG
|
|
#define BT_DBG(fmt, ...)
|
|
#endif
|
|
|
|
/* Build the list of prototypes and check that list are made only of matching
|
|
* signatures
|
|
*/
|
|
#define FN_SIG_NONE(__fn) void __fn(void);
|
|
LIST_FN_SIG_NONE
|
|
#undef FN_SIG_NONE
|
|
|
|
#define FN_SIG_S(__fn, __s) void __fn(__s p_s);
|
|
LIST_FN_SIG_S
|
|
#undef FN_SIG_S
|
|
|
|
#define FN_SIG_P(__fn, __type) void __fn(__type priv);
|
|
LIST_FN_SIG_P
|
|
#undef FN_SIG_P
|
|
|
|
#define FN_SIG_S_B(__fn, __s, __type, __length) \
|
|
void __fn(__s p_s, __type buf, __length length);
|
|
LIST_FN_SIG_S_B
|
|
#undef FN_SIG_S_B
|
|
|
|
#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, \
|
|
__type3) \
|
|
void __fn(__type1 p_buf1, __length1 length1, __type2 p_buf2, \
|
|
__length2 length2, __type3 priv);
|
|
LIST_FN_SIG_B_B_P
|
|
#undef FN_SIG_B_B_P
|
|
|
|
#define FN_SIG_S_P(__fn, __s, __type) void __fn(__s p_s, __type priv);
|
|
LIST_FN_SIG_S_P
|
|
#undef FN_SIG_S_P
|
|
|
|
#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \
|
|
void __fn(__s p_s, __type buf, __length length, __type_ptr priv);
|
|
LIST_FN_SIG_S_B_P
|
|
#undef FN_SIG_S_B_P
|
|
|
|
#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, \
|
|
__length2, __type_ptr) \
|
|
void __fn(__s p_s, __type1 p_buf1, __length1 length1, \
|
|
__type2 p_buf2, __length2 length2, __type_ptr priv);
|
|
LIST_FN_SIG_S_B_B_P
|
|
#undef FN_SIG_S_B_B_P
|
|
|
|
/* 1 - define the size check arrays */
|
|
#define FN_SIG_NONE(__fn)
|
|
|
|
#define FN_SIG_S(__fn, __s) sizeof(*((__s)0)),
|
|
|
|
#define FN_SIG_P(__fn, __type)
|
|
|
|
#define FN_SIG_S_B(__fn, __s, __type, __length) sizeof(*((__s)0)),
|
|
|
|
#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, \
|
|
__type3) sizeof(*((__s)0)),
|
|
|
|
#define FN_SIG_S_P(__fn, __s, __type) sizeof(*((__s)0)),
|
|
|
|
#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \
|
|
sizeof(*((__s)0)),
|
|
|
|
#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, \
|
|
__length2, __type3) sizeof(*((__s)0)),
|
|
|
|
static uint8_t m_size_s[] = { LIST_FN_SIG_S };
|
|
static uint8_t m_size_s_b[] = { LIST_FN_SIG_S_B };
|
|
static uint8_t m_size_s_p[] = { LIST_FN_SIG_S_P };
|
|
static uint8_t m_size_s_b_p[] = { LIST_FN_SIG_S_B_P };
|
|
static uint8_t m_size_s_b_b_p[] = { LIST_FN_SIG_S_B_B_P };
|
|
|
|
#undef FN_SIG_NONE
|
|
#undef FN_SIG_S
|
|
#undef FN_SIG_P
|
|
#undef FN_SIG_S_B
|
|
#undef FN_SIG_B_B_P
|
|
#undef FN_SIG_S_P
|
|
#undef FN_SIG_S_B_P
|
|
#undef FN_SIG_S_B_B_P
|
|
|
|
/* 2- build the enumerations list */
|
|
#define FN_SIG_NONE(__fn) fn_index_##__fn,
|
|
#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B(__fn, __s, __type, __length) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, \
|
|
__type3) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \
|
|
FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, \
|
|
__length2, __type3) FN_SIG_NONE(__fn)
|
|
|
|
/* Build the list of function indexes in the deserialization array */
|
|
enum { LIST_FN_SIG_NONE fn_none_index_max };
|
|
enum { LIST_FN_SIG_S fn_s_index_max };
|
|
enum { LIST_FN_SIG_P fn_p_index_max };
|
|
enum { LIST_FN_SIG_S_B fn_s_b_index_max };
|
|
enum { LIST_FN_SIG_B_B_P fn_b_b_p_index_max };
|
|
enum { LIST_FN_SIG_S_P fn_s_p_index_max };
|
|
enum { LIST_FN_SIG_S_B_P fn_s_b_p_index_max };
|
|
enum { LIST_FN_SIG_S_B_B_P fn_s_b_b_p_index_max };
|
|
|
|
#undef FN_SIG_NONE
|
|
#undef FN_SIG_S
|
|
#undef FN_SIG_P
|
|
#undef FN_SIG_S_B
|
|
#undef FN_SIG_B_B_P
|
|
#undef FN_SIG_S_P
|
|
#undef FN_SIG_S_B_P
|
|
#undef FN_SIG_S_B_B_P
|
|
|
|
/* 3- build the array */
|
|
#define FN_SIG_NONE(__fn) [fn_index_##__fn] = \
|
|
(void *)__fn,
|
|
#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B(__fn, __s, __type, __length) \
|
|
FN_SIG_NONE(__fn)
|
|
#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, \
|
|
__type3) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \
|
|
FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, \
|
|
__length2, __type3) FN_SIG_NONE(__fn)
|
|
|
|
static void (*m_fct_none[])(void) = { LIST_FN_SIG_NONE };
|
|
static void (*m_fct_s[])(void *structure) = { LIST_FN_SIG_S };
|
|
static void (*m_fct_p[])(void *pointer) = { LIST_FN_SIG_P };
|
|
static void (*m_fct_s_b[])(void *structure, void *buffer,
|
|
uint8_t length) = { LIST_FN_SIG_S_B };
|
|
static void (*m_fct_b_b_p[])(void *buffer1, uint8_t length1,
|
|
void *buffer2, uint8_t length2,
|
|
void *pointer) = { LIST_FN_SIG_B_B_P };
|
|
static void (*m_fct_s_p[])(void *structure,
|
|
void *pointer) = { LIST_FN_SIG_S_P };
|
|
static void (*m_fct_s_b_p[])(void *structure, void *buffer, uint8_t length,
|
|
void *pointer) = { LIST_FN_SIG_S_B_P };
|
|
static void (*m_fct_s_b_b_p[])(void *structure, void *buffer1, uint8_t length1,
|
|
void *buffer2, uint8_t length2,
|
|
void *pointer) = { LIST_FN_SIG_S_B_B_P };
|
|
|
|
/* Build debug table to help development with this "robust" macro stuff */
|
|
|
|
#if defined(CONFIG_NBLE_DEBUG_RPC)
|
|
|
|
#undef FN_SIG_NONE
|
|
#undef FN_SIG_S
|
|
#undef FN_SIG_P
|
|
#undef FN_SIG_S_B
|
|
#undef FN_SIG_B_B_P
|
|
#undef FN_SIG_S_P
|
|
#undef FN_SIG_S_B_P
|
|
#undef FN_SIG_S_B_B_P
|
|
|
|
#define FN_SIG_NONE(__fn) #__fn,
|
|
#define FN_SIG_S(__fn, __s) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_P(__fn, __type) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B(__fn, __s, __type, __length) \
|
|
FN_SIG_NONE(__fn)
|
|
#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, \
|
|
__type3) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_P(__fn, __s, __type) FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \
|
|
FN_SIG_NONE(__fn)
|
|
#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, \
|
|
__length2, __type3) FN_SIG_NONE(__fn)
|
|
|
|
static char *debug_func_none[] = { LIST_FN_SIG_NONE };
|
|
static char *debug_func_s[] = { LIST_FN_SIG_S };
|
|
static char *debug_func_p[] = { LIST_FN_SIG_P };
|
|
static char *debug_func_s_b[] = { LIST_FN_SIG_S_B };
|
|
static char *debug_func_b_b_p[] = { LIST_FN_SIG_B_B_P };
|
|
static char *debug_func_s_p[] = { LIST_FN_SIG_S_P };
|
|
static char *debug_func_s_b_p[] = { LIST_FN_SIG_S_B_P };
|
|
static char *debug_func_s_b_b_p[] = { LIST_FN_SIG_S_B_B_P};
|
|
|
|
#endif
|
|
|
|
#undef FN_SIG_NONE
|
|
#undef FN_SIG_S
|
|
#undef FN_SIG_P
|
|
#undef FN_SIG_S_B
|
|
#undef FN_SIG_B_B_P
|
|
#undef FN_SIG_S_P
|
|
#undef FN_SIG_S_B_P
|
|
#undef FN_SIG_S_B_B_P
|
|
|
|
#define DJB2_HASH(__h, __v) ((((__h) << 5) + (__h)) + (__v))
|
|
|
|
#define FN_SIG_NONE(__fn) \
|
|
hash = DJB2_HASH(hash, 1);
|
|
|
|
#define FN_SIG_S(__fn, __s) \
|
|
do { \
|
|
hash = DJB2_HASH(hash, 2); \
|
|
hash = DJB2_HASH(hash, sizeof(*((__s)0))); \
|
|
} while (0);
|
|
|
|
#define FN_SIG_P(__fn, __type) \
|
|
hash = DJB2_HASH(hash, 3);
|
|
|
|
#define FN_SIG_S_B(__fn, __s, __type, __length) \
|
|
do { \
|
|
hash = DJB2_HASH(hash, 4); \
|
|
hash = DJB2_HASH(hash, sizeof(*((__s)0))); \
|
|
} while (0);
|
|
|
|
#define FN_SIG_B_B_P(__fn, __type1, __length1, __type2, __length2, \
|
|
__type3) \
|
|
do { \
|
|
hash = DJB2_HASH(hash, 5); \
|
|
hash = DJB2_HASH(hash, sizeof(*((__s)0))); \
|
|
} while (0);
|
|
|
|
#define FN_SIG_S_P(__fn, __s, __type) \
|
|
do { \
|
|
hash = DJB2_HASH(hash, 6); \
|
|
hash = DJB2_HASH(hash, sizeof(*((__s)0))); \
|
|
} while (0);
|
|
|
|
#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \
|
|
do { \
|
|
hash = DJB2_HASH(hash, 7); \
|
|
hash = DJB2_HASH(hash, sizeof(*((__s)0))); \
|
|
} while (0);
|
|
|
|
#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, \
|
|
__length2, __type3) \
|
|
do { \
|
|
hash = DJB2_HASH(hash, 8); \
|
|
hash = DJB2_HASH(hash, sizeof(*((__s)0))); \
|
|
} while (0);
|
|
|
|
uint32_t rpc_deserialize_hash(void)
|
|
{
|
|
uint32_t hash = 5381;
|
|
|
|
LIST_FN_SIG_NONE;
|
|
LIST_FN_SIG_S;
|
|
LIST_FN_SIG_P;
|
|
LIST_FN_SIG_S_B;
|
|
LIST_FN_SIG_B_B_P;
|
|
LIST_FN_SIG_S_P;
|
|
LIST_FN_SIG_S_B_P;
|
|
LIST_FN_SIG_S_B_B_P;
|
|
|
|
return hash;
|
|
}
|
|
|
|
static void panic(int err)
|
|
{
|
|
PRINTK("panic: errcode %d", err);
|
|
|
|
while (true) {
|
|
}
|
|
}
|
|
|
|
static void deserialize_struct(struct net_buf *buf, const uint8_t **struct_ptr,
|
|
uint8_t *struct_length)
|
|
{
|
|
*struct_length = net_buf_pull_u8(buf);
|
|
*struct_ptr = buf->data;
|
|
net_buf_pull(buf, *struct_length);
|
|
}
|
|
|
|
static void deserialize_buf(struct net_buf *buf, const uint8_t **buf_ptr,
|
|
uint16_t *buf_len)
|
|
{
|
|
uint8_t b;
|
|
|
|
/* Get the current byte */
|
|
b = net_buf_pull_u8(buf);
|
|
*buf_len = b & 0x7F;
|
|
if (b & 0x80) {
|
|
/* Get the current byte */
|
|
b = net_buf_pull_u8(buf);
|
|
*buf_len += (uint16_t)b << 7;
|
|
}
|
|
|
|
/* Return the values */
|
|
*buf_ptr = buf->data;
|
|
|
|
net_buf_pull(buf, *buf_len);
|
|
}
|
|
|
|
static void deserialize_ptr(struct net_buf *buf, uintptr_t *priv)
|
|
{
|
|
memcpy(priv, buf->data, sizeof(*priv));
|
|
net_buf_pull(buf, sizeof(*priv));
|
|
}
|
|
|
|
static void deserialize_none(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
(void)buf;
|
|
|
|
if (buf->len != 0) {
|
|
panic(-1);
|
|
}
|
|
|
|
m_fct_none[fn_index]();
|
|
}
|
|
|
|
static void deserialize_s(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
const uint8_t *struct_ptr;
|
|
uint8_t struct_length;
|
|
|
|
deserialize_struct(buf, &struct_ptr, &struct_length);
|
|
|
|
if (struct_length != m_size_s[fn_index]) {
|
|
panic(-1);
|
|
} else {
|
|
/* Always align structures on word boundary */
|
|
uintptr_t struct_data[(struct_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
|
|
memcpy(struct_data, struct_ptr, struct_length);
|
|
|
|
m_fct_s[fn_index](struct_data);
|
|
}
|
|
}
|
|
|
|
static void deserialize_p(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
uintptr_t priv;
|
|
|
|
if (buf->len != sizeof(priv)) {
|
|
panic(-1);
|
|
}
|
|
|
|
deserialize_ptr(buf, &priv);
|
|
|
|
m_fct_p[fn_index]((void *)priv);
|
|
}
|
|
|
|
static void deserialize_s_b(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
const uint8_t *p_struct_data;
|
|
uint8_t struct_length;
|
|
const uint8_t *p_vbuf;
|
|
uint16_t vbuf_length;
|
|
|
|
deserialize_struct(buf, &p_struct_data, &struct_length);
|
|
deserialize_buf(buf, &p_vbuf, &vbuf_length);
|
|
|
|
if (struct_length != m_size_s_b[fn_index]) {
|
|
panic(-1);
|
|
} else {
|
|
/* Always align structures on word boundary */
|
|
uintptr_t struct_data[(struct_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
uintptr_t vbuf[(vbuf_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
void *buf = NULL;
|
|
|
|
memcpy(struct_data, p_struct_data, struct_length);
|
|
|
|
if (vbuf_length) {
|
|
memcpy(vbuf, p_vbuf, vbuf_length);
|
|
buf = vbuf;
|
|
}
|
|
|
|
m_fct_s_b[fn_index](struct_data, buf, vbuf_length);
|
|
}
|
|
}
|
|
|
|
static void deserialize_b_b_p(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
const uint8_t *p_vbuf1;
|
|
uint16_t vbuf1_length;
|
|
const uint8_t *p_vbuf2;
|
|
uint16_t vbuf2_length;
|
|
uintptr_t priv;
|
|
|
|
deserialize_buf(buf, &p_vbuf1, &vbuf1_length);
|
|
deserialize_buf(buf, &p_vbuf2, &vbuf2_length);
|
|
deserialize_ptr(buf, &priv);
|
|
|
|
{
|
|
/* Always align structures on word boundary */
|
|
uintptr_t vbuf1[(vbuf1_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
uintptr_t vbuf2[(vbuf2_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
void *buf1 = NULL;
|
|
void *buf2 = NULL;
|
|
|
|
if (vbuf1_length) {
|
|
memcpy(vbuf1, p_vbuf1, vbuf1_length);
|
|
buf1 = vbuf1;
|
|
}
|
|
|
|
if (vbuf2_length) {
|
|
memcpy(vbuf2, p_vbuf2, vbuf2_length);
|
|
buf2 = vbuf2;
|
|
}
|
|
|
|
m_fct_b_b_p[fn_index](buf1, vbuf1_length, buf2, vbuf2_length,
|
|
(void *)priv);
|
|
}
|
|
}
|
|
|
|
static void deserialize_s_p(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
const uint8_t *p_struct_data;
|
|
uint8_t struct_length;
|
|
uintptr_t priv;
|
|
|
|
deserialize_struct(buf, &p_struct_data, &struct_length);
|
|
deserialize_ptr(buf, &priv);
|
|
|
|
if (struct_length != m_size_s_p[fn_index]) {
|
|
panic(-1);
|
|
} else {
|
|
/* Always align structures on word boundary */
|
|
uintptr_t struct_data[(struct_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
|
|
memcpy(struct_data, p_struct_data, struct_length);
|
|
|
|
m_fct_s_p[fn_index](struct_data, (void *)priv);
|
|
}
|
|
}
|
|
|
|
static void deserialize_s_b_p(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
const uint8_t *p_struct_data;
|
|
uint8_t struct_length;
|
|
const uint8_t *p_vbuf;
|
|
uint16_t vbuf_length;
|
|
uintptr_t priv;
|
|
|
|
deserialize_struct(buf, &p_struct_data, &struct_length);
|
|
deserialize_buf(buf, &p_vbuf, &vbuf_length);
|
|
deserialize_ptr(buf, &priv);
|
|
|
|
if (struct_length != m_size_s_b_p[fn_index]) {
|
|
panic(-1);
|
|
} else {
|
|
/* Always align structures on word boundary */
|
|
uintptr_t struct_data[(struct_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
uintptr_t vbuf[(vbuf_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
void *buf = NULL;
|
|
|
|
memcpy(struct_data, p_struct_data, struct_length);
|
|
|
|
if (vbuf_length) {
|
|
memcpy(vbuf, p_vbuf, vbuf_length);
|
|
buf = vbuf;
|
|
}
|
|
|
|
m_fct_s_b_p[fn_index](struct_data, buf, vbuf_length,
|
|
(void *)priv);
|
|
}
|
|
}
|
|
|
|
static void deserialize_s_b_b_p(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
const uint8_t *p_struct_data;
|
|
uint8_t struct_length;
|
|
const uint8_t *p_vbuf1;
|
|
uint16_t vbuf1_length;
|
|
const uint8_t *p_vbuf2;
|
|
uint16_t vbuf2_length;
|
|
uintptr_t priv;
|
|
|
|
deserialize_struct(buf, &p_struct_data, &struct_length);
|
|
deserialize_buf(buf, &p_vbuf1, &vbuf1_length);
|
|
deserialize_buf(buf, &p_vbuf2, &vbuf2_length);
|
|
deserialize_ptr(buf, &priv);
|
|
|
|
if (struct_length != m_size_s_b_b_p[fn_index]) {
|
|
panic(-1);
|
|
} else {
|
|
/* Always align structures on word boundary */
|
|
uintptr_t struct_data[(struct_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
uintptr_t vbuf1[(vbuf1_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
uintptr_t vbuf2[(vbuf2_length +
|
|
(sizeof(uintptr_t) - 1))/(sizeof(uintptr_t))];
|
|
void *buf1 = NULL;
|
|
void *buf2 = NULL;
|
|
|
|
memcpy(struct_data, p_struct_data, struct_length);
|
|
|
|
if (vbuf1_length) {
|
|
memcpy(vbuf1, p_vbuf1, vbuf1_length);
|
|
buf1 = vbuf1;
|
|
}
|
|
|
|
if (vbuf2_length) {
|
|
memcpy(vbuf2, p_vbuf2, vbuf2_length);
|
|
buf2 = vbuf2;
|
|
}
|
|
|
|
m_fct_s_b_b_p[fn_index](struct_data, buf1, vbuf1_length, buf2,
|
|
vbuf2_length, (void *)priv);
|
|
}
|
|
}
|
|
|
|
static void deserialize_control(uint8_t fn_index, struct net_buf *buf)
|
|
{
|
|
const uint8_t *p_struct_data;
|
|
uint8_t struct_length;
|
|
struct {
|
|
uint32_t version;
|
|
uint32_t ser_hash;
|
|
uint32_t des_hash;
|
|
} struct_data;
|
|
|
|
switch (fn_index) {
|
|
case 0:
|
|
deserialize_struct(buf, &p_struct_data, &struct_length);
|
|
|
|
if (struct_length != sizeof(struct_data))
|
|
panic(-1);
|
|
memcpy(&struct_data, p_struct_data, struct_length);
|
|
if (struct_data.ser_hash != rpc_deserialize_hash() ||
|
|
struct_data.des_hash != rpc_serialize_hash()) {
|
|
rpc_init_cb(struct_data.version, false);
|
|
} else {
|
|
rpc_init_cb(struct_data.version, true);
|
|
}
|
|
break;
|
|
break;
|
|
panic(-1);
|
|
}
|
|
}
|
|
|
|
void rpc_deserialize(struct net_buf *buf)
|
|
{
|
|
|
|
uint8_t fn_index;
|
|
uint8_t sig_type;
|
|
|
|
sig_type = buf->data[0];
|
|
fn_index = buf->data[1];
|
|
|
|
net_buf_pull(buf, 2);
|
|
|
|
switch (sig_type) {
|
|
case SIG_TYPE_NONE:
|
|
if (fn_index < ARRAY_SIZE(m_fct_none)) {
|
|
BT_DBG("%s", debug_func_none[fn_index]);
|
|
deserialize_none(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_S:
|
|
if (fn_index < ARRAY_SIZE(m_fct_s)) {
|
|
BT_DBG("%s", debug_func_s[fn_index]);
|
|
deserialize_s(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_P:
|
|
if (fn_index < ARRAY_SIZE(m_fct_p)) {
|
|
BT_DBG("%s", debug_func_p[fn_index]);
|
|
deserialize_p(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_S_B:
|
|
if (fn_index < ARRAY_SIZE(m_fct_s_b)) {
|
|
BT_DBG("%s", debug_func_s_b[fn_index]);
|
|
deserialize_s_b(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_B_B_P:
|
|
if (fn_index < ARRAY_SIZE(m_fct_b_b_p)) {
|
|
BT_DBG("%s", debug_func_b_b_p[fn_index]);
|
|
deserialize_b_b_p(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_S_P:
|
|
if (fn_index < ARRAY_SIZE(m_fct_s_p)) {
|
|
BT_DBG("%s", debug_func_s_p[fn_index]);
|
|
deserialize_s_p(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_S_B_P:
|
|
if (fn_index < ARRAY_SIZE(m_fct_s_b_p)) {
|
|
BT_DBG("%s", debug_func_s_b_p[fn_index]);
|
|
deserialize_s_b_p(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_S_B_B_P:
|
|
if (fn_index < ARRAY_SIZE(m_fct_s_b_b_p)) {
|
|
BT_DBG("%s", debug_func_s_b_b_p[fn_index]);
|
|
deserialize_s_b_b_p(fn_index, buf);
|
|
}
|
|
break;
|
|
case SIG_TYPE_CONTROL:
|
|
deserialize_control(fn_index, buf);
|
|
break;
|
|
default:
|
|
panic(-1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
__weak
|
|
void rpc_init_cb(uint32_t version, bool compatible)
|
|
{
|
|
}
|