mirror of https://github.com/ARMmbed/mbed-os.git
554 lines
15 KiB
C
554 lines
15 KiB
C
|
/*
|
||
|
* Copyright (c) 2015-2017, Arm Limited and affiliates.
|
||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions are met:
|
||
|
*
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. Neither the name of the copyright holder nor the
|
||
|
* names of its contributors may be used to endorse or promote products
|
||
|
* derived from this software without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#include "nsconfig.h"
|
||
|
|
||
|
#include "thread_meshcop_lib.h"
|
||
|
#include "common_functions.h"
|
||
|
#include <string.h>
|
||
|
#ifdef HAVE_THREAD
|
||
|
uint8_t *thread_meshcop_tlv_data_write(uint8_t *ptr, uint8_t type, uint16_t length, const uint8_t *data)
|
||
|
{
|
||
|
if (!ptr) {
|
||
|
return ptr; // Check parameters
|
||
|
}
|
||
|
*ptr++ = type;
|
||
|
if (length > 254) {
|
||
|
*ptr++ = 0Xff;
|
||
|
ptr = common_write_16_bit(length, ptr);
|
||
|
} else {
|
||
|
*ptr++ = length;
|
||
|
}
|
||
|
if (length > 0 && data) {
|
||
|
memcpy(ptr, data, length);
|
||
|
}
|
||
|
return ptr + length;
|
||
|
}
|
||
|
uint8_t *thread_meshcop_tlv_data_write_header(uint8_t *ptr, uint8_t type, uint16_t length)
|
||
|
{
|
||
|
if (!ptr) {
|
||
|
return ptr; // Check parameters
|
||
|
}
|
||
|
*ptr++ = type;
|
||
|
if (length > 254) {
|
||
|
*ptr++ = 0Xff;
|
||
|
ptr = common_write_16_bit(length, ptr);
|
||
|
} else {
|
||
|
*ptr++ = length;
|
||
|
}
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint8(uint8_t *ptr, uint8_t type, uint8_t data)
|
||
|
{
|
||
|
*ptr++ = type;
|
||
|
*ptr++ = 1;
|
||
|
*ptr++ = data;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint16(uint8_t *ptr, uint8_t type, uint16_t data)
|
||
|
{
|
||
|
*ptr++ = type;
|
||
|
*ptr++ = 2;
|
||
|
ptr = common_write_16_bit(data, ptr);
|
||
|
return ptr;
|
||
|
}
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint32(uint8_t *ptr, uint8_t type, uint32_t data)
|
||
|
{
|
||
|
*ptr++ = type;
|
||
|
*ptr++ = 4;
|
||
|
ptr = common_write_32_bit(data, ptr);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint64(uint8_t *ptr, uint8_t type, uint64_t data)
|
||
|
{
|
||
|
*ptr++ = type;
|
||
|
*ptr++ = 8;
|
||
|
ptr = common_write_64_bit(data, ptr);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
bool thread_meshcop_tlv_exist(const uint8_t *ptr, const uint16_t length, const uint8_t type)
|
||
|
{
|
||
|
const uint8_t *p;
|
||
|
if (!ptr || length < 2) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
p = ptr;
|
||
|
while (p != NULL) {
|
||
|
const uint8_t *tlv_data_ptr;
|
||
|
uint16_t tlv_data_length;
|
||
|
// check if we have enough length for normal length tlv
|
||
|
if (p + 2 > ptr + length) {
|
||
|
break; //must have at least type and short length
|
||
|
}
|
||
|
|
||
|
if (p[1] == 0xff) {
|
||
|
// Long length format
|
||
|
if (p + 4 > ptr + length) {
|
||
|
break; // check if enough length for long length
|
||
|
}
|
||
|
|
||
|
tlv_data_length = common_read_16_bit(&p[2]);
|
||
|
tlv_data_ptr = p + 4;
|
||
|
} else {
|
||
|
tlv_data_length = p[1];
|
||
|
tlv_data_ptr = p + 2;
|
||
|
}
|
||
|
|
||
|
// check if length of tlv is correct
|
||
|
if (tlv_data_ptr + tlv_data_length > ptr + length) {
|
||
|
break; //length goes past the data block
|
||
|
}
|
||
|
|
||
|
if (*p == type) {
|
||
|
// Correct TLV found
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
p = tlv_data_ptr + tlv_data_length;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
uint16_t thread_meshcop_tlv_find(const uint8_t *ptr, uint16_t length, uint8_t type, uint8_t **result_ptr)
|
||
|
{
|
||
|
const uint8_t *p;
|
||
|
if (!ptr || length < 2) {
|
||
|
return 0;
|
||
|
}
|
||
|
//tr_info("tlv_find length: %d, type: %d", length, type);
|
||
|
|
||
|
p = ptr;
|
||
|
while (p != NULL) {
|
||
|
const uint8_t *tlv_data_ptr;
|
||
|
uint16_t tlv_data_length;
|
||
|
//tr_info("tlv_find first check");
|
||
|
// check if we have enough length for normal length tlv
|
||
|
if (p + 2 > ptr + length) {
|
||
|
break; //must have at least type and short length
|
||
|
}
|
||
|
|
||
|
if (p[1] == 0xff) {
|
||
|
// Long length format
|
||
|
if (p + 4 > ptr + length) {
|
||
|
break; // check if enough length for long length
|
||
|
}
|
||
|
|
||
|
tlv_data_length = common_read_16_bit(&p[2]);
|
||
|
tlv_data_ptr = p + 4;
|
||
|
} else {
|
||
|
tlv_data_length = p[1];
|
||
|
tlv_data_ptr = p + 2;
|
||
|
}
|
||
|
//tr_info("tlv_find check: %d, type: %d", tlv_data_length, *p);
|
||
|
|
||
|
// check if length of tlv is correct
|
||
|
if (tlv_data_ptr + tlv_data_length > ptr + length) {
|
||
|
break; //length goes past the data block
|
||
|
}
|
||
|
|
||
|
if (*p == type) {
|
||
|
// Correct TLV found
|
||
|
//tr_info("tlv_find Found: %d, type: %d", tlv_data_length, *p);
|
||
|
if (result_ptr != NULL) {
|
||
|
*result_ptr = (uint8_t *)tlv_data_ptr;
|
||
|
}
|
||
|
// return the correct tlv data
|
||
|
return tlv_data_length;
|
||
|
}
|
||
|
|
||
|
p = tlv_data_ptr + tlv_data_length;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static const uint8_t *thread_meshcop_next_tlv(const uint8_t *ptr, uint16_t length)
|
||
|
{
|
||
|
// This fails if returned pointer would go past the length and it must have 2 bytes room
|
||
|
if (length < 4) {
|
||
|
return NULL;
|
||
|
}
|
||
|
if (ptr[1] == 0xff) {
|
||
|
// Long length format
|
||
|
if (length < 6) {
|
||
|
return NULL;
|
||
|
}
|
||
|
return ptr + 4 + common_read_16_bit(&ptr[2]);
|
||
|
}
|
||
|
return ptr + 2 + ptr[1];
|
||
|
}
|
||
|
int16_t thread_meshcop_tlv_length(const uint8_t *ptr, uint16_t length)
|
||
|
{
|
||
|
if (length < 2) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (ptr[1] == 0xff) {
|
||
|
// Long length format
|
||
|
if (length < 4) {
|
||
|
return -1;
|
||
|
}
|
||
|
return common_read_16_bit(&ptr[2]);
|
||
|
}
|
||
|
return ptr[1];
|
||
|
}
|
||
|
|
||
|
int16_t thread_meshcop_tlv_length_required(const uint8_t *ptr, uint16_t length)
|
||
|
{
|
||
|
if (length < 2) {
|
||
|
return -1;
|
||
|
}
|
||
|
if (ptr[1] == 0xff) {
|
||
|
// Long length format
|
||
|
if (length < 4) {
|
||
|
return -1;
|
||
|
}
|
||
|
return 4 + common_read_16_bit(&ptr[2]);
|
||
|
}
|
||
|
return 2 + ptr[1];
|
||
|
}
|
||
|
|
||
|
const uint8_t *thread_meshcop_tlv_get_next(const uint8_t *ptr, uint16_t *length)
|
||
|
{
|
||
|
if (!ptr || !length) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
const uint8_t *next_ptr = thread_meshcop_next_tlv(ptr, *length);
|
||
|
|
||
|
if (!next_ptr) {
|
||
|
// No next TLV present
|
||
|
*length = 0;
|
||
|
return NULL;
|
||
|
}
|
||
|
*length -= next_ptr - ptr;
|
||
|
return next_ptr;
|
||
|
}
|
||
|
|
||
|
bool thread_meshcop_tlv_list_present(const uint8_t *ptr, uint16_t length, const uint8_t *required_tlv_ptr, uint8_t required_tlv_len)
|
||
|
{
|
||
|
if (!ptr || !required_tlv_ptr) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for (uint8_t n = 0; n < sizeof(required_tlv_len); n++) {
|
||
|
if (0 == thread_meshcop_tlv_find(ptr, length, required_tlv_ptr[n], NULL)) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
uint16_t thread_meshcop_tlv_list_generate(const uint8_t *ptr, uint16_t length, uint8_t *result_ptr, uint16_t *result_len)
|
||
|
{
|
||
|
if (!ptr || length < 2 || !result_len) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
*result_len = 0;
|
||
|
while (ptr && length) {
|
||
|
if (result_ptr) {
|
||
|
*result_ptr++ = *ptr; // write the TLV name
|
||
|
}
|
||
|
(*result_len)++; // Count the amount of TLVs
|
||
|
ptr = thread_meshcop_tlv_get_next(ptr, &length);
|
||
|
}
|
||
|
return *result_len;
|
||
|
}
|
||
|
uint16_t thread_meshcop_tlv_list_remove(uint8_t *tlv_ptr, uint16_t tlv_len, uint8_t tlv_type)
|
||
|
{
|
||
|
uint8_t *start_ptr = tlv_ptr;
|
||
|
|
||
|
if ((!tlv_ptr) || (!tlv_len)) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Go through TLV's */
|
||
|
while ((tlv_ptr - start_ptr) < tlv_len) {
|
||
|
/* If match, remove it from list */
|
||
|
if (*tlv_ptr == tlv_type) {
|
||
|
/* If not last TLV in list, shift */
|
||
|
if (((tlv_ptr - start_ptr) + 1) < tlv_len) {
|
||
|
memmove(tlv_ptr, tlv_ptr + 1, (tlv_len - ((tlv_ptr - start_ptr) + 1)));
|
||
|
}
|
||
|
/* Update length */
|
||
|
tlv_len--;
|
||
|
/* No match, go to next... */
|
||
|
} else {
|
||
|
tlv_ptr++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return tlv_len;
|
||
|
}
|
||
|
|
||
|
bool thread_meshcop_tlv_list_type_available(const uint8_t *list_ptr, uint16_t list_len, uint8_t tlv_type)
|
||
|
{
|
||
|
for (uint16_t i = 0 ; i < list_len; i++) {
|
||
|
if (*(list_ptr + i) == tlv_type) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
uint16_t thread_meshcop_tlv_find_next(uint8_t *tlv_ba, uint16_t tlv_ba_length, uint8_t tlv_id, uint8_t **found_tlv)
|
||
|
{
|
||
|
//tr_debug("thread_meshcop_tlv_find_next TLV ID=%d ", tlv_id);
|
||
|
uint8_t *prev_tlv = *found_tlv;
|
||
|
uint16_t tlv_length = thread_meshcop_tlv_find((const uint8_t *)tlv_ba, tlv_ba_length, tlv_id, found_tlv);
|
||
|
|
||
|
if (!prev_tlv || tlv_length == 0) {
|
||
|
// first TLV requested or TLV not found
|
||
|
return tlv_length;
|
||
|
}
|
||
|
|
||
|
while (tlv_length > 0) {
|
||
|
tlv_ba_length = tlv_ba_length - tlv_length - (*found_tlv - tlv_ba); // adjust length
|
||
|
tlv_ba = *found_tlv + tlv_length; //+ 2; // skip already found TLV
|
||
|
|
||
|
if (*found_tlv == prev_tlv) {
|
||
|
// current TLV is matching previous one, return next TLV
|
||
|
return thread_meshcop_tlv_find((const uint8_t *)tlv_ba, tlv_ba_length, tlv_id, found_tlv);
|
||
|
}
|
||
|
tlv_length = thread_meshcop_tlv_find((const uint8_t *)tlv_ba, tlv_ba_length, tlv_id, found_tlv);
|
||
|
}
|
||
|
|
||
|
return tlv_length;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint8(const uint8_t *ptr, uint16_t length, uint8_t type, uint8_t *data_ptr)
|
||
|
{
|
||
|
uint8_t result_len;
|
||
|
uint8_t *result_ptr;
|
||
|
result_len = thread_meshcop_tlv_find(ptr, length, type, &result_ptr);
|
||
|
|
||
|
//tr_info("tlv_find Found: %s",trace_array(result_ptr,result_len));
|
||
|
if (result_len >= 1 && data_ptr) {
|
||
|
*data_ptr = *result_ptr;
|
||
|
}
|
||
|
return result_len;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint16(const uint8_t *ptr, uint16_t length, uint8_t type, uint16_t *data_ptr)
|
||
|
{
|
||
|
uint8_t result_len;
|
||
|
uint8_t *result_ptr;
|
||
|
|
||
|
result_len = thread_meshcop_tlv_find(ptr, length, type, &result_ptr);
|
||
|
if (result_len >= 2 && data_ptr) {
|
||
|
*data_ptr = common_read_16_bit(result_ptr);
|
||
|
}
|
||
|
return result_len;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint32(const uint8_t *ptr, uint16_t length, uint8_t type, uint32_t *data_ptr)
|
||
|
{
|
||
|
uint8_t result_len;
|
||
|
uint8_t *result_ptr;
|
||
|
|
||
|
result_len = thread_meshcop_tlv_find(ptr, length, type, &result_ptr);
|
||
|
if (result_len >= 4 && data_ptr) {
|
||
|
*data_ptr = common_read_32_bit(result_ptr);
|
||
|
}
|
||
|
return result_len;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint64(const uint8_t *ptr, uint16_t length, uint8_t type, uint64_t *data_ptr)
|
||
|
{
|
||
|
uint8_t result_len;
|
||
|
uint8_t *result_ptr;
|
||
|
|
||
|
result_len = thread_meshcop_tlv_find(ptr, length, type, &result_ptr);
|
||
|
if (result_len >= 8 && data_ptr) {
|
||
|
*data_ptr = common_read_64_bit(result_ptr);
|
||
|
}
|
||
|
return result_len;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
uint16_t thread_meshcop_tlv_find(const uint8_t *ptr, uint16_t length, uint8_t type, uint8_t **result_ptr)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
(void)type;
|
||
|
(void)result_ptr;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write(uint8_t *ptr, uint8_t type, uint16_t length, const uint8_t *data)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)type;
|
||
|
(void)length;
|
||
|
(void)data;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint8(uint8_t *ptr, uint8_t type, uint8_t data)
|
||
|
{
|
||
|
(void) ptr;
|
||
|
(void)type;
|
||
|
(void)data;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint16(uint8_t *ptr, uint8_t type, uint16_t data)
|
||
|
{
|
||
|
(void) ptr;
|
||
|
(void)type;
|
||
|
(void)data;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint32(uint8_t *ptr, uint8_t type, uint32_t data)
|
||
|
{
|
||
|
(void) ptr;
|
||
|
(void)type;
|
||
|
(void)data;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
uint8_t *thread_meshcop_tlv_data_write_uint64(uint8_t *ptr, uint8_t type, uint64_t data)
|
||
|
{
|
||
|
(void) ptr;
|
||
|
(void)type;
|
||
|
(void)data;
|
||
|
return NULL;
|
||
|
}
|
||
|
bool thread_meshcop_tlv_exist(const uint8_t *ptr, const uint16_t length, const uint8_t type)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
(void)type;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int16_t thread_meshcop_tlv_length(const uint8_t *ptr, uint16_t length)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int16_t thread_meshcop_tlv_length_required(const uint8_t *ptr, uint16_t length)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
const uint8_t *thread_meshcop_tlv_get_next(const uint8_t *ptr, uint16_t *length)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
bool thread_meshcop_tlv_list_present(const uint8_t *ptr, uint16_t length, const uint8_t *required_tlv_ptr, uint8_t required_tlv_len)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
(void)required_tlv_ptr;
|
||
|
(void)required_tlv_len;
|
||
|
return false;
|
||
|
}
|
||
|
uint16_t thread_meshcop_tlv_list_generate(const uint8_t *ptr, uint16_t length, uint8_t *result_ptr, uint16_t *result_len)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
(void)result_ptr;
|
||
|
(void)result_len;
|
||
|
return 0;
|
||
|
}
|
||
|
uint16_t thread_meshcop_tlv_list_remove(uint8_t *tlv_ptr, uint16_t tlv_len, uint8_t tlv_type)
|
||
|
{
|
||
|
(void)tlv_ptr;
|
||
|
(void)tlv_len;
|
||
|
(void)tlv_type;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool thread_meshcop_tlv_list_type_available(const uint8_t *list_ptr, uint16_t list_len, uint8_t tlv_type)
|
||
|
{
|
||
|
(void)list_ptr;
|
||
|
(void)list_len;
|
||
|
(void)tlv_type;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
uint16_t thread_meshcop_tlv_find_next(uint8_t *tlv_ba, uint16_t tlv_ba_length, uint8_t tlv_id, uint8_t **found_tlv)
|
||
|
{
|
||
|
(void)tlv_ba;
|
||
|
(void)tlv_ba_length;
|
||
|
(void)tlv_id;
|
||
|
(void)found_tlv;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint8(const uint8_t *ptr, uint16_t length, uint8_t type, uint8_t *data_ptr)
|
||
|
{
|
||
|
(void)ptr;
|
||
|
(void)length;
|
||
|
(void)type;
|
||
|
(void)data_ptr;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint16(const uint8_t *ptr, uint16_t length, uint8_t type, uint16_t *data_ptr)
|
||
|
{
|
||
|
(void) ptr;
|
||
|
(void)length;
|
||
|
(void)type;
|
||
|
(void)data_ptr;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint32(const uint8_t *ptr, uint16_t length, uint8_t type, uint32_t *data_ptr)
|
||
|
{
|
||
|
(void) ptr;
|
||
|
(void)length;
|
||
|
(void)type;
|
||
|
(void)data_ptr;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t thread_meshcop_tlv_data_get_uint64(const uint8_t *ptr, uint16_t length, uint8_t type, uint64_t *data_ptr)
|
||
|
{
|
||
|
(void) ptr;
|
||
|
(void)length;
|
||
|
(void)type;
|
||
|
(void)data_ptr;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif
|