Bluetooth: nble: Add RPC Serialization IPC
Port RPC Serialization to Zephyr upstream Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Change-Id: I315d52dc6576254a6928520d1353856d41a25c69
This commit is contained in:
parent
124795afed
commit
79f47c65ba
9 changed files with 2357 additions and 1 deletions
371
drivers/nble/rpc_serialize.c
Normal file
371
drivers/nble/rpc_serialize.c
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "rpc.h"
|
||||
|
||||
#include "rpc_functions_to_ble_core.h"
|
||||
|
||||
/* Build the functions exposed */
|
||||
/* Define the functions identifiers per signature */
|
||||
#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 -> this should match the array at
|
||||
* deserialization
|
||||
*/
|
||||
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 };
|
||||
|
||||
/* Implement the functions using serialization API */
|
||||
#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) \
|
||||
void __fn(void) \
|
||||
{ \
|
||||
rpc_serialize_none(fn_index_##__fn); \
|
||||
}
|
||||
|
||||
#define FN_SIG_S(__fn, __s) \
|
||||
void __fn(__s p_s) \
|
||||
{ \
|
||||
rpc_serialize_s(fn_index_##__fn, p_s, sizeof(*p_s)); \
|
||||
}
|
||||
|
||||
#define FN_SIG_P(__fn, __type) \
|
||||
void __fn(__type p_priv) \
|
||||
{ \
|
||||
rpc_serialize_p(fn_index_##__fn, p_priv); \
|
||||
}
|
||||
|
||||
#define FN_SIG_S_B(__fn, __s, __type, __length) \
|
||||
void __fn(__s p_s, __type p_buf, __length length) \
|
||||
{ \
|
||||
rpc_serialize_s_b(fn_index_##__fn, p_s, sizeof(*p_s), \
|
||||
p_buf, length); \
|
||||
}
|
||||
|
||||
#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 p_priv) \
|
||||
{ \
|
||||
rpc_serialize_b_b_p(fn_index_##__fn, p_buf1, length1, \
|
||||
p_buf2, length2, p_priv); \
|
||||
}
|
||||
|
||||
#define FN_SIG_S_P(__fn, __s, __type) \
|
||||
void __fn(__s p_s, __type p_priv) \
|
||||
{ \
|
||||
rpc_serialize_s_p(fn_index_##__fn, p_s, sizeof(*p_s), \
|
||||
p_priv); \
|
||||
}
|
||||
|
||||
#define FN_SIG_S_B_P(__fn, __s, __type, __length, __type_ptr) \
|
||||
void __fn(__s p_s, __type p_buf, __length length, \
|
||||
__type_ptr p_priv) \
|
||||
{ \
|
||||
rpc_serialize_s_b_p(fn_index_##__fn, p_s, sizeof(*p_s), \
|
||||
p_buf, length, p_priv); \
|
||||
}
|
||||
|
||||
#define FN_SIG_S_B_B_P(__fn, __s, __type1, __length1, __type2, \
|
||||
__length2, __type3) \
|
||||
void __fn(__s p_s, __type1 p_buf1, __length1 length1, \
|
||||
__type2 p_buf2, __length2 length2, __type3 p_priv) \
|
||||
{ \
|
||||
rpc_serialize_s_b_b_p(fn_index_##__fn, p_s, \
|
||||
sizeof(*p_s), p_buf1, length1, \
|
||||
p_buf2, length2, p_priv); \
|
||||
}
|
||||
|
||||
|
||||
/* Build the functions */
|
||||
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
|
||||
|
||||
#define SIG_TYPE_SIZE 1
|
||||
#define FN_INDEX_SIZE 1
|
||||
#define POINTER_SIZE 4
|
||||
|
||||
static void _send(uint8_t *buf, uint16_t length)
|
||||
{
|
||||
rpc_transmit_cb(buf, length);
|
||||
}
|
||||
|
||||
static uint16_t encoded_structlen(uint8_t structlen)
|
||||
{
|
||||
return 1 + structlen;
|
||||
}
|
||||
|
||||
static uint8_t *serialize_struct(uint8_t *p, const uint8_t *struct_data,
|
||||
uint8_t struct_length)
|
||||
{
|
||||
*p++ = struct_length;
|
||||
memcpy(p, struct_data, struct_length);
|
||||
p += struct_length;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static uint16_t encoded_buflen(const uint8_t *buf, uint16_t buflen)
|
||||
{
|
||||
if (!buf) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (buflen < (1 << 7)) {
|
||||
return 1 + buflen;
|
||||
} else {
|
||||
return 2 + buflen;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t *serialize_buf(uint8_t *p, const uint8_t *buf, uint16_t buflen)
|
||||
{
|
||||
uint16_t varint;
|
||||
|
||||
if (!buf) {
|
||||
buflen = 0;
|
||||
}
|
||||
|
||||
varint = buflen;
|
||||
|
||||
*p = varint & 0x7F;
|
||||
if (varint >= (1 << 7)) {
|
||||
*p |= 0x80;
|
||||
p++;
|
||||
*p = varint >> 7;
|
||||
}
|
||||
|
||||
p++;
|
||||
memcpy(p, buf, buflen);
|
||||
p += buflen;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static uint8_t *serialize_p(uint8_t *p, uintptr_t priv)
|
||||
{
|
||||
*p++ = priv;
|
||||
*p++ = (priv >> 8);
|
||||
*p++ = (priv >> 16);
|
||||
*p++ = (priv >> 24);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void rpc_serialize_none(uint8_t fn_index)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
|
||||
length = SIG_TYPE_SIZE + FN_INDEX_SIZE;
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_NONE;
|
||||
*p = fn_index;
|
||||
|
||||
_send(buf, length);
|
||||
}
|
||||
|
||||
void rpc_serialize_s(uint8_t fn_index, const void *struct_data,
|
||||
uint8_t struct_length)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
|
||||
length = SIG_TYPE_SIZE + FN_INDEX_SIZE +
|
||||
encoded_structlen(struct_length);
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_S;
|
||||
*p++ = fn_index;
|
||||
p = serialize_struct(p, struct_data, struct_length);
|
||||
|
||||
_send(buf, length);
|
||||
}
|
||||
|
||||
|
||||
void rpc_serialize_p(uint8_t fn_index, void *p_priv)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
uintptr_t priv = (uintptr_t) p_priv;
|
||||
|
||||
length = SIG_TYPE_SIZE + FN_INDEX_SIZE + POINTER_SIZE;
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_P;
|
||||
*p++ = fn_index;
|
||||
p = serialize_p(p, priv);
|
||||
|
||||
_send(buf, length);
|
||||
}
|
||||
|
||||
void rpc_serialize_s_b(uint8_t fn_index, const void *struct_data,
|
||||
uint8_t struct_length, const void *vbuf,
|
||||
uint16_t vbuf_length)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
|
||||
length = SIG_TYPE_SIZE + FN_INDEX_SIZE +
|
||||
encoded_structlen(struct_length) +
|
||||
encoded_buflen(vbuf, vbuf_length);
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_S_B;
|
||||
*p++ = fn_index;
|
||||
p = serialize_struct(p, struct_data, struct_length);
|
||||
p = serialize_buf(p, vbuf, vbuf_length);
|
||||
|
||||
_send(buf, length);
|
||||
}
|
||||
|
||||
void rpc_serialize_b_b_p(uint8_t fn_index, const void *vbuf1,
|
||||
uint16_t vbuf1_length, const void *vbuf2,
|
||||
uint16_t vbuf2_length, void *p_priv)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
uintptr_t priv = (uintptr_t) p_priv;
|
||||
|
||||
length = SIG_TYPE_SIZE + FN_INDEX_SIZE +
|
||||
encoded_buflen(vbuf1, vbuf1_length) +
|
||||
encoded_buflen(vbuf2, vbuf2_length) + POINTER_SIZE;
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_B_B_P;
|
||||
*p++ = fn_index;
|
||||
p = serialize_buf(p, vbuf1, vbuf1_length);
|
||||
p = serialize_buf(p, vbuf2, vbuf2_length);
|
||||
p = serialize_p(p, priv);
|
||||
|
||||
_send(buf, length);
|
||||
}
|
||||
|
||||
void rpc_serialize_s_p(uint8_t fn_index, const void *struct_data,
|
||||
uint8_t struct_length, void *p_priv)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
uintptr_t priv = (uintptr_t) p_priv;
|
||||
|
||||
length = SIG_TYPE_SIZE +
|
||||
FN_INDEX_SIZE + encoded_structlen(struct_length) +
|
||||
POINTER_SIZE;
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_S_P;
|
||||
*p++ = fn_index;
|
||||
p = serialize_struct(p, struct_data, struct_length);
|
||||
p = serialize_p(p, priv);
|
||||
|
||||
_send(buf, length);
|
||||
}
|
||||
|
||||
void rpc_serialize_s_b_p(uint8_t fn_index, const void *struct_data,
|
||||
uint8_t struct_length, const void *vbuf,
|
||||
uint16_t vbuf_length, void *p_priv)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
uintptr_t priv = (uintptr_t) p_priv;
|
||||
|
||||
length = SIG_TYPE_SIZE + FN_INDEX_SIZE +
|
||||
encoded_structlen(struct_length) +
|
||||
encoded_buflen(vbuf, vbuf_length) + POINTER_SIZE;
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_S_B_P;
|
||||
*p++ = fn_index;
|
||||
p = serialize_struct(p, struct_data, struct_length);
|
||||
p = serialize_buf(p, vbuf, vbuf_length);
|
||||
p = serialize_p(p, priv);
|
||||
|
||||
_send(buf, length);
|
||||
}
|
||||
|
||||
void rpc_serialize_s_b_b_p(uint8_t fn_index, const void *struct_data,
|
||||
uint8_t struct_length, const void *vbuf1,
|
||||
uint16_t vbuf1_length, const void *vbuf2,
|
||||
uint16_t vbuf2_length, void *p_priv)
|
||||
{
|
||||
uint16_t length;
|
||||
uint8_t *buf;
|
||||
uint8_t *p;
|
||||
uintptr_t priv = (uintptr_t) p_priv;
|
||||
|
||||
length = SIG_TYPE_SIZE + FN_INDEX_SIZE +
|
||||
encoded_structlen(struct_length) +
|
||||
encoded_buflen(vbuf1, vbuf1_length) +
|
||||
encoded_buflen(vbuf2, vbuf2_length) + POINTER_SIZE;
|
||||
|
||||
p = buf = rpc_alloc_cb(length);
|
||||
|
||||
*p++ = SIG_TYPE_S_B_B_P;
|
||||
*p++ = fn_index;
|
||||
p = serialize_struct(p, struct_data, struct_length);
|
||||
p = serialize_buf(p, vbuf1, vbuf1_length);
|
||||
p = serialize_buf(p, vbuf2, vbuf2_length);
|
||||
p = serialize_p(p, priv);
|
||||
|
||||
_send(buf, length);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue