/* * 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 #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); }