| /* |
| * 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 "gap_internal.h" |
| #include "gatt_internal.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); |
| } |