save failed integration state
This commit is contained in:
@ -0,0 +1,15 @@
|
||||
#ifndef PARAM_PARAM_CLIENT_H
|
||||
#define PARAM_PARAM_CLIENT_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
Legacy/deprecated include of header files for libparam client.
|
||||
*/
|
||||
|
||||
#include <param/param_serializer.h>
|
||||
#include <param/param_string.h>
|
||||
#include <param/param_lock.h>
|
||||
#include <param/rparam_client.h>
|
||||
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
* GomSpace Parameter System.
|
||||
*/
|
||||
#ifndef PARAM_PARAM_LOCK_H_
|
||||
#define PARAM_PARAM_LOCK_H_
|
||||
|
||||
#include <gs/param/table.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void param_lock(param_index_t * mem)
|
||||
{
|
||||
gs_param_table_lock((gs_param_table_instance_t *) mem);
|
||||
}
|
||||
|
||||
static inline void param_unlock(param_index_t * mem)
|
||||
{
|
||||
gs_param_table_unlock((gs_param_table_instance_t *) mem);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,55 @@
|
||||
#ifndef PARAM_PARAM_SERIALIZER_H
|
||||
#define PARAM_PARAM_SERIALIZER_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
* GomSpace Parameter System
|
||||
*/
|
||||
|
||||
#include <param/param_types.h>
|
||||
#include <gs/param/serialize.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef gs_param_serialize_flags_t param_serializer_flags;
|
||||
|
||||
static inline int param_betoh(param_type_t type, void * item)
|
||||
{
|
||||
return gs_param_betoh(type, item);
|
||||
}
|
||||
|
||||
static inline int param_htobe(param_type_t type, void * item)
|
||||
{
|
||||
return gs_param_htobe(type, item);
|
||||
}
|
||||
|
||||
static inline int param_serialize_full_table(param_index_t * mem, unsigned int *start, uint8_t * buf, unsigned int maxbuflen, param_serializer_flags flags)
|
||||
{
|
||||
unsigned int buf_pos = 0;
|
||||
gs_error_t error = gs_param_serialize_full_table((gs_param_table_instance_t *) mem, start, flags, buf, maxbuflen, &buf_pos);
|
||||
return (error == GS_OK) ? (int) buf_pos : -1;
|
||||
}
|
||||
|
||||
static inline gs_error_t param_serialize_item(const param_table_t * param, uint16_t addr, uint8_t * buf, uint16_t * pos, unsigned int maxlen, void * item, param_serializer_flags flags)
|
||||
{
|
||||
unsigned int tmp_pos = *pos;
|
||||
gs_error_t error = gs_param_serialize_item((const gs_param_table_row_t*) param, addr, item, flags, buf, maxlen, &tmp_pos);
|
||||
*pos = tmp_pos;
|
||||
return (error == GS_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
static inline gs_error_t param_deserialize(param_index_t * mem, uint8_t * buf, int len, param_serializer_flags flags)
|
||||
{
|
||||
return (gs_param_deserialize((gs_param_table_instance_t *) mem, buf, len, flags) == GS_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
static inline gs_error_t param_deserialize_item(const param_table_t * param, uint16_t addr, param_index_t * mem, void * item, param_serializer_flags flags)
|
||||
{
|
||||
return (gs_param_deserialize_item((gs_param_table_instance_t *) mem, (const gs_param_table_row_t*)param, addr, item, flags) == GS_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,74 @@
|
||||
#ifndef PARAM_PARAM_STRING_H
|
||||
#define PARAM_PARAM_STRING_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
* GomSpace Parameter System
|
||||
*/
|
||||
|
||||
#include <param/param_types.h>
|
||||
#include <gs/param/table.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
const param_table_t * row3;
|
||||
const gs_param_table_row_t * row4;
|
||||
} gs_param_row_align_t;
|
||||
|
||||
static inline const param_table_t * param_find_name(const param_table_t rows[], size_t row_count, const char * name)
|
||||
{
|
||||
gs_param_row_align_t row_in = {.row3 = rows};
|
||||
gs_param_row_align_t row_out = {.row4 = gs_param_row_by_name(name, row_in.row4, row_count)};
|
||||
return row_out.row3;
|
||||
}
|
||||
|
||||
static inline const param_table_t * param_find_addr(const param_table_t rows[], size_t row_count, uint16_t addr)
|
||||
{
|
||||
gs_param_row_align_t row_in = {.row3 = rows};
|
||||
gs_param_row_align_t row_out = {.row4 = gs_param_row_by_address(addr, row_in.row4, row_count)};
|
||||
return row_out.row3;
|
||||
}
|
||||
|
||||
static inline void param_list_single(param_table_t * param, param_index_t * mem, int do_read)
|
||||
{
|
||||
gs_param_list_single((gs_param_table_instance_t *) mem, (const gs_param_table_row_t *) param, (do_read != 0));
|
||||
}
|
||||
|
||||
static inline void param_list(param_index_t * mem, int do_read)
|
||||
{
|
||||
gs_param_list((gs_param_table_instance_t *) mem, (do_read != 0));
|
||||
}
|
||||
|
||||
static inline gs_error_t param_from_string(const param_table_t * param , const char * string, void * value)
|
||||
{
|
||||
return gs_param_from_string((const gs_param_table_row_t *)param , string, value);
|
||||
}
|
||||
|
||||
static inline int param_to_string(const param_table_t * param, char * buf, int pos, const void * value, int with_type, int max_size)
|
||||
{
|
||||
unsigned int written = 0;
|
||||
gs_param_to_string((const gs_param_table_row_t *)param, value, with_type, buf, max_size, pos, &written);
|
||||
return (int) written;
|
||||
}
|
||||
|
||||
static inline const char * param_type_to_string(param_type_t type)
|
||||
{
|
||||
return gs_param_type_to_string(type);
|
||||
}
|
||||
|
||||
static inline uint16_t param_index_chksum(param_index_t * mem)
|
||||
{
|
||||
return gs_param_table_checksum((gs_param_table_instance_t*)mem);
|
||||
}
|
||||
|
||||
static inline uint16_t param_index_chksum2(param_index_t * mem)
|
||||
{
|
||||
return gs_param_table_checksum2((gs_param_table_instance_t*)mem);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,92 @@
|
||||
#ifndef PARAM_PARAM_TYPES_H
|
||||
#define PARAM_PARAM_TYPES_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
Legacy/deprecated parameter types and definitions - use <gs/param/types.h>.
|
||||
*/
|
||||
|
||||
#include <gs/param/table.h>
|
||||
#include <gs/param/rparam.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_PARAM_NAME_LEN GS_PARAM_MAX_NAME
|
||||
|
||||
/*
|
||||
Legacy parameter type definition - matches gs_param_type_t exactly.
|
||||
*/
|
||||
typedef gs_param_type_t param_type_t;
|
||||
|
||||
/*
|
||||
Legacy table row definition - matches gs_param_table_row_t exactly.
|
||||
*/
|
||||
typedef struct param_table_s {
|
||||
uint16_t addr;
|
||||
param_type_t type;
|
||||
uint8_t size;
|
||||
uint8_t count; // -> array_size
|
||||
uint8_t flags;
|
||||
char name[MAX_PARAM_NAME_LEN];
|
||||
} param_table_t;
|
||||
|
||||
#define PARAM_COUNT gs_max(GS_PGM_UINT8((param)->count), 1)
|
||||
#define PARAM_SIZE GS_PARAM_SIZE(param)
|
||||
#define PARAM_TYPE GS_PARAM_TYPE(param)
|
||||
#define PARAM_ADDR GS_PARAM_ADDR(param)
|
||||
#define PARAM_FLAGS GS_PARAM_FLAGS(param)
|
||||
|
||||
#define RPARAM_QUERY_MAX_LEN GS_RPARAM_MAX_QUERY
|
||||
|
||||
#define PARAM_MAX_FILESIZE 0x400
|
||||
|
||||
struct param_index_s;
|
||||
|
||||
/*
|
||||
Legacy callback - matches gs_param_callback_func_t exactly.
|
||||
*/
|
||||
typedef void (*param_callback_func)(uint16_t addr, struct param_index_s * index);
|
||||
|
||||
typedef gs_param_table_id_t param_mem;
|
||||
|
||||
/*
|
||||
Legacy table instance definition - matches gs_param_table_instance_t exactly.
|
||||
*/
|
||||
typedef struct param_index_s {
|
||||
const char * name;
|
||||
param_mem mem_id;
|
||||
const param_table_t * table;
|
||||
unsigned int count;
|
||||
void * physaddr;
|
||||
unsigned int size;
|
||||
const gs_param_function_interface_t function_interface;
|
||||
const uint16_t table_chksum;
|
||||
const uint16_t chksum2;
|
||||
const uint16_t checksum_le;
|
||||
const gs_mutex_t lock;
|
||||
param_callback_func callback;
|
||||
const char * const var1;
|
||||
const char * const var2;
|
||||
const void * const var3;
|
||||
const void * const var4;
|
||||
const void * const var5;
|
||||
const void * const var6;
|
||||
const void * const var7;
|
||||
const uint32_t var8;
|
||||
} param_index_t;
|
||||
|
||||
/**
|
||||
Return base size of a parameter type.
|
||||
*/
|
||||
static inline uint8_t param_type_size(param_type_t type)
|
||||
{
|
||||
return gs_param_type_size(type);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,208 @@
|
||||
#ifndef PARAM_RPARAM_CLIENT_H
|
||||
#define PARAM_RPARAM_CLIENT_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
* GomSpace Parameter System
|
||||
*/
|
||||
|
||||
#include <param/param_types.h>
|
||||
#include <gs/param/rparam.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Legacy magic checksum.
|
||||
@deprecated use #GS_RPARAM_MAGIC_CHECKSUM (if remote products supports it).
|
||||
*/
|
||||
#define GS_RPARAM_LEGACY_MAGIC_CHECKSUM 0xb00b
|
||||
|
||||
static inline int rparam_get_full_table(param_index_t* idx, int node, int port, int index_id, uint32_t timeout_ms)
|
||||
{
|
||||
return (gs_rparam_get_full_table((gs_param_table_instance_t *) idx,
|
||||
node,
|
||||
index_id,
|
||||
GS_RPARAM_LEGACY_MAGIC_CHECKSUM,
|
||||
timeout_ms) == GS_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
static inline int rparam_download_table_spec_from_remote_and_save_to_file2(const char* fname, uint8_t node, uint8_t port, param_index_t* idx, uint16_t* return_checksum, uint32_t timeout_ms)
|
||||
{
|
||||
return (gs_rparam_download_table_spec((gs_param_table_instance_t *) idx,
|
||||
fname,
|
||||
node,
|
||||
idx->mem_id,
|
||||
timeout_ms,
|
||||
return_checksum) == GS_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
static inline int rparam_download_table_spec_from_remote_and_save_to_file(const char* fname, uint8_t node, uint8_t port, param_index_t* idx, uint16_t* checksum)
|
||||
{
|
||||
return rparam_download_table_spec_from_remote_and_save_to_file2(fname, node, port, idx, checksum, 10000);
|
||||
}
|
||||
|
||||
static inline int rparam_load_table_spec_from_file(const char* fname, param_index_t* idx, uint16_t* return_checksum)
|
||||
{
|
||||
return (gs_rparam_load_table_spec((gs_param_table_instance_t *) idx, fname, return_checksum) == GS_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
static inline int rparam_get_single(void * out, uint16_t addr, param_type_t type, int size, int mem_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return (gs_rparam_get(node, mem_id, addr, type, GS_RPARAM_LEGACY_MAGIC_CHECKSUM, timeout_ms, out, size) == GS_OK) ? size : -1;
|
||||
}
|
||||
|
||||
static inline int rparam_set_single(const void * in, uint16_t addr, param_type_t type, int size, int mem_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return (gs_rparam_set(node, mem_id, addr, type, GS_RPARAM_LEGACY_MAGIC_CHECKSUM, timeout_ms, in, size) == GS_OK) ? size : -1;
|
||||
}
|
||||
|
||||
static inline int rparam_copy(uint8_t node, uint8_t port, uint32_t timeout_ms, uint8_t from, uint8_t to)
|
||||
{
|
||||
return (gs_rparam_copy(node, timeout_ms, from, to) == GS_OK) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int rparam_save(uint8_t node, uint8_t port, uint32_t timeout_ms, uint8_t from, uint8_t to)
|
||||
{
|
||||
return (gs_rparam_save(node, timeout_ms, from, to) == GS_OK) ? 1 : 0;
|
||||
}
|
||||
|
||||
static inline int rparam_load(uint8_t node, uint8_t port, uint32_t timeout_ms, uint8_t from, uint8_t to)
|
||||
{
|
||||
return (gs_rparam_load(node, timeout_ms, from, to) == GS_OK) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote getters for parameters.
|
||||
* @param out pointer to the output buffer/parameter
|
||||
* @param outlen length of the supplied out-buffer, only applies to rparam_get_string()
|
||||
* @param addr local address of the parameter
|
||||
* @param node CSP address of the node to query
|
||||
* @param port CSP port of the parameter server
|
||||
* @param timeout timeout on remote CSP calls
|
||||
* @returns <0 on error in which case the contents of out is invalid, >0 on success
|
||||
*/
|
||||
static inline int rparam_get_string(char *out, int outlen, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_STRING, outlen, index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote setters for parameters.
|
||||
* @param in pointer to the buffer/parameter value to set
|
||||
* @param inlen length of the supplied in-buffer, only applies to rparam_set_string()
|
||||
* @param addr local address of the parameter
|
||||
* @param node CSP address of the node to query
|
||||
* @param port CSP port of the parameter server
|
||||
* @param timeout timeout on remote CSP calls
|
||||
* @returns <0 on error in which case the contents of out is invalid, >0 on success
|
||||
*/
|
||||
static inline int rparam_set_string(const char *in, int inlen, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_STRING, inlen, index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_uint8(uint8_t * out, uint16_t addr, int tinst_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_UINT8, sizeof(uint8_t), tinst_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_uint8(const uint8_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_UINT8, sizeof(uint8_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_uint16(uint16_t * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_UINT16, sizeof(uint16_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_uint16(const uint16_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_UINT16, sizeof(uint16_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_uint32(uint32_t * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_UINT32, sizeof(uint32_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_uint32(const uint32_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_UINT32, sizeof(uint32_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_uint64(uint64_t * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_UINT64, sizeof(uint64_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_uint64(const uint64_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_UINT64, sizeof(uint64_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_int8(int8_t * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_INT8, sizeof(int8_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_int8(const int8_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_INT8, sizeof(int8_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_int16(int16_t * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_INT16, sizeof(int16_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_int16(const int16_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_INT16, sizeof(int16_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_int32(int32_t * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_INT32, sizeof(int32_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_int32(const int32_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_INT32, sizeof(int32_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_int64(int64_t * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_INT64, sizeof(int64_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_int64(const int64_t * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_INT64, sizeof(int64_t), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_float(float * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_FLOAT, sizeof(float), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_float(const float * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_FLOAT, sizeof(float), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_get_double(double * out, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_get_single(out, addr, PARAM_DOUBLE, sizeof(double), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
static inline int rparam_set_double(const double * in, uint16_t addr, int index_id, int node, int port, uint32_t timeout_ms)
|
||||
{
|
||||
return rparam_set_single(in, addr, PARAM_DOUBLE, sizeof(double), index_id, node, port, timeout_ms);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,42 @@
|
||||
#ifndef GS_PARAM_INTERNAL_PP_I2C_I2C_H
|
||||
#define GS_PARAM_INTERNAL_PP_I2C_I2C_H
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/param/pp/i2c/i2c.h>
|
||||
#include <gs/param/internal/pp/i2c/slave_dispatch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GS_PARAM_I2C_LENGTH_TABLE(length, table) ((length << 3) | (table & 0x07))
|
||||
#define GS_PARAM_I2C_LENGTH_TABLE_TO_LENGTH(lt) ((lt >> 3) & 0x1f)
|
||||
#define GS_PARAM_I2C_LENGTH_TABLE_TO_TABLE(lt) (lt & 0x07)
|
||||
|
||||
/**
|
||||
Data structure for setting parameter.
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) gs_param_i2c_set_request {
|
||||
gs_i2c_slave_dispatch_header_t header;
|
||||
uint8_t length_table;
|
||||
uint8_t addr;
|
||||
uint8_t data[]; // data (+ checksum)
|
||||
} gs_param_i2c_set_request_t;
|
||||
|
||||
/**
|
||||
Data structure for getting parameter.
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) gs_param_i2c_get_request {
|
||||
gs_i2c_slave_dispatch_header_t header;
|
||||
uint8_t length_table;
|
||||
uint8_t addr;
|
||||
uint8_t checksum; // optional
|
||||
} gs_param_i2c_get_request_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,71 @@
|
||||
#ifndef GS_PARAM_INTERNAL_PP_I2C_SLAVE_DISPATCH_H
|
||||
#define GS_PARAM_INTERNAL_PP_I2C_SLAVE_DISPATCH_H
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/util/drivers/i2c/slave.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Header for I2C slave dispatch protocol - must be first in all protocols.
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) gs_i2c_slave_dispatch_header {
|
||||
uint8_t domain_command;
|
||||
} gs_i2c_slave_dispatch_header_t;
|
||||
|
||||
/**
|
||||
Make header from domain and command.
|
||||
*/
|
||||
#define GS_I2C_SLAVE_DISPATCH_HEADER(domain, command) ((domain << 5) | (command & 0x1f))
|
||||
|
||||
/**
|
||||
Extract domain from header.
|
||||
*/
|
||||
#define GS_I2C_SLAVE_DISPATCH_HEADER_TO_DOMAIN(header) ((header >> 5) & 0x7)
|
||||
|
||||
/**
|
||||
Extract comman from header.
|
||||
*/
|
||||
#define GS_I2C_SLAVE_DISPATCH_HEADER_TO_COMMAND(header) (header & 0x1f)
|
||||
|
||||
/**
|
||||
Domain handler.
|
||||
|
||||
Basically same features as normal I2C slave rx callback. The generic I2C dispatch interface will parse the header (first byte)
|
||||
and call the associated handler, based on the domain.
|
||||
|
||||
@param[in] channel I2C channel (handle).
|
||||
@param[in] cmd domain specific command.
|
||||
@param[in] rx_buffer Pointer to start of rx buffer.
|
||||
@param[in] rx number of bytes received so far.
|
||||
@param[in] cswitch If called from within an ISR (embedded platform), this will none NULL.
|
||||
@return total number of bytes to receive before next call back. Return 0 to ignore rest of data - no additional call backs will be done for current I2C transaction.
|
||||
*/
|
||||
typedef void (* gs_i2c_slave_dispatch_handler_t)(uint8_t channel, uint8_t cmd, const uint8_t * rx, size_t rx_length, gs_context_switch_t * cswitch);
|
||||
|
||||
/**
|
||||
Dispatch domains.
|
||||
|
||||
Standard domains should be assigned from the lowest value.
|
||||
Application/board/product should be assigned from highest value.
|
||||
*/
|
||||
typedef enum {
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_RESERVED = 0, //! Avoid use - reserved for GSSB, GSSB broadcasts UID request on domain=0, cmd=13
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_USER1, //! Avoid use - overlap with GSSB commands
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_USER2, //! Avoid use - may overlap with GSSB commands
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_USER3, //! Avoid use - may overlap with GSSB commands
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_PARAM, //! Reserved for libparam.
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_USER5,
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_USER6,
|
||||
GS_I2C_SLAVE_DISPATCH_DOMAIN_USER7,
|
||||
} gs_i2c_slave_dispatch_domain_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,80 @@
|
||||
#ifndef GS_PARAM_INTERNAL_PP_SPI_SLAVE_DISPATCH_H
|
||||
#define GS_PARAM_INTERNAL_PP_SPI_SLAVE_DISPATCH_H
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/util/drivers/spi/slave.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Header for SPI slave dispatch protocol - must be first in all protocols.
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) gs_spi_slave_dispatch_header {
|
||||
uint8_t domain_command;
|
||||
} gs_spi_slave_dispatch_header_t;
|
||||
|
||||
/**
|
||||
Make header from domain and command.
|
||||
*/
|
||||
#define GS_SPI_SLAVE_DISPATCH_HEADER(domain, command) ((domain << 5) | (command & 0x1f))
|
||||
|
||||
/**
|
||||
Extract domain from header.
|
||||
*/
|
||||
#define GS_SPI_SLAVE_DISPATCH_HEADER_TO_DOMAIN(header) ((header >> 5) & 0x7)
|
||||
|
||||
/**
|
||||
Extract comman from header.
|
||||
*/
|
||||
#define GS_SPI_SLAVE_DISPATCH_HEADER_TO_COMMAND(header) (header & 0x1f)
|
||||
|
||||
/**
|
||||
Domain handler.
|
||||
|
||||
Basically same features as normal SPI slave rx callback. The generic SPI dispatch interface will parse the header (first byte)
|
||||
and call the associated handler, based on the domain.
|
||||
|
||||
@param[in] channel SPI channel (handle).
|
||||
@param[in] cmd domain specific command.
|
||||
@param[in] rx_buffer Pointer to start of rx buffer.
|
||||
@param[in] rx number of bytes received so far.
|
||||
@param[in] cswitch If called from within an ISR (embedded platform), this will none NULL.
|
||||
@return total number of bytes to receive before next call back. Return 0 to ignore rest of data - no additional call backs will be done for current SPI transaction.
|
||||
*/
|
||||
typedef uint8_t (* gs_spi_slave_dispatch_handler_t)(uint8_t channel, uint8_t cmd, const uint8_t * rx_buffer, size_t rx, gs_context_switch_t * cswitch);
|
||||
|
||||
/**
|
||||
Dispatch domains.
|
||||
|
||||
Standard domains should be assigned form the lowest value.
|
||||
Application/board/product should be assigned from highest value.
|
||||
*/
|
||||
typedef enum {
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_RESERVED = 0, //! Avoid using 0,
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_USER1,
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_USER2,
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_USER3,
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM,
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_USER5,
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_USER6,
|
||||
GS_SPI_SLAVE_DISPATCH_DOMAIN_USER7,
|
||||
} gs_spi_slave_dispatch_domain_t;
|
||||
|
||||
/**
|
||||
Slave dispatch SPI receiver.
|
||||
|
||||
Must be added on the channel as receiver function, using gs_spi_slave_set_rx().
|
||||
|
||||
@param[in] cswitch If called from within an ISR (embedded platform), this will be set and allow for triggering context switch.
|
||||
*/
|
||||
uint8_t gs_spi_slave_dispatch_rx(uint8_t channel, const uint8_t * rx_buffer, size_t rx, bool new_request, gs_context_switch_t * cswitch);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,65 @@
|
||||
#ifndef GS_PARAM_INTERNAL_PP_SPI_SPI_H
|
||||
#define GS_PARAM_INTERNAL_PP_SPI_SPI_H
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/param/pp/spi/spi.h>
|
||||
#include <gs/param/internal/pp/spi/slave_dispatch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Domain commands.
|
||||
*/
|
||||
typedef enum {
|
||||
GS_PARAM_SPI_COMMAND_SET = 1,
|
||||
GS_PARAM_SPI_COMMAND_GET = 2,
|
||||
GS_PARAM_SPI_COMMAND_SET_WITH_CHECKSUM = 10,
|
||||
GS_PARAM_SPI_COMMAND_GET_WITH_CHECKSUM = 11,
|
||||
} gs_param_spi_command_t;
|
||||
|
||||
#define GS_PARAM_SPI_LENGTH_TABLE(length, table) ((length << 3) | (table & 0x07))
|
||||
#define GS_PARAM_SPI_LENGTH_TABLE_TO_LENGTH(lt) ((lt >> 3) & 0x1f)
|
||||
#define GS_PARAM_SPI_LENGTH_TABLE_TO_TABLE(lt) (lt & 0x07)
|
||||
|
||||
/**
|
||||
Data structure for setting parameter.
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) gs_param_spi_set {
|
||||
gs_spi_slave_dispatch_header_t header;
|
||||
uint8_t length_table;
|
||||
uint8_t addr;
|
||||
uint8_t data[]; // data (+ checksum)
|
||||
} gs_param_spi_set_t;
|
||||
|
||||
/**
|
||||
Data structure for getting parameter.
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) gs_param_spi_get {
|
||||
gs_spi_slave_dispatch_header_t header;
|
||||
uint8_t length_table;
|
||||
uint8_t addr;
|
||||
uint8_t filler; // filler/delay - allow slave to find and prepare data/response
|
||||
uint8_t data[]; // data
|
||||
} gs_param_spi_get_t;
|
||||
|
||||
/**
|
||||
Data structure for getting parameter with checksum
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) gs_param_spi_get_with_checksum {
|
||||
gs_spi_slave_dispatch_header_t header;
|
||||
uint8_t length_table;
|
||||
uint8_t addr;
|
||||
uint8_t checksum;
|
||||
uint8_t filler; // filler/delay - allow slave to find and prepare data/response
|
||||
uint8_t data[]; // data + checksum
|
||||
} gs_param_spi_get_with_checksum_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
146
gomspace/libparam_client/include/gs/param/internal/rparam.h
Normal file
146
gomspace/libparam_client/include/gs/param/internal/rparam.h
Normal file
@ -0,0 +1,146 @@
|
||||
#ifndef GS_PARAM_INTERNAL_RPARAM_H
|
||||
#define GS_PARAM_INTERNAL_RPARAM_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/param/rparam.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Max query payload in a single message (bytes).
|
||||
*/
|
||||
#define GS_RPARAM_QUERY_MAX_PAYLOAD 180
|
||||
|
||||
/**
|
||||
Macro for calculating total query message size, header + payload.
|
||||
*/
|
||||
#define RPARAM_QUERY_LENGTH(query, payload_size) (sizeof(*query) - sizeof(query->payload) + payload_size)
|
||||
|
||||
/**
|
||||
R(emote) parameter request codes.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
Get one or more parameters.
|
||||
*/
|
||||
RPARAM_GET = 0x00,
|
||||
/**
|
||||
Reply to a request.
|
||||
*/
|
||||
RPARAM_REPLY = 0x55,
|
||||
/**
|
||||
Set one or more parameters.
|
||||
*/
|
||||
RPARAM_SET = 0xFF,
|
||||
// RPARAM_SET_TO_FILE = 0xEE,
|
||||
/**
|
||||
Download table specification.
|
||||
*/
|
||||
RPARAM_TABLE = 0x44,
|
||||
/**
|
||||
Copy memory slot to memory slot.
|
||||
@version 4.x: Not supported.
|
||||
*/
|
||||
RPARAM_COPY = 0x77,
|
||||
/**
|
||||
Load from file (slot) to memory (slot).
|
||||
@version 4.x: Only load from primary store - file (slot) is ignored.
|
||||
*/
|
||||
RPARAM_LOAD = 0x88,
|
||||
/**
|
||||
Load from file (slot) to memory (slot).
|
||||
@version 4.x: load by name(s).
|
||||
*/
|
||||
RPARAM_LOAD_FROM_STORE = 0x89,
|
||||
/**
|
||||
Save from memory (slot) to file (slot).
|
||||
@version 4.x: Only save to primary store - file (slot) is ignored.
|
||||
*/
|
||||
RPARAM_SAVE = 0x99,
|
||||
/**
|
||||
Save from memory (slot) to file (slot).
|
||||
@version 4.x: save by name(s).
|
||||
*/
|
||||
RPARAM_SAVE_TO_STORE = 0x9a,
|
||||
// RPARAM_CLEAR = 0xAA, - completely removed
|
||||
} gs_rparam_action_t;
|
||||
|
||||
/**
|
||||
R(emote) parameter reply/completion codes.
|
||||
*/
|
||||
typedef enum {
|
||||
RPARAM_SET_OK = 1,
|
||||
RPARAM_LOAD_OK = 2,
|
||||
RPARAM_SAVE_OK = 3,
|
||||
RPARAM_COPY_OK = 4,
|
||||
// RPARAM_CLEAR_OK = 5,
|
||||
RPARAM_ERROR = 0xFF,
|
||||
} gs_rparam_reply_t;
|
||||
|
||||
/**
|
||||
Payload - save/load to/from stores
|
||||
@version 4
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) {
|
||||
char table[25 + 1];
|
||||
char store[25 + 1];
|
||||
char slot[25 + 1];
|
||||
} gs_rparam_query_payload_store_t;
|
||||
|
||||
/**
|
||||
Payload.
|
||||
*/
|
||||
typedef union __attribute__ ((packed)) {
|
||||
uint16_t addr[0]; //! action = RPARAM_GET
|
||||
uint8_t packed[0]; //! action = RPARAM_REPLY | RPARAM_SET
|
||||
struct { //! action = RPARAM_COPY | RPARAM_LOAD | RPARM_SAVE
|
||||
uint8_t from;
|
||||
uint8_t to;
|
||||
} copy;
|
||||
} gs_rparam_query_payload_t;
|
||||
|
||||
/**
|
||||
Protocol between client and server.
|
||||
@version 4.x: layout (size) has not changed - only naming of certain fields.
|
||||
*/
|
||||
typedef struct __attribute__ ((packed)) {
|
||||
/**
|
||||
Request (gs_rparam_action_t) or Reply (gs_rparam_reply_t).
|
||||
*/
|
||||
uint8_t action;
|
||||
/**
|
||||
Table id.
|
||||
Name changed in 4.0 from \a mem.
|
||||
*/
|
||||
uint8_t table_id;
|
||||
/**
|
||||
Length/size of \a payload in bytes.
|
||||
*/
|
||||
uint16_t length;
|
||||
/**
|
||||
Fletcher's checksum.
|
||||
*/
|
||||
uint16_t checksum;
|
||||
/**
|
||||
Sequence number when split over multiple frames (messages).
|
||||
*/
|
||||
uint16_t seq;
|
||||
/**
|
||||
Total number of frames.
|
||||
*/
|
||||
uint16_t total;
|
||||
/**
|
||||
Payload.
|
||||
*/
|
||||
gs_rparam_query_payload_t payload;
|
||||
} gs_rparam_query_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
@ -0,0 +1,29 @@
|
||||
#ifndef GS_PARAM_INTERNAL_SERIALIZE_H
|
||||
#define GS_PARAM_INTERNAL_SERIALIZE_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/param/serialize.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Serialize data
|
||||
* @param mem Pointer to indexed parameter table
|
||||
* @param addr Array of addresses to serialize
|
||||
* @param addr_count number of items in addr array
|
||||
* @param[in|out] param_offset table parameter offset
|
||||
* @param flags Set options using combination of flags
|
||||
* @param buf Pointer to output
|
||||
* @param buf_size Size of \a buf.
|
||||
*/
|
||||
gs_error_t gs_param_serialize_list(gs_param_table_instance_t * tinst, const uint16_t addr[], unsigned int addr_count, unsigned int * param_pos, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
19
gomspace/libparam_client/include/gs/param/internal/table.h
Normal file
19
gomspace/libparam_client/include/gs/param/internal/table.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef GS_PARAM_INTERNAL_TABLE_H
|
||||
#define GS_PARAM_INTERNAL_TABLE_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/param/table.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
gs_error_t gs_param_parse_name_and_array_index(const char * inp, char * name, size_t size_name, uint8_t * array_index, bool * return_is_array);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
129
gomspace/libparam_client/include/gs/param/internal/types.h
Normal file
129
gomspace/libparam_client/include/gs/param/internal/types.h
Normal file
@ -0,0 +1,129 @@
|
||||
#ifndef GS_PARAM_INTERNAL_TYPES_H
|
||||
#define GS_PARAM_INTERNAL_TYPES_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#if (GS_PARAM_INTERNAL_USE)
|
||||
|
||||
#include <gs/param/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Table instance.
|
||||
*/
|
||||
struct gs_param_table_instance {
|
||||
/**
|
||||
Name of table.
|
||||
*/
|
||||
const char * name;
|
||||
|
||||
/**
|
||||
Table id.
|
||||
*/
|
||||
gs_param_table_id_t id;
|
||||
|
||||
/**
|
||||
Table elements/rows.
|
||||
*/
|
||||
const gs_param_table_row_t * rows;
|
||||
/**
|
||||
Table element/row count.
|
||||
*/
|
||||
unsigned int row_count;
|
||||
|
||||
/**
|
||||
Table memory - volatile parameter store.
|
||||
The allocated size must be at least \a memory_size bytes.
|
||||
*/
|
||||
void * memory;
|
||||
|
||||
/**
|
||||
Size of table data memory in bytes, normally size of memory allocated \a memory.
|
||||
Size must always be specified, even when using function interface and no memory is allocated.
|
||||
*/
|
||||
unsigned int memory_size;
|
||||
|
||||
/**
|
||||
Function interface, e.g. get/set.
|
||||
*/
|
||||
gs_param_function_interface_t function_interface;
|
||||
|
||||
/**
|
||||
Checksum - based on host order (e.g. le or be).
|
||||
@see gs_param_table_checksum()
|
||||
*/
|
||||
uint16_t checksum;
|
||||
|
||||
/**
|
||||
Checksum - based on big-endian (address converted to big-endian).
|
||||
@see gs_param_table_checksum_be()
|
||||
*/
|
||||
uint16_t checksum_be;
|
||||
|
||||
/**
|
||||
Checksum - based on little-endian (address converted to little-endian).
|
||||
@see gs_param_table_checksum_le()
|
||||
*/
|
||||
uint16_t checksum_le;
|
||||
|
||||
/**
|
||||
Lock.
|
||||
Internal access/use only, use gs_param_lock() and gs_param_unlock() to lock and un-lock table.
|
||||
*/
|
||||
gs_mutex_t lock;
|
||||
|
||||
/**
|
||||
Callback for table (data) change.
|
||||
*/
|
||||
void (*callback)(uint16_t addr, gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Store location(s).
|
||||
CSV format, e.g. \"persistent,protected\".
|
||||
*/
|
||||
const char * stores;
|
||||
|
||||
/**
|
||||
Auto-persist.
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
Store.
|
||||
*/
|
||||
const char * store;
|
||||
|
||||
/**
|
||||
User context(s) for the \a set function.
|
||||
*/
|
||||
void * context1;
|
||||
void * context2;
|
||||
|
||||
/**
|
||||
Set/write parameter.
|
||||
*/
|
||||
gs_error_t (*set)(gs_param_table_instance_t * tinst, uint16_t addr, gs_param_type_t type, const void * item, size_t size, uint32_t flags);
|
||||
} auto_persist;
|
||||
|
||||
/**
|
||||
Function for initializing table.
|
||||
*/
|
||||
gs_error_t (*initializer_function)(gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Default values for initializing table.
|
||||
*/
|
||||
const void * default_values;
|
||||
|
||||
/**
|
||||
Future flags.
|
||||
*/
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
60
gomspace/libparam_client/include/gs/param/pp/i2c/i2c.h
Normal file
60
gomspace/libparam_client/include/gs/param/pp/i2c/i2c.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef GS_PARAM_PP_I2C_I2C_H
|
||||
#define GS_PARAM_PP_I2C_I2C_H
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
I2C param protocol client interface.
|
||||
*/
|
||||
|
||||
#include <gs/param/pp/pp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Commands.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
Set parameter.
|
||||
*/
|
||||
GS_PARAM_I2C_COMMAND_SET = 1,
|
||||
/**
|
||||
Get parameter.
|
||||
*/
|
||||
GS_PARAM_I2C_COMMAND_GET = 2,
|
||||
/**
|
||||
Lock table.
|
||||
*/
|
||||
GS_PARAM_I2C_COMMAND_SET_LOCK_WITH_CHECKSUM = 3,
|
||||
/**
|
||||
Get table lock state.
|
||||
*/
|
||||
GS_PARAM_I2C_COMMAND_GET_LOCK_WITH_CHECKSUM = 4,
|
||||
/**
|
||||
Set parameter with checksum.
|
||||
*/
|
||||
GS_PARAM_I2C_COMMAND_SET_WITH_CHECKSUM = 10,
|
||||
/**
|
||||
Get parameter with checksum.
|
||||
*/
|
||||
GS_PARAM_I2C_COMMAND_GET_WITH_CHECKSUM = 11,
|
||||
} gs_param_i2c_command_t;
|
||||
|
||||
/**
|
||||
Initialize the param protocol handle for I2C.
|
||||
|
||||
@param[in] pp handle.
|
||||
@param[in] bus bus to communicate on.
|
||||
@param[in] addr address of node.
|
||||
@param[in] big_endian \a true if slave is big endian. Used to convert to host endian.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_pp_i2c_init(gs_pp_t * pp, uint8_t bus, uint8_t addr, bool big_endian);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
214
gomspace/libparam_client/include/gs/param/pp/pp.h
Normal file
214
gomspace/libparam_client/include/gs/param/pp/pp.h
Normal file
@ -0,0 +1,214 @@
|
||||
#ifndef GS_PARAM_PP_PP_H
|
||||
#define GS_PARAM_PP_PP_H
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
Param Protocol (PP) API - generic interface for getting/setting parameters over SPI, I2C, etc.
|
||||
*/
|
||||
|
||||
#include <gs/util/error.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Flags used in gs_pp_xxx() functions.
|
||||
@{
|
||||
*/
|
||||
/**
|
||||
Use checksum in transfer.
|
||||
@see gs_pp_checksum8()
|
||||
*/
|
||||
#define GS_PP_FLAG_CHECKSUM 0x0001
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
Handle for a protocol connection.
|
||||
*/
|
||||
typedef struct gs_pp gs_pp_t;
|
||||
|
||||
/**
|
||||
Callback for getting a parameter.
|
||||
*/
|
||||
typedef gs_error_t (*gs_pp_get_t)(gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Callback for setting a parameter.
|
||||
*/
|
||||
typedef gs_error_t (*gs_pp_set_t)(gs_pp_t * pp, uint8_t table_id, uint16_t addr, const void * value, size_t value_size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Callback for setting table lock.
|
||||
*/
|
||||
typedef gs_error_t (*gs_pp_get_table_lock_t)(gs_pp_t * pp, uint8_t table_id, bool * value, uint32_t flags);
|
||||
|
||||
/**
|
||||
Callback for setting table lock.
|
||||
*/
|
||||
typedef gs_error_t (*gs_pp_set_table_lock_t)(gs_pp_t * pp, uint8_t table_id, const bool * value, uint32_t flags);
|
||||
|
||||
/**
|
||||
Handle for a protocol connection.
|
||||
*/
|
||||
struct gs_pp {
|
||||
/**
|
||||
Endian type of slave.
|
||||
*/
|
||||
bool big_endian;
|
||||
/**
|
||||
Callback function for \a get.
|
||||
*/
|
||||
gs_pp_get_t get;
|
||||
/**
|
||||
Callback function for \a set.
|
||||
*/
|
||||
gs_pp_set_t set;
|
||||
/**
|
||||
Callback function for \a get_table_lock.
|
||||
*/
|
||||
gs_pp_get_table_lock_t get_table_lock;
|
||||
/**
|
||||
Callback function for \a set_table_lock.
|
||||
*/
|
||||
gs_pp_set_table_lock_t set_table_lock;
|
||||
/**
|
||||
Protocol specifics.
|
||||
*/
|
||||
union {
|
||||
/**
|
||||
SPI connection.
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
SPI slave id.
|
||||
*/
|
||||
uint8_t slave;
|
||||
} spi;
|
||||
/**
|
||||
I2C connection.
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
I2C bus.
|
||||
*/
|
||||
uint8_t bus;
|
||||
/**
|
||||
I2C address.
|
||||
*/
|
||||
uint8_t addr;
|
||||
} i2c;
|
||||
} pp;
|
||||
};
|
||||
|
||||
/**
|
||||
Calculate very simple 8 bit checksum.
|
||||
The checksum is calculated by adding all bytes. If the checksum is 0 (zero), the checksum is set to 1 (one).
|
||||
@param[in] data data to calculate checksum for.
|
||||
@param[in] length data length.
|
||||
@return checksum
|
||||
*/
|
||||
uint8_t gs_pp_checksum8(const void * data, size_t length);
|
||||
|
||||
/**
|
||||
Get lock value
|
||||
|
||||
@param[in] pp Handle for connection
|
||||
@param[in] table_id Table ID
|
||||
@param[out] value Lock state (0 = unlocked, 1 = locked)
|
||||
@param[in] flags
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_pp_get_table_lock(gs_pp_t * pp, uint8_t table_id, bool * value, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set lock value
|
||||
|
||||
@param[in] pp Handle for connection
|
||||
@param[in] table_id Table ID
|
||||
@param[in] value Lock state (0 = unlocked, 1 = locked)
|
||||
@param[in] flags
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_pp_set_table_lock(gs_pp_t * pp, uint8_t table_id, const bool * value, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get int8.
|
||||
*/
|
||||
gs_error_t gs_pp_get_int8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int8_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set int8.
|
||||
*/
|
||||
gs_error_t gs_pp_set_int8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int8_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get uint8.
|
||||
*/
|
||||
gs_error_t gs_pp_get_uint8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint8_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set uint8.
|
||||
*/
|
||||
gs_error_t gs_pp_set_uint8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint8_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get int16.
|
||||
*/
|
||||
gs_error_t gs_pp_get_int16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int16_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set int16.
|
||||
*/
|
||||
gs_error_t gs_pp_set_int16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int16_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get uint16.
|
||||
*/
|
||||
gs_error_t gs_pp_get_uint16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint16_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set uint16.
|
||||
*/
|
||||
gs_error_t gs_pp_set_uint16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint16_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get int32.
|
||||
*/
|
||||
gs_error_t gs_pp_get_int32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int32_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set int32.
|
||||
*/
|
||||
gs_error_t gs_pp_set_int32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int32_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get uint32.
|
||||
*/
|
||||
gs_error_t gs_pp_get_uint32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint32_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set uint32.
|
||||
*/
|
||||
gs_error_t gs_pp_set_uint32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint32_t * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get float.
|
||||
*/
|
||||
gs_error_t gs_pp_get_float(gs_pp_t * pp, uint8_t table_id, uint8_t addr, float * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set float.
|
||||
*/
|
||||
gs_error_t gs_pp_set_float(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const float * value, size_t count, uint32_t flags);
|
||||
|
||||
/**
|
||||
Register commands.
|
||||
*/
|
||||
gs_error_t gs_pp_register_commands(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
29
gomspace/libparam_client/include/gs/param/pp/spi/spi.h
Normal file
29
gomspace/libparam_client/include/gs/param/pp/spi/spi.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef GS_PARAM_PP_SPI_SPI_H
|
||||
#define GS_PARAM_PP_SPI_SPI_H
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
SPI Param Protocol (pp) client interface.
|
||||
*/
|
||||
|
||||
#include <gs/param/pp/pp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Initialize the param protocol handle for SPI.
|
||||
|
||||
@param[in] pp handle.
|
||||
@param[in] slave slave to communicate with.
|
||||
@param[in] big_endian \a true if slave is big endian. Used to convert to host endian.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_pp_spi_init(gs_pp_t * pp, uint8_t slave, bool big_endian);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
395
gomspace/libparam_client/include/gs/param/rparam.h
Normal file
395
gomspace/libparam_client/include/gs/param/rparam.h
Normal file
@ -0,0 +1,395 @@
|
||||
#ifndef GS_PARAM_REMOTE_H
|
||||
#define GS_PARAM_REMOTE_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
Remote parameter API - pending refactoring.
|
||||
*/
|
||||
|
||||
#include <gs/param/types.h>
|
||||
#include <gs/util/string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Magic checksum.
|
||||
If specifying a magic checksum, the rparam server will ignore/skip checksum validation.
|
||||
*/
|
||||
#define GS_RPARAM_MAGIC_CHECKSUM 0x0bb0
|
||||
|
||||
/**
|
||||
Register rparam commands.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_register_commands(void);
|
||||
|
||||
/**
|
||||
Download all (data) values from a remote table to a local instance.
|
||||
|
||||
@param[in] tinst local table instance.
|
||||
@param[in] node CSP address.
|
||||
@param[in] table_id remote table id to download.
|
||||
@param[in] checksum table checksum.
|
||||
@param[in] timeout_ms timeout.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_get_full_table(gs_param_table_instance_t * tinst,
|
||||
uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint16_t checksum,
|
||||
uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
Download a table specification from a remote node, store it in memory and save it to local file system.
|
||||
|
||||
@note Will free existing rows - do not use this on table instances with static assigned rows.
|
||||
|
||||
Table memory will be (re)allocated to match specification.
|
||||
|
||||
@param[in] tinst local table instance.
|
||||
@param[in] fname name of the file to store the table specification in. If NULL, no file will be stored.
|
||||
@param[in] node CSP address
|
||||
@param[in] table_id remote table id to download.
|
||||
@param[in] timeout_ms timeout.
|
||||
@param[out] return_checksum fletcher16 checksum of downloaded specification "as is" - before network/host swapping.
|
||||
@return_gs_error_t
|
||||
@see gs_param_table_free()
|
||||
*/
|
||||
gs_error_t gs_rparam_download_table_spec(gs_param_table_instance_t * tinst,
|
||||
const char * fname,
|
||||
uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint32_t timeout_ms,
|
||||
uint16_t * return_checksum);
|
||||
|
||||
/**
|
||||
Load a table specification from a local file and store it in memory.
|
||||
|
||||
@note Will free existing rows - do not use this on table instances with static assigned rows.
|
||||
|
||||
Table memory will be (re)allocated to match specification.
|
||||
|
||||
@param[in] tinst local table instance.
|
||||
@param[in] fname name of the file to load the table specification from.
|
||||
@param[out] return_checksum fletcher16 checksum stored in file.
|
||||
@return_gs_error_t
|
||||
@see gs_param_table_free()
|
||||
*/
|
||||
gs_error_t gs_rparam_load_table_spec(gs_param_table_instance_t * tinst, const char* fname, uint16_t * return_checksum);
|
||||
|
||||
/**
|
||||
Copy from one table to another table.
|
||||
|
||||
@deprecated Not supported by a param 4 backend and future versions.
|
||||
|
||||
@param[in] node CSP address
|
||||
@param[in] timeout_ms timeout on remote CSP calls
|
||||
@param[in] from from table-id.
|
||||
@param[in] to to table-id.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_copy(uint8_t node, uint32_t timeout_ms, uint8_t from, uint8_t to);
|
||||
|
||||
/**
|
||||
Save table.
|
||||
|
||||
@note On a param 4 backend, the table will always be saved to it's primary store.
|
||||
|
||||
@param[in] node CSP address
|
||||
@param[in] timeout_ms timeout on remote CSP calls
|
||||
@param[in] id table to save.
|
||||
@param[in] to to file slot - ignored on param 4 backends.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_save(uint8_t node, uint32_t timeout_ms, gs_param_table_id_t id, uint8_t to);
|
||||
|
||||
/**
|
||||
Save table.
|
||||
|
||||
@version 4
|
||||
@param[in] node CSP address
|
||||
@param[in] timeout_ms timeout on remote CSP calls
|
||||
@param[in] table_id remote table id.
|
||||
@param[in] store store name.
|
||||
@param[in] slot slot within store.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_save_to_store(uint8_t node, uint32_t timeout_ms, uint8_t table_id,
|
||||
const char * store, const char * slot);
|
||||
|
||||
/**
|
||||
Load table from store.
|
||||
|
||||
@note On a param 4 backend, the specified table will be loadded from it's primary store.
|
||||
|
||||
@param[in] node CSP address
|
||||
@param[in] timeout_ms timeout on remote CSP calls
|
||||
@param[in] from from file slot - ignored on param 4 backends.
|
||||
@param[in] id table to load.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_load(uint8_t node, uint32_t timeout_ms, uint8_t from, gs_param_table_id_t id);
|
||||
|
||||
/**
|
||||
Load table from store.
|
||||
|
||||
@version 4
|
||||
@param[in] node CSP address
|
||||
@param[in] timeout_ms timeout on remote CSP calls
|
||||
@param[in] table_id remote table id.
|
||||
@param[in] store store name.
|
||||
@param[in] slot slot within store.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_load_from_store(uint8_t node, uint32_t timeout_ms, uint8_t table_id,
|
||||
const char * store, const char * slot);
|
||||
|
||||
/**
|
||||
Get parameter.
|
||||
|
||||
@param[in] node CSP address
|
||||
@param[in] table_id remote table id.
|
||||
@param[in] addr parameter address (remote table).
|
||||
@param[in] type parameter type.
|
||||
@param[in] checksum checksum
|
||||
@param[in] timeout_ms timeout
|
||||
@param[out] value returned value (user allocated)
|
||||
@param[in] value_size size of \a value buffer.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_get(uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint16_t addr,
|
||||
gs_param_type_t type,
|
||||
uint16_t checksum,
|
||||
uint32_t timeout_ms,
|
||||
void * value,
|
||||
size_t value_size);
|
||||
|
||||
/**
|
||||
Set parameter.
|
||||
|
||||
@param[in] node CSP address
|
||||
@param[in] table_id remote table id.
|
||||
@param[in] addr parameter address (remote table).
|
||||
@param[in] type parameter type.
|
||||
@param[in] checksum checksum
|
||||
@param[in] timeout_ms timeout
|
||||
@param[in] value value to set
|
||||
@param[in] value_size size of \a value.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_set(uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint16_t addr,
|
||||
gs_param_type_t type,
|
||||
uint16_t checksum,
|
||||
uint32_t timeout_ms,
|
||||
const void * value,
|
||||
size_t value_size);
|
||||
|
||||
/**
|
||||
Get string.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_string(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, char * value, size_t value_size)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_STRING, checksum, timeout_ms, value, value_size);
|
||||
}
|
||||
|
||||
/**
|
||||
Set string.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_string(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, const char * value, size_t value_size)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_STRING, checksum, timeout_ms, value, (value_size == 0) ? (strlen(value) + 1) : value_size);
|
||||
}
|
||||
|
||||
/**
|
||||
Get int8.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_int8(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int8_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_INT8, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set int8.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_int8(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int8_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_INT8, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get uint8.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_uint8(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint8_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_UINT8, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set uint8.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_uint8(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint8_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_UINT8, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get int16.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_int16(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int16_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_INT16, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set int16.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_int16(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int16_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_INT16, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get uint16.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_uint16(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint16_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_UINT16, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set uint16.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_uint16(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint16_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_UINT16, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get int32.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_int32(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int32_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_INT32, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set int32.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_int32(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int32_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_INT32, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get uint32.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_uint32(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint32_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_UINT32, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set uint32.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_uint32(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint32_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_UINT32, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get int64.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_int64(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int64_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_INT64, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set int64.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_int64(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, int64_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_INT64, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get uint64.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_uint64(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint64_t * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_UINT64, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set uint64.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_uint64(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, uint64_t value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_UINT64, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get float.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_float(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, float * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_FLOAT, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set float.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_float(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, float value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_FLOAT, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/**
|
||||
Get double.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_get_double(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, double * value)
|
||||
{
|
||||
return gs_rparam_get(node, table_id, addr, GS_PARAM_DOUBLE, checksum, timeout_ms, value, sizeof(*value));
|
||||
}
|
||||
|
||||
/**
|
||||
Set double.
|
||||
*/
|
||||
static inline gs_error_t gs_rparam_set_double(uint8_t node, gs_param_table_id_t table_id, uint16_t addr,
|
||||
uint16_t checksum, uint32_t timeout_ms, double value)
|
||||
{
|
||||
return gs_rparam_set(node, table_id, addr, GS_PARAM_DOUBLE, checksum, timeout_ms, &value, sizeof(value));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
101
gomspace/libparam_client/include/gs/param/serialize.h
Normal file
101
gomspace/libparam_client/include/gs/param/serialize.h
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef GS_PARAM_CLIENT_SERIALIZE_H
|
||||
#define GS_PARAM_CLIENT_SERIALIZE_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
Serialize API - pending refactoring.
|
||||
*/
|
||||
|
||||
#include <gs/param/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Serialize/deserialize flags
|
||||
Flags must be in range: bit 8 - 15, to avoid clash with other parts of the parameter system.
|
||||
*/
|
||||
typedef enum {
|
||||
GS_PARAM_SF_DRY_RUN = (1 << 8), //!< F_DRY_RUN do not write to memory
|
||||
GS_PARAM_SF_TO_BIG_ENDIAN = (1 << 9), //!< F_TO_BIG_ENDIAN Convert from host to big endian
|
||||
GS_PARAM_SF_FROM_BIG_ENDIAN = (1 << 10), //!< F_FROM_BIG_ENDIAN Confert from big endian to host order
|
||||
GS_PARAM_SF_PACKED = (1 << 11), //!< F_PACKED Do not pack addresses
|
||||
|
||||
F_DRY_RUN = GS_PARAM_SF_DRY_RUN,
|
||||
F_TO_BIG_ENDIAN = GS_PARAM_SF_TO_BIG_ENDIAN,
|
||||
F_FROM_BIG_ENDIAN = GS_PARAM_SF_FROM_BIG_ENDIAN,
|
||||
F_PACKED = GS_PARAM_SF_PACKED,
|
||||
} gs_param_serialize_flags_t;
|
||||
|
||||
/**
|
||||
* In-place conversion of a single parameter from big endian to host byte order
|
||||
* @param type param type
|
||||
* @param item pointer to parameter memory
|
||||
* @return 1 if memory has been swapped, 0 if not
|
||||
*/
|
||||
bool gs_param_betoh(gs_param_type_t type, void * item);
|
||||
|
||||
/**
|
||||
* In-place conversion of a single parameter from host byte order to big endian
|
||||
* @param type param type
|
||||
* @param item porinter to parameter memory
|
||||
* @return 1 if memory has been swapped, 0 if not
|
||||
*/
|
||||
bool gs_param_htobe(gs_param_type_t type, void * item);
|
||||
|
||||
/**
|
||||
Serialize data
|
||||
|
||||
@param[in] tinst table.
|
||||
@param[in,out] param_pos parameter iterator.
|
||||
@param[in] flags flags.
|
||||
@param[out] buf user supplied buffer of \a buf_size.
|
||||
@param[in] buf_size of size of \a buf
|
||||
@param[in,out] buf_pos index into \a buf
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_serialize_full_table(gs_param_table_instance_t * tinst, unsigned int * param_pos, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos);
|
||||
|
||||
/**
|
||||
Serialize single item
|
||||
|
||||
@param[in] param parameter to serialize
|
||||
@param[in] addr Address of item
|
||||
@param[in] item item to serialize.
|
||||
@param[in] flags flags.
|
||||
@param[out] buf user supplied buffer of \a buf_size.
|
||||
@param[in] buf_size of size of \a buf
|
||||
@param[in,out] buf_pos index into \a buf
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_serialize_item(const gs_param_table_row_t * param, uint16_t addr, const void * item, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos);
|
||||
|
||||
/**
|
||||
Deserialize packed parameters into memory
|
||||
|
||||
@param[in] tinst table.
|
||||
@param[in] buf serialized data.
|
||||
@param[in] buf_size size \a buf containing serialized data
|
||||
@param[in] flags flags.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_deserialize(gs_param_table_instance_t * tinst, const uint8_t * buf, unsigned int buf_size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Deserialize a sginle item from a string into memory
|
||||
|
||||
@param[in] tinst table.
|
||||
@param param Pointer to specific parameter to deserialize
|
||||
@param addr Address of parameter
|
||||
@param item Pointer to memory area where item should be written
|
||||
@param flags Set options using combination of flags
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_deserialize_item(gs_param_table_instance_t * tinst, const gs_param_table_row_t * param, uint16_t addr, const void * item, uint32_t flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
428
gomspace/libparam_client/include/gs/param/table.h
Normal file
428
gomspace/libparam_client/include/gs/param/table.h
Normal file
@ -0,0 +1,428 @@
|
||||
#ifndef GS_PARAM_TABLE_H
|
||||
#define GS_PARAM_TABLE_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
Client table API.
|
||||
*/
|
||||
|
||||
#include <gs/param/types.h>
|
||||
#include <gs/util/stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Allocate table memory when creating a table.
|
||||
|
||||
Flags must be in range: bit 16 - 23, to avoid clash with other parts of the parameter system.
|
||||
*/
|
||||
#define GS_PARAM_TABLE_F_ALLOC_MEMORY 0x0100
|
||||
/**
|
||||
Allocate table rows.
|
||||
|
||||
Flags must be in range: bit 16 - 23, to avoid clash with other parts of the parameter system.
|
||||
*/
|
||||
#define GS_PARAM_TABLE_F_ALLOC_ROWS 0x0200
|
||||
/**
|
||||
Disable table locking.
|
||||
|
||||
Flags must be in range: bit 16 - 23, to avoid clash with other parts of the parameter system.
|
||||
*/
|
||||
#define GS_PARAM_TABLE_F_NO_LOCK 0x0400
|
||||
|
||||
/**
|
||||
Calculate memory size based on table rows.
|
||||
|
||||
@param[in] rows rows
|
||||
@param[in] row_count row count.
|
||||
@return size of table or 0 in case of invalid arguments.
|
||||
*/
|
||||
size_t gs_param_calc_table_size(const gs_param_table_row_t * rows, size_t row_count);
|
||||
|
||||
/**
|
||||
Return size of table instance.
|
||||
*/
|
||||
size_t gs_param_table_instance_size(void);
|
||||
|
||||
/**
|
||||
Clear (and check size) of memory for table instance.
|
||||
|
||||
@param[in] var user allocated space of at least gs_param_table_instance_size() bytes.
|
||||
@param[in] var_size of \a var.
|
||||
@return table instance
|
||||
@see gs_param_table_instance_size()
|
||||
@see #GS_PARAM_TINST_VAR
|
||||
*/
|
||||
gs_param_table_instance_t * gs_param_table_instance_clear(void * var, size_t var_size);
|
||||
|
||||
/**
|
||||
Allocates aligned space on the stack for a table instance structure.
|
||||
@param[in] var name of table instsance variable.
|
||||
*/
|
||||
#define GS_PARAM_TINST_VAR(var) uint8_t var##__data [gs_param_table_instance_size()] __attribute__ ((aligned(4))); gs_param_table_instance_t * var = gs_param_table_instance_clear(var##__data, sizeof(var##__data))
|
||||
|
||||
/**
|
||||
Allocate memory for table instance.
|
||||
|
||||
Use gs_param_table_free() to free any internal resources.
|
||||
|
||||
Use standard free() to free allocated memory.
|
||||
|
||||
@return table instance on success, otherwise NULL.
|
||||
*/
|
||||
gs_param_table_instance_t * gs_param_table_instance_alloc(void);
|
||||
|
||||
/**
|
||||
Find row by name.
|
||||
|
||||
@param[in] name parameter name.
|
||||
@param[in] rows rows
|
||||
@param[in] row_count row count.
|
||||
@return row or NULL if not found.
|
||||
*/
|
||||
const gs_param_table_row_t * gs_param_row_by_name(const char * name, const gs_param_table_row_t * rows, size_t row_count);
|
||||
|
||||
/**
|
||||
Find row by address.
|
||||
|
||||
@param[in] addr parameter address.
|
||||
@param[in] rows rows
|
||||
@param[in] row_count row count.
|
||||
@return row or NULL if not found.
|
||||
*/
|
||||
const gs_param_table_row_t * gs_param_row_by_address(uint16_t addr, const gs_param_table_row_t * rows, size_t row_count);
|
||||
|
||||
/**
|
||||
Return table memory.
|
||||
|
||||
@note handle with care - any read/write should be atomic to prevent inconsistent data.
|
||||
|
||||
@param[in] tinst table instance
|
||||
@param[out] return_size if not NULL, the memory size is returned.
|
||||
@return pointer to the table's data memory.
|
||||
*/
|
||||
void * gs_param_table_get_memory(gs_param_table_instance_t * tinst, size_t * return_size);
|
||||
|
||||
/**
|
||||
Return table rows.
|
||||
|
||||
@param[in] tinst table instance
|
||||
@param[out] return_count if not NULL, the row count is returned.
|
||||
@return pointer to the table rows.
|
||||
*/
|
||||
const gs_param_table_row_t * gs_param_table_get_rows(gs_param_table_instance_t * tinst, size_t * return_count);
|
||||
|
||||
/**
|
||||
Lock table (recursive).
|
||||
|
||||
@param[in] tinst table instance
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_table_lock(gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Unlock table.
|
||||
|
||||
Unlock must be called once for every time gs_param_table_lock() has been called.
|
||||
|
||||
@param[in] tinst table instance
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_table_unlock(gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Free internal resources and clears instance.
|
||||
|
||||
@param[in] tinst table instance
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_table_free(gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Print a single parameter on stream.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] row row to print.
|
||||
@param[in] list_data \a true includes parameter value.
|
||||
@param[in] flags flags to control output format: #GS_PARAM_F_SHOW_SCIENTIFIC, #GS_PARAM_F_SHOW_HEX.
|
||||
@param[in] out output stream.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_list_single_to_stream(gs_param_table_instance_t * tinst, const gs_param_table_row_t * row, bool list_data, uint32_t flags, FILE * out);
|
||||
|
||||
/**
|
||||
Print a single parameter on stdout.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] row row to print.
|
||||
@param[in] list_data \a true includes parameter value.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
static inline gs_error_t gs_param_list_single(gs_param_table_instance_t * tinst, const gs_param_table_row_t * row, bool list_data)
|
||||
{
|
||||
return gs_param_list_single_to_stream(tinst, row, list_data, 0, stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
Print entire table on stream.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] list_data \a true includes parameter value.
|
||||
@param[in] flags flags to control output format: #GS_PARAM_F_SHOW_SCIENTIFIC, #GS_PARAM_F_SHOW_HEX.
|
||||
@param[in] out output stream.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_list_to_stream(gs_param_table_instance_t * tinst, bool list_data, uint32_t flags, FILE * out);
|
||||
|
||||
/**
|
||||
Print entire table on stdout.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] list_data \a true includes parameter value.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
static inline gs_error_t gs_param_list(gs_param_table_instance_t * tinst, bool list_data)
|
||||
{
|
||||
return gs_param_list_to_stream(tinst, list_data, 0, stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
Convert string to parameter.
|
||||
|
||||
@param[in] row row defining the parameter to convert.
|
||||
@param[in] string string to convert.
|
||||
@param[out] return_value user supplied buffer for returning the value - must be at least the size specified in \a row
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_from_string(const gs_param_table_row_t * row, const char * string, void * return_value);
|
||||
|
||||
/**
|
||||
Convert parameter to string.
|
||||
|
||||
@param[in] row row defining the parameter to convert.
|
||||
@param[in] value parameter value to convert.
|
||||
@param[in] with_type \a true includes data type.
|
||||
@param[in] flags flags to control output format: #GS_PARAM_F_SHOW_SCIENTIFIC, #GS_PARAM_F_SHOW_HEX.
|
||||
@param[out] buf user supplied buffer of \a buf_size bytes.
|
||||
@param[in] buf_size size of \a buf in bytes.
|
||||
@param[in] buf_pos buffer position to insert string.
|
||||
@param[out] return_buf_written number of bytes written to \a buf.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_to_string2(const gs_param_table_row_t * row, const void * value, bool with_type, uint32_t flags, char * buf, unsigned int buf_size, unsigned int buf_pos, unsigned int * return_buf_written);
|
||||
|
||||
/**
|
||||
Convert parameter to string.
|
||||
|
||||
@param[in] row row defining the parameter to convert.
|
||||
@param[in] value parameter value to convert.
|
||||
@param[in] with_type \a true includes data type.
|
||||
@param[out] buf user supplied buffer of \a buf_size bytes.
|
||||
@param[in] buf_size size of \a buf in bytes.
|
||||
@param[in] buf_pos buffer position to insert string.
|
||||
@param[out] return_buf_written number of bytes written to \a buf.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
static inline gs_error_t gs_param_to_string(const gs_param_table_row_t * row, const void * value, bool with_type, char * buf, unsigned int buf_size, unsigned int buf_pos, unsigned int * return_buf_written)
|
||||
{
|
||||
return gs_param_to_string2(row, value, with_type, 0, buf, buf_size, buf_pos, return_buf_written);
|
||||
}
|
||||
|
||||
/**
|
||||
Convert parameter type to string.
|
||||
|
||||
@param[in] type parameter type.
|
||||
@return pointer to a static string.
|
||||
*/
|
||||
const char * gs_param_type_to_string(gs_param_type_t type);
|
||||
|
||||
/**
|
||||
Return size of parameter type.
|
||||
|
||||
@param[in] type parameter type.
|
||||
@return size of parameter type in bytes.
|
||||
*/
|
||||
uint8_t gs_param_type_size(gs_param_type_t type);
|
||||
|
||||
/**
|
||||
Get table checksum - little-endian.
|
||||
@note Use/exchange gs_param_table_checksum_be(), as this is calculated the same on all platforms.
|
||||
@param[in] tinst table instance.
|
||||
@returns 16-bit fletcher checksum
|
||||
*/
|
||||
uint16_t gs_param_table_checksum_le(gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Get table checksum - big-endian/network-order (prefered).
|
||||
@param[in] tinst table instance.
|
||||
@returns 16-bit fletcher checksum
|
||||
*/
|
||||
uint16_t gs_param_table_checksum_be(gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Get table checksum - host-order (not cross-platform).
|
||||
@deprecated use gs_param_table_checksum_be()
|
||||
@param[in] tinst table instance.
|
||||
@returns 16-bit fletcher checksum
|
||||
*/
|
||||
uint16_t gs_param_table_checksum(gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Get table checksum - big-endian.
|
||||
@deprecated use gs_param_table_checksum_be()
|
||||
@param[in] tinst table instance.
|
||||
@returns 16-bit fletcher checksum
|
||||
*/
|
||||
static inline uint16_t gs_param_table_checksum2(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
return gs_param_table_checksum_be(tinst);
|
||||
}
|
||||
|
||||
/**
|
||||
Get/read parameter from table.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] addr parameter address (offset in table).
|
||||
@param[in] type parameter type.
|
||||
@param[out] return_value value of parameter - user supplied memory of at least \a size size.
|
||||
@param[in] size number of bytes to get/read - must match \a type, e.g. 4 bytes for an uint32_t.
|
||||
@param[in] flags flags.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_get(gs_param_table_instance_t * tinst, uint16_t addr, gs_param_type_t type, void * return_value, size_t size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set/write parameter in table.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] addr parameter address (offset in table).
|
||||
@param[in] type parameter type.
|
||||
@param[in] value value of parameter.
|
||||
@param[in] size number of bytes to set/write - must match \a type, e.g. 4 bytes for an uint32_t.
|
||||
@param[in] flags flags.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_set(gs_param_table_instance_t * tinst, uint16_t addr, gs_param_type_t type, const void * value, size_t size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get string parameter.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] addr parameter address (offset in table).
|
||||
@param[out] buf value of parameter - user supplied memory of at least parameter size + 1 to hold NUL termination.
|
||||
@param[in] buf_size size of \a buf - ensure room for NUL termination.
|
||||
@param[in] flags flags.
|
||||
@return GS_ERROR_OVERFLOW if string + NUL termination exceeds \a buf_size.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_get_string(gs_param_table_instance_t * tinst, uint16_t addr, char * buf, size_t buf_size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set string parameter.
|
||||
|
||||
@param[in] tinst table.
|
||||
@param[in] addr parameter address (offset in table).
|
||||
@param[in] value string to save - parameter must be able to hold string + NUL termination.
|
||||
@param[in] flags flags.
|
||||
@return GS_ERROR_OVERFLOW if string + NUL termination exceeds parameter size.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_set_string(gs_param_table_instance_t * tinst, uint16_t addr, const char * value, uint32_t flags);
|
||||
|
||||
/**
|
||||
Get data parameter.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] addr parameter address (offset in table).
|
||||
@param[out] buf value of parameter - user supplied memory of at least parameter size.
|
||||
@param[in] buf_size size of \a buf.
|
||||
@param[in] flags flags.
|
||||
@return GS_ERROR_OVERFLOW if parameter size is greater than \a buf_size.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_get_data(gs_param_table_instance_t * tinst, uint16_t addr, void * buf, size_t buf_size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Set data parameter.
|
||||
|
||||
@param[in] tinst table instanc.
|
||||
@param[in] addr parameter address (offset in table).
|
||||
@param[in] value value of parameter.
|
||||
@param[in] value_size size of \a value.
|
||||
@param[in] flags flags.
|
||||
@return GS_ERROR_OVERFLOW if parameter size is greater than \a buf_size.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_param_set_data(gs_param_table_instance_t * tinst, uint16_t addr, const void * value, size_t value_size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Macro for expanding get/set functions.
|
||||
@param[in] name function suffix name.
|
||||
@param[in] native_type native type
|
||||
@param[in] param_type parameter type
|
||||
*/
|
||||
#define GS_PARAM_PASTE(name, native_type, param_type) \
|
||||
static inline gs_error_t gs_param_get_##name(gs_param_table_instance_t * tinst, uint16_t addr, native_type * buf, uint32_t flags) { \
|
||||
return gs_param_get(tinst, addr, param_type, buf, sizeof(*buf), flags); \
|
||||
} \
|
||||
static inline native_type gs_param_get_##name##_nc(gs_param_table_instance_t * tinst, uint16_t addr, uint32_t flags) { \
|
||||
native_type value = 0; \
|
||||
gs_param_get(tinst, addr, param_type, &value, sizeof(value), flags); \
|
||||
return value; \
|
||||
} \
|
||||
static inline gs_error_t gs_param_set_##name(gs_param_table_instance_t * tinst, uint16_t addr, native_type value, uint32_t flags) { \
|
||||
return gs_param_set(tinst, addr, param_type, &value, sizeof(value), flags); \
|
||||
}
|
||||
|
||||
/**
|
||||
Get/set boolean.
|
||||
*/
|
||||
GS_PARAM_PASTE(bool, bool, GS_PARAM_BOOL)
|
||||
/**
|
||||
Get/set uint8.
|
||||
*/
|
||||
GS_PARAM_PASTE(uint8, uint8_t, GS_PARAM_UINT8)
|
||||
/**
|
||||
Get/set uint16.
|
||||
*/
|
||||
GS_PARAM_PASTE(uint16, uint16_t, GS_PARAM_UINT16)
|
||||
/**
|
||||
Get/set uint32.
|
||||
*/
|
||||
GS_PARAM_PASTE(uint32, uint32_t, GS_PARAM_UINT32)
|
||||
/**
|
||||
Get/set uint64.
|
||||
*/
|
||||
GS_PARAM_PASTE(uint64, uint64_t, GS_PARAM_UINT64)
|
||||
/**
|
||||
Get/set int8.
|
||||
*/
|
||||
GS_PARAM_PASTE(int8, int8_t, GS_PARAM_INT8)
|
||||
/**
|
||||
Get/set int16.
|
||||
*/
|
||||
GS_PARAM_PASTE(int16, int16_t, GS_PARAM_INT16)
|
||||
/**
|
||||
Get/set int32.
|
||||
*/
|
||||
GS_PARAM_PASTE(int32, int32_t, GS_PARAM_INT32)
|
||||
/**
|
||||
Get/set int64.
|
||||
*/
|
||||
GS_PARAM_PASTE(int64, int64_t, GS_PARAM_INT64)
|
||||
/**
|
||||
Get/set double.
|
||||
*/
|
||||
GS_PARAM_PASTE(double, double, GS_PARAM_DOUBLE)
|
||||
/**
|
||||
Get/set float.
|
||||
*/
|
||||
GS_PARAM_PASTE(float, float, GS_PARAM_FLOAT)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
272
gomspace/libparam_client/include/gs/param/types.h
Normal file
272
gomspace/libparam_client/include/gs/param/types.h
Normal file
@ -0,0 +1,272 @@
|
||||
#ifndef GS_PARAM_TYPES_H
|
||||
#define GS_PARAM_TYPES_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
/**
|
||||
@file
|
||||
|
||||
Parameter types.
|
||||
*/
|
||||
|
||||
#include <gs/util/mutex.h>
|
||||
#include <gs/util/pgm.h>
|
||||
#include <gs/util/minmax.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Macros for accessing table row members.
|
||||
These macros can be used to access members in a cross-platform way, compensating for the AVR8's memory model.
|
||||
@{
|
||||
*/
|
||||
#define GS_PARAM_ARRAY_SIZE(p) gs_max(GS_PGM_UINT8((p)->array_size), 1)
|
||||
#define GS_PARAM_SIZE(p) GS_PGM_UINT8((p)->size)
|
||||
#define GS_PARAM_TYPE(p) GS_PGM_UINT8((p)->type)
|
||||
#define GS_PARAM_ADDR(p) GS_PGM_UINT16((p)->addr)
|
||||
#define GS_PARAM_FLAGS(p) GS_PGM_UINT8((p)->flags)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
Max parameter name - including 0 termination.
|
||||
@note In some rare/old table definitions, the name may not be NULL terminated.
|
||||
*/
|
||||
#define GS_PARAM_MAX_NAME 14
|
||||
|
||||
/**
|
||||
Parameter flags.
|
||||
Flags must be in range: bit 0 - 7, to avoid clash with other parts of the parameter system.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
Parameter will be stored in configured auto-persist store when set.
|
||||
@note Flag must be specified when setting the parameter.
|
||||
*/
|
||||
GS_PARAM_F_AUTO_PERSIST = (1 << 0),
|
||||
/**
|
||||
@deprecated Not supported in version 4.0
|
||||
*/
|
||||
PARAM_F_READONLY = (1 << 1),
|
||||
/**
|
||||
Skip callback, when parameter is set.
|
||||
@note Flag must be specified when setting the parameter.
|
||||
*/
|
||||
GS_PARAM_F_NO_CALLBACK = (1 << 2),
|
||||
/**
|
||||
Show/display parameter in hex.
|
||||
*/
|
||||
GS_PARAM_F_SHOW_HEX = (1 << 3),
|
||||
/**
|
||||
Show double/float using scientific notation.
|
||||
*/
|
||||
GS_PARAM_F_SHOW_SCIENTIFIC = (1 << 4),
|
||||
|
||||
PARAM_F_NOCALLBACK = GS_PARAM_F_NO_CALLBACK,
|
||||
PARAM_F_PERSIST = GS_PARAM_F_AUTO_PERSIST,
|
||||
} gs_param_flags_t;
|
||||
|
||||
/**
|
||||
* Parameter types.
|
||||
*/
|
||||
typedef enum __attribute__((__packed__)) {
|
||||
/**
|
||||
Unsigned 8 bit (uint8_t).
|
||||
*/
|
||||
GS_PARAM_UINT8 = 0,
|
||||
/**
|
||||
Unsigned 16 bit (uint16_t).
|
||||
*/
|
||||
GS_PARAM_UINT16 = 1,
|
||||
/**
|
||||
Unsigned 32 bit (uint32_t).
|
||||
*/
|
||||
GS_PARAM_UINT32 = 2,
|
||||
/**
|
||||
Unsigned 64 bit (uint64_t).
|
||||
*/
|
||||
GS_PARAM_UINT64 = 3,
|
||||
/**
|
||||
Signed 8 bit (int8_t).
|
||||
*/
|
||||
GS_PARAM_INT8 = 4,
|
||||
/**
|
||||
Signed 16 bit (int16_t).
|
||||
*/
|
||||
GS_PARAM_INT16 = 5,
|
||||
/**
|
||||
Signed 32 bit (int32_t).
|
||||
*/
|
||||
GS_PARAM_INT32 = 6,
|
||||
/**
|
||||
Signed 64 bit (int64_t).
|
||||
*/
|
||||
GS_PARAM_INT64 = 7,
|
||||
/**
|
||||
@deprecated - use #GS_PARAM_UINT8 and #GS_PARAM_F_SHOW_HEX.
|
||||
*/
|
||||
PARAM_X8 = 8,
|
||||
/**
|
||||
@deprecated - use #GS_PARAM_UINT16 and #GS_PARAM_F_SHOW_HEX.
|
||||
*/
|
||||
PARAM_X16 = 9,
|
||||
/**
|
||||
@deprecated - use #GS_PARAM_UINT32 and #GS_PARAM_F_SHOW_HEX.
|
||||
*/
|
||||
PARAM_X32 = 10,
|
||||
/**
|
||||
@deprecated - use #GS_PARAM_UINT64 and #GS_PARAM_F_SHOW_HEX.
|
||||
*/
|
||||
PARAM_X64 = 11,
|
||||
/**
|
||||
Double.
|
||||
*/
|
||||
GS_PARAM_DOUBLE = 12,
|
||||
/**
|
||||
Float.
|
||||
*/
|
||||
GS_PARAM_FLOAT = 13,
|
||||
/**
|
||||
C or null-terminated string.
|
||||
@note The specified \a size must include space for the NUL character.
|
||||
*/
|
||||
GS_PARAM_STRING = 14,
|
||||
/**
|
||||
Data (binary blob).
|
||||
Binary blob: [0, 0x40, 0x4f] -> '00404f'
|
||||
*/
|
||||
GS_PARAM_DATA = 15,
|
||||
/**
|
||||
Boolean.
|
||||
Expected same size as uint8_t.
|
||||
*/
|
||||
GS_PARAM_BOOL = 16,
|
||||
|
||||
PARAM_UINT8 = GS_PARAM_UINT8,
|
||||
PARAM_UINT16 = GS_PARAM_UINT16,
|
||||
PARAM_UINT32 = GS_PARAM_UINT32,
|
||||
PARAM_UINT64 = GS_PARAM_UINT64,
|
||||
PARAM_INT8 = GS_PARAM_INT8,
|
||||
PARAM_INT16 = GS_PARAM_INT16,
|
||||
PARAM_INT32 = GS_PARAM_INT32,
|
||||
PARAM_INT64 = GS_PARAM_INT64,
|
||||
PARAM_DOUBLE = GS_PARAM_DOUBLE,
|
||||
PARAM_FLOAT = GS_PARAM_FLOAT,
|
||||
PARAM_STRING = GS_PARAM_STRING,
|
||||
PARAM_DATA = GS_PARAM_DATA,
|
||||
PARAM_BOOL = GS_PARAM_BOOL,
|
||||
} gs_param_type_t;
|
||||
|
||||
/**
|
||||
Table row.
|
||||
|
||||
A table row defines one parameter, and a table is defined by one or more rows.
|
||||
|
||||
@note Make sure to update gs_param_table_checksum2(), if adding fields > 1 byte.
|
||||
|
||||
@note AVR8: Table definitions must be located in \a program memory, i.e. must be const.
|
||||
*/
|
||||
typedef struct __attribute__((__packed__)) {
|
||||
/**
|
||||
Address (or offset) in table.
|
||||
*/
|
||||
uint16_t addr;
|
||||
/**
|
||||
Type.
|
||||
*/
|
||||
gs_param_type_t type;
|
||||
/**
|
||||
Size of element.
|
||||
uint32_t = 4, string[5] = 5 (4 characters + 1 for NUL), etc.
|
||||
*/
|
||||
uint8_t size;
|
||||
/**
|
||||
Array size.
|
||||
Size greater than 1, will make the parameter an array - if the value is 0 or 1, the parameter is not an array.
|
||||
*/
|
||||
uint8_t array_size;
|
||||
/**
|
||||
Flags.
|
||||
@see gs_param_flags_t
|
||||
*/
|
||||
uint8_t flags;
|
||||
/**
|
||||
Name (C string).
|
||||
@note In some rare/old table definitions, the name may not be NUL terminated.
|
||||
*/
|
||||
char name[GS_PARAM_MAX_NAME];
|
||||
} gs_param_table_row_t;
|
||||
|
||||
/**
|
||||
Table instance.
|
||||
*/
|
||||
typedef struct gs_param_table_instance gs_param_table_instance_t;
|
||||
|
||||
/**
|
||||
Table id.
|
||||
|
||||
Tables can be associated with a number/id, which normally is unique on a specific node.
|
||||
*/
|
||||
typedef uint8_t gs_param_table_id_t;
|
||||
|
||||
/**
|
||||
Undefined table id.
|
||||
*/
|
||||
#define GS_PARAM_UNDEFINED_TABLE_ID 255
|
||||
|
||||
/**
|
||||
Function for setting a parameter.
|
||||
|
||||
@param[in] context user context/reference.
|
||||
@param[in] tinst table instance.
|
||||
@param[in] addr parameter address.
|
||||
@param[in] type parameter type.
|
||||
@param[in] item parameter value.
|
||||
@param[in] size parameter size (e.g. how many bytes to copy from \a item).
|
||||
@param[in] flags flags related to the operation - these may vary depending on the context.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
typedef gs_error_t (*gs_param_table_function_set_t)(void * context, gs_param_table_instance_t * tinst, uint16_t addr, gs_param_type_t type, const void * item, size_t size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Function for getting a parameter.
|
||||
|
||||
@param[in] context user context/reference.
|
||||
@param[in] tinst table instance.
|
||||
@param[in] addr parameter address.
|
||||
@param[in] type parameter type.
|
||||
@param[out] item parameter buffer (provided by the caller).
|
||||
@param[in] size parameter size (e.g. how many bytes to copy to \a item).
|
||||
@param[in] flags flags related to the operation - these may vary depending on the context.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
typedef gs_error_t (*gs_param_table_function_get_t)(void * context, gs_param_table_instance_t * tinst, uint16_t addr, gs_param_type_t type, void * item, size_t size, uint32_t flags);
|
||||
|
||||
/**
|
||||
Function interface for setting and getting parameters.
|
||||
Functions will be invoked, when set/get is called on the table instance.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
User context, provided in the callback functions.
|
||||
*/
|
||||
void * context;
|
||||
/**
|
||||
Called when setting a parameter.
|
||||
*/
|
||||
gs_param_table_function_set_t set;
|
||||
/**
|
||||
Called when getting a parameter.
|
||||
*/
|
||||
gs_param_table_function_get_t get;
|
||||
} gs_param_function_interface_t;
|
||||
|
||||
/**
|
||||
Callback function for changed parameter.
|
||||
See gs_param_table_create() for details.
|
||||
*/
|
||||
typedef void (*gs_param_callback_func_t)(uint16_t addr, gs_param_table_instance_t * tinst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
1084
gomspace/libparam_client/src/bindings/python/pyparam.c
Normal file
1084
gomspace/libparam_client/src/bindings/python/pyparam.c
Normal file
File diff suppressed because it is too large
Load Diff
418
gomspace/libparam_client/src/pp/cmd/master_cmd.c
Normal file
418
gomspace/libparam_client/src/pp/cmd/master_cmd.c
Normal file
@ -0,0 +1,418 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#include <gs/param/pp/spi/spi.h>
|
||||
#include <gs/param/pp/i2c/i2c.h>
|
||||
#include <gs/util/gosh/command.h>
|
||||
#include <gs/util/stdio.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/log.h>
|
||||
|
||||
static bool use_checksum;
|
||||
|
||||
static gs_pp_t gs_pp;
|
||||
|
||||
static int cmd_spi_init(gs_command_context_t *ctx)
|
||||
{
|
||||
uint8_t slave;
|
||||
gs_error_t error = gs_string_to_uint8(ctx->argv[1], &slave);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
bool big_endian = false;
|
||||
if (ctx->argc > 2) {
|
||||
error = gs_string_to_bool(ctx->argv[2], &big_endian);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
error = gs_pp_spi_init(&gs_pp, slave, big_endian);
|
||||
if (error) {
|
||||
memset(&gs_pp, 0, sizeof(gs_pp));
|
||||
return error;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_i2c_init(gs_command_context_t *ctx)
|
||||
{
|
||||
uint8_t bus;
|
||||
gs_error_t error = gs_string_to_uint8(ctx->argv[1], &bus);
|
||||
if (error) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
uint8_t addr;
|
||||
error = gs_string_to_uint8(ctx->argv[2], &addr);
|
||||
if (error) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
bool big_endian = false;
|
||||
if (ctx->argc > 3) {
|
||||
error = gs_string_to_bool(ctx->argv[3], &big_endian);
|
||||
if (error) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
error = gs_pp_i2c_init(&gs_pp, bus, addr, big_endian);
|
||||
if (error) {
|
||||
memset(&gs_pp, 0, sizeof(gs_pp));
|
||||
return error;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_checksum(gs_command_context_t *ctx)
|
||||
{
|
||||
if (ctx->argc > 1) {
|
||||
if (gs_string_to_bool(ctx->argv[1], &use_checksum)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
printf("Use CHECKSUM: %d\r\n", use_checksum);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
// get_xxxx <table> <addr>
|
||||
static int cmd_parse(gs_command_context_t *ctx,
|
||||
uint32_t * table, uint32_t * addr)
|
||||
{
|
||||
if (ctx->argc < 3) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
gs_error_t error = gs_string_to_uint32(ctx->argv[1], table);
|
||||
if (error || (*table > 7)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
error = gs_string_to_uint32(ctx->argv[2], addr);
|
||||
if (error || (*addr > 255)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_get_parse(gs_command_context_t * ctx,
|
||||
uint32_t * table, uint32_t * addr, uint32_t * count)
|
||||
{
|
||||
int res = cmd_parse(ctx, table, addr);
|
||||
if (res == GS_OK) {
|
||||
*count = 1;
|
||||
if (ctx->argc > 3) {
|
||||
gs_error_t error = gs_string_to_uint32(ctx->argv[3], count);
|
||||
if (error || (*count > 100)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define CMD_GET(_ctx, _type, _func, _format) \
|
||||
{ \
|
||||
uint32_t table; \
|
||||
uint32_t addr; \
|
||||
uint32_t count; \
|
||||
int res = cmd_get_parse(_ctx, &table, &addr, &count); \
|
||||
if (res == GS_OK) { \
|
||||
_type value[count]; \
|
||||
gs_error_t error = _func(&gs_pp, table, addr, value, count, use_checksum ? GS_PP_FLAG_CHECKSUM : 0); \
|
||||
if (error) { \
|
||||
return error; \
|
||||
} \
|
||||
printf("value(s): "); \
|
||||
for (unsigned int i = 0; i < count; ++i) { \
|
||||
printf("%" _format " ", value[i]); \
|
||||
} \
|
||||
printf("\r\n"); \
|
||||
} \
|
||||
return res; \
|
||||
}
|
||||
|
||||
static int cmd_get_int8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, int8_t, gs_pp_get_int8, PRId8);
|
||||
}
|
||||
|
||||
static int cmd_get_int16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, int16_t, gs_pp_get_int16, PRId16);
|
||||
}
|
||||
|
||||
static int cmd_get_int32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, int32_t, gs_pp_get_int32, PRId32);
|
||||
}
|
||||
|
||||
static int cmd_get_uint8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, uint8_t, gs_pp_get_uint8, PRIu8);
|
||||
}
|
||||
|
||||
static int cmd_get_uint16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, uint16_t, gs_pp_get_uint16, PRIu16);
|
||||
}
|
||||
|
||||
static int cmd_get_uint32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, uint32_t, gs_pp_get_uint32, PRIu32);
|
||||
}
|
||||
|
||||
static int cmd_get_float(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_GET(ctx, float, gs_pp_get_float, "f");
|
||||
}
|
||||
|
||||
#define CMD_SET(_ctx, _type, _func, _convert) \
|
||||
{ \
|
||||
const unsigned int MAX_VALUES = 20; \
|
||||
uint32_t table; \
|
||||
uint32_t addr; \
|
||||
int res = cmd_parse(_ctx, &table, &addr); \
|
||||
if (res == GS_OK) { \
|
||||
_type value[MAX_VALUES]; \
|
||||
unsigned int count = 0; \
|
||||
for (int i = 3; (i < _ctx->argc) && (count < MAX_VALUES); ++i, ++count) { \
|
||||
res = _convert(_ctx->argv[i], &value[count]); \
|
||||
if (res) { \
|
||||
return GS_ERROR_DATA; \
|
||||
} \
|
||||
} \
|
||||
res = _func(&gs_pp, table, addr, value, count, use_checksum ? GS_PP_FLAG_CHECKSUM : 0); \
|
||||
} \
|
||||
return res; \
|
||||
}
|
||||
|
||||
static int cmd_set_int8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, int8_t, gs_pp_set_int8, gs_string_to_int8);
|
||||
}
|
||||
|
||||
static int cmd_set_int16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, int16_t, gs_pp_set_int16, gs_string_to_int16);
|
||||
}
|
||||
|
||||
static int cmd_set_int32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, int32_t, gs_pp_set_int32, gs_string_to_int32);
|
||||
}
|
||||
|
||||
static int cmd_set_uint8(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, uint8_t, gs_pp_set_uint8, gs_string_to_uint8);
|
||||
}
|
||||
|
||||
static int cmd_set_uint16(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, uint16_t, gs_pp_set_uint16, gs_string_to_uint16);
|
||||
}
|
||||
|
||||
static int cmd_set_uint32(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, uint32_t, gs_pp_set_uint32, gs_string_to_uint32);
|
||||
}
|
||||
|
||||
static int cmd_set_float(gs_command_context_t * ctx)
|
||||
{
|
||||
CMD_SET(ctx, float, gs_pp_set_float, gs_string_to_float);
|
||||
}
|
||||
|
||||
static int cmd_get_table_lock(gs_command_context_t * ctx)
|
||||
{
|
||||
uint32_t table;
|
||||
gs_error_t res = gs_string_to_uint32(ctx->argv[1], &table);
|
||||
if (res == GS_OK) {
|
||||
if (table <= 7) {
|
||||
bool lock;
|
||||
res = gs_pp_get_table_lock(&gs_pp, table, &lock, GS_PP_FLAG_CHECKSUM);
|
||||
if (res == GS_OK) {
|
||||
const char locked[] = "locked\n";
|
||||
const char unlocked[] = "unlocked\n";
|
||||
const char * lock_state = (lock) ? locked : unlocked;
|
||||
printf("Table %s", lock_state);
|
||||
}
|
||||
} else {
|
||||
res = GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int cmd_set_table_lock(gs_command_context_t * ctx)
|
||||
{
|
||||
uint32_t table;
|
||||
gs_error_t res = gs_string_to_uint32(ctx->argv[1], &table);
|
||||
if (res == GS_OK) {
|
||||
if (table <= 7) {
|
||||
uint32_t lock;
|
||||
res = gs_string_to_uint32(ctx->argv[2], &lock);
|
||||
if (res == GS_OK) {
|
||||
if(lock <= 1) {
|
||||
res = gs_pp_set_table_lock(&gs_pp, table, (bool *)&lock, GS_PP_FLAG_CHECKSUM);
|
||||
} else {
|
||||
res = GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static const gs_command_t gs_param_cmd_master_pp_sub[] = {
|
||||
{
|
||||
.name = "spi_init",
|
||||
.help = "Initialize/setup SPI device",
|
||||
.usage = "<slave> [big_endian]",
|
||||
.handler = cmd_spi_init,
|
||||
.mandatory_args = 1,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "i2c_init",
|
||||
.help = "Initialize/setup I2C device",
|
||||
.usage = "<device> <addr> [big_endian]",
|
||||
.handler = cmd_i2c_init,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "checksum",
|
||||
.help = "Enable/disable checksum",
|
||||
.usage = "[0|1]",
|
||||
.handler = cmd_checksum,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_table_lock",
|
||||
.help = "Get table lock (0 = unlocked, 1 = locked)",
|
||||
.usage = "<table>",
|
||||
.mandatory_args = 1,
|
||||
.handler = cmd_get_table_lock,
|
||||
},{
|
||||
.name = "set_table_lock",
|
||||
.help = "Set table lock (0 = unlocked, 1 = locked)",
|
||||
.usage = "<table> <lock/unlock>",
|
||||
.mandatory_args = 2,
|
||||
.handler = cmd_set_table_lock,
|
||||
},{
|
||||
.name = "get_int8",
|
||||
.help = "Get int8",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_int8,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_int16",
|
||||
.help = "Get int16",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_int16,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_int32",
|
||||
.help = "Get int32",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_int32,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_uint8",
|
||||
.help = "Get uint8",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_uint8,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_uint16",
|
||||
.help = "Get uint16",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_uint16,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_uint32",
|
||||
.help = "Get uint32",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_uint32,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "get_float",
|
||||
.help = "Get float",
|
||||
.usage = "<table> <addr> [count]",
|
||||
.handler = cmd_get_float,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "set_int8",
|
||||
.help = "Set int8",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_int8,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_int16",
|
||||
.help = "Set int16",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_int16,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_int32",
|
||||
.help = "Set int32",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_int32,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_uint8",
|
||||
.help = "Set uint8",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_uint8,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_uint16",
|
||||
.help = "Set uint16",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_uint16,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_uint32",
|
||||
.help = "Set uint32",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_uint32,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
},{
|
||||
.name = "set_float",
|
||||
.help = "Set float",
|
||||
.usage = "<table> <addr> <data> [data] ...",
|
||||
.handler = cmd_set_float,
|
||||
.mandatory_args = 3,
|
||||
.optional_args = 20,
|
||||
}
|
||||
};
|
||||
|
||||
static const gs_command_t GS_COMMAND_ROOT gs_param_cmd_master_pp[] = {
|
||||
{
|
||||
.name = "pp",
|
||||
.help = "Param Protocol interface",
|
||||
.chain = GS_COMMAND_INIT_CHAIN(gs_param_cmd_master_pp_sub),
|
||||
}
|
||||
};
|
||||
|
||||
gs_error_t gs_pp_register_commands(void)
|
||||
{
|
||||
return GS_COMMAND_REGISTER(gs_param_cmd_master_pp);
|
||||
}
|
129
gomspace/libparam_client/src/pp/i2c/i2c.c
Normal file
129
gomspace/libparam_client/src/pp/i2c/i2c.c
Normal file
@ -0,0 +1,129 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/pp/i2c/i2c.h>
|
||||
#include <gs/util/drivers/i2c/master.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <alloca.h>
|
||||
|
||||
static gs_error_t gs_pp_i2c_write(gs_param_i2c_command_t cmd, gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, bool checksum)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
GS_CHECK_RANGE((value_size > 0) && (value_size <= 31));
|
||||
|
||||
gs_param_i2c_set_request_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size + (checksum ? 1 : 0));
|
||||
request = alloca(size);
|
||||
|
||||
request->header.domain_command = GS_I2C_SLAVE_DISPATCH_HEADER(GS_I2C_SLAVE_DISPATCH_DOMAIN_PARAM, cmd);
|
||||
request->length_table = GS_PARAM_I2C_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
memcpy(request->data, value, value_size);
|
||||
|
||||
if (checksum) {
|
||||
request->data[value_size] = gs_pp_checksum8(request, size - 1);
|
||||
}
|
||||
return gs_i2c_master_transaction(pp->pp.i2c.bus, pp->pp.i2c.addr, request, size, NULL, 0, 1000);
|
||||
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_read(gs_param_i2c_command_t cmd, gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, bool checksum)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
GS_CHECK_RANGE((value_size > 0) && (value_size <= 31));
|
||||
|
||||
gs_param_i2c_get_request_t request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.length_table = GS_PARAM_I2C_LENGTH_TABLE(value_size, table_id);
|
||||
request.addr = addr;
|
||||
size_t request_size;
|
||||
|
||||
uint8_t reply[value_size + sizeof(request.checksum)]; // + for checksum
|
||||
memset(reply, 0, sizeof(reply));
|
||||
size_t reply_size;
|
||||
|
||||
request.header.domain_command = GS_I2C_SLAVE_DISPATCH_HEADER(GS_I2C_SLAVE_DISPATCH_DOMAIN_PARAM, cmd);
|
||||
|
||||
if (checksum) {
|
||||
request.checksum = gs_pp_checksum8(&request, (sizeof(request) - sizeof(request.checksum)));
|
||||
request_size = sizeof(request);
|
||||
reply_size = sizeof(reply);
|
||||
} else {
|
||||
request_size = sizeof(request) - sizeof(request.checksum);
|
||||
reply_size = sizeof(reply) - sizeof(request.checksum);
|
||||
}
|
||||
|
||||
gs_error_t error = gs_i2c_master_transaction(pp->pp.i2c.bus, pp->pp.i2c.addr, &request, request_size, reply, reply_size, 1000);
|
||||
if (error == GS_OK) {
|
||||
if (checksum) {
|
||||
if (gs_pp_checksum8(reply, value_size) != reply[value_size]) {
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
memcpy(value, reply, value_size);
|
||||
}
|
||||
return error;
|
||||
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_get(gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd;
|
||||
bool checksum = false;
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
checksum = true;
|
||||
cmd = GS_PARAM_I2C_COMMAND_GET_WITH_CHECKSUM;
|
||||
} else {
|
||||
cmd = GS_PARAM_I2C_COMMAND_GET;
|
||||
}
|
||||
return gs_pp_i2c_read(cmd, pp, table_id, addr, value, value_size, checksum);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_set(gs_pp_t * pp, uint8_t table_id, uint16_t addr, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd;
|
||||
bool checksum = false;
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
checksum = true;
|
||||
cmd = GS_PARAM_I2C_COMMAND_SET_WITH_CHECKSUM;
|
||||
} else {
|
||||
cmd = GS_PARAM_I2C_COMMAND_SET;
|
||||
}
|
||||
return gs_pp_i2c_write(cmd, pp, table_id, addr, (void *)value, value_size, checksum);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_set_table_lock(gs_pp_t * pp, uint8_t table_id, const bool * value, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd = GS_PARAM_I2C_COMMAND_SET_LOCK_WITH_CHECKSUM;
|
||||
bool checksum = true;
|
||||
return gs_pp_i2c_write(cmd, pp, table_id, 0, (void *)value, 1, checksum);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_i2c_get_table_lock(gs_pp_t * pp, uint8_t table_id, bool * value, uint32_t flags)
|
||||
{
|
||||
gs_param_i2c_command_t cmd = GS_PARAM_I2C_COMMAND_GET_LOCK_WITH_CHECKSUM;
|
||||
bool checksum = true;
|
||||
return gs_pp_i2c_read(cmd, pp, table_id, 0, value, 1, checksum);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_i2c_init(gs_pp_t * pp, uint8_t bus, uint8_t addr, bool big_endian)
|
||||
{
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
|
||||
memset(pp, 0, sizeof(*pp));
|
||||
|
||||
pp->get = gs_pp_i2c_get;
|
||||
pp->set = gs_pp_i2c_set;
|
||||
pp->set_table_lock = gs_pp_i2c_set_table_lock;
|
||||
pp->get_table_lock = gs_pp_i2c_get_table_lock;
|
||||
pp->big_endian = big_endian;
|
||||
|
||||
pp->pp.i2c.bus = bus;
|
||||
pp->pp.i2c.addr = addr;
|
||||
|
||||
return GS_OK;
|
||||
}
|
189
gomspace/libparam_client/src/pp/pp.c
Normal file
189
gomspace/libparam_client/src/pp/pp.c
Normal file
@ -0,0 +1,189 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#include <gs/param/pp/pp.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <gs/util/byteorder.h>
|
||||
#include <gs/util/endian.h>
|
||||
|
||||
static inline bool gs_pp_endian_convert(gs_pp_t * pp)
|
||||
{
|
||||
return (pp && (pp->big_endian != gs_endian_big()));
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_get(gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
if (pp == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (pp->get == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->get(pp, table_id, addr, value, value_size, flags);
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_set(gs_pp_t * pp, uint8_t table_id, uint16_t addr, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
if (pp == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (pp->set == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->set(pp, table_id, addr, value, value_size, flags);
|
||||
}
|
||||
|
||||
uint8_t gs_pp_checksum8(const void * data_in, size_t length)
|
||||
{
|
||||
const uint8_t * data = data_in;
|
||||
unsigned int checksum = 0;
|
||||
for (unsigned int i = 0; i < length; ++i) {
|
||||
checksum += *data++;
|
||||
}
|
||||
checksum &= 0xff;
|
||||
return checksum ? checksum : 1;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_get_table_lock(gs_pp_t * pp, uint8_t table_id, bool * value, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
if (pp->get_table_lock == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->get_table_lock(pp, table_id, value, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_table_lock(gs_pp_t * pp, uint8_t table_id, const bool * value, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
if (pp->set_table_lock == NULL) {
|
||||
return GS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return pp->set_table_lock(pp, table_id, value, flags);
|
||||
}
|
||||
|
||||
// int8_t
|
||||
gs_error_t gs_pp_get_int8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_get_uint8(pp, table_id, addr, (uint8_t *) value, count, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_int8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_set_uint8(pp, table_id, addr, (const uint8_t *) value, count, flags);
|
||||
}
|
||||
|
||||
// uint8_t
|
||||
|
||||
gs_error_t gs_pp_get_uint8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
return gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_uint8(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint8_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
// int16_t
|
||||
|
||||
gs_error_t gs_pp_get_int16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_get_uint16(pp, table_id, addr, (uint16_t *) value, count, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_int16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_set_uint16(pp, table_id, addr, (const uint16_t *) value, count, flags);
|
||||
}
|
||||
|
||||
// uint16_t
|
||||
|
||||
gs_error_t gs_pp_get_uint16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
gs_error_t error = gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_16_array(value, value, count);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_uint16(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint16_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
uint16_t _converted[count];
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_16_array(value, _converted, count);
|
||||
value = _converted;
|
||||
}
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
// int32_t
|
||||
|
||||
gs_error_t gs_pp_get_int32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, int32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_get_uint32(pp, table_id, addr, (uint32_t *) value, count, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_int32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const int32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
return gs_pp_set_uint32(pp, table_id, addr, (const uint32_t *) value, count, flags);
|
||||
}
|
||||
|
||||
// uint32_t
|
||||
|
||||
gs_error_t gs_pp_get_uint32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, uint32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
gs_error_t error = gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_32_array(value, value, count);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_uint32(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const uint32_t * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
uint32_t _converted[count];
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_32_array(value, _converted, count);
|
||||
value = _converted;
|
||||
}
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_get_float(gs_pp_t * pp, uint8_t table_id, uint8_t addr, float * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
gs_error_t error = gs_pp_get(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_float_array(value, value, count);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_set_float(gs_pp_t * pp, uint8_t table_id, uint8_t addr, const float * value, size_t count, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_ARG(value != NULL);
|
||||
GS_CHECK_ARG(count > 0);
|
||||
float _converted[count];
|
||||
if (gs_pp_endian_convert(pp)) {
|
||||
gs_bswap_float_array(value, _converted, count);
|
||||
value = _converted;
|
||||
}
|
||||
return gs_pp_set(pp, table_id, addr, value, (sizeof(*value) * count), flags);
|
||||
}
|
91
gomspace/libparam_client/src/pp/spi/spi.c
Normal file
91
gomspace/libparam_client/src/pp/spi/spi.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/pp/spi/spi.h>
|
||||
#include <gs/util/drivers/spi/master.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <alloca.h>
|
||||
|
||||
static gs_error_t gs_pp_spi_get(gs_pp_t * pp, uint8_t table_id, uint16_t addr, void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
gs_param_spi_get_with_checksum_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size + 1); // +1 for CHECKSUM in returned data
|
||||
request = alloca(size);
|
||||
memset(request, 0, size);
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_GET_WITH_CHECKSUM);
|
||||
request->length_table = GS_PARAM_SPI_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
request->checksum = gs_pp_checksum8(request, (sizeof(*request) - sizeof(request->filler)));
|
||||
|
||||
gs_error_t error = gs_spi_master_transaction(pp->pp.spi.slave, request, request, size, 1000);
|
||||
if (error == GS_OK) {
|
||||
if (gs_pp_checksum8(request->data, value_size) != request->data[value_size]) {
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
memcpy(value, request->data, value_size);
|
||||
}
|
||||
return error;
|
||||
|
||||
} else {
|
||||
gs_param_spi_get_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size);
|
||||
request = alloca(size);
|
||||
memset(request, 0, size);
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_GET);
|
||||
request->length_table = GS_PARAM_SPI_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
|
||||
gs_error_t error = gs_spi_master_transaction(pp->pp.spi.slave, request, request, size, 1000);
|
||||
if (error == GS_OK) {
|
||||
memcpy(value, request->data, value_size);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
static gs_error_t gs_pp_spi_set(gs_pp_t * pp, uint8_t table_id, uint16_t addr, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
GS_CHECK_RANGE(table_id <= 7);
|
||||
GS_CHECK_RANGE(addr <= 255);
|
||||
|
||||
gs_param_spi_set_t * request;
|
||||
const size_t size = (sizeof(*request) + value_size + ((flags & GS_PP_FLAG_CHECKSUM) ? 1 : 0));
|
||||
request = alloca(size);
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_SET_WITH_CHECKSUM);
|
||||
} else {
|
||||
request->header.domain_command = GS_SPI_SLAVE_DISPATCH_HEADER(GS_SPI_SLAVE_DISPATCH_DOMAIN_PARAM, GS_PARAM_SPI_COMMAND_SET);
|
||||
}
|
||||
request->length_table = GS_PARAM_SPI_LENGTH_TABLE(value_size, table_id);
|
||||
request->addr = addr;
|
||||
memcpy(request->data, value, value_size);
|
||||
|
||||
if (flags & GS_PP_FLAG_CHECKSUM) {
|
||||
request->data[value_size] = gs_pp_checksum8(request, size - 1);
|
||||
}
|
||||
|
||||
return gs_spi_master_transaction(pp->pp.spi.slave, request, NULL, size, 1000);
|
||||
}
|
||||
|
||||
gs_error_t gs_pp_spi_init(gs_pp_t * pp, uint8_t slave, bool big_endian)
|
||||
{
|
||||
GS_CHECK_HANDLE(pp != NULL);
|
||||
|
||||
memset(pp, 0, sizeof(*pp));
|
||||
|
||||
pp->get = gs_pp_spi_get;
|
||||
pp->set = gs_pp_spi_set;
|
||||
pp->set_table_lock = NULL; // Not implemented
|
||||
pp->get_table_lock = NULL; // Not implemented
|
||||
pp->big_endian = big_endian;
|
||||
|
||||
pp->pp.spi.slave = slave;
|
||||
|
||||
return GS_OK;
|
||||
}
|
354
gomspace/libparam_client/src/rparam/cmd/cmd_rparam.c
Normal file
354
gomspace/libparam_client/src/rparam/cmd/cmd_rparam.c
Normal file
@ -0,0 +1,354 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/rparam.h>
|
||||
#include <gs/param/internal/table.h>
|
||||
#include <gs/param/internal/serialize.h>
|
||||
#include <gs/param/internal/types.h>
|
||||
#include "../query.h"
|
||||
#include <gs/util/log.h>
|
||||
#include <gs/util/gosh/command.h>
|
||||
#include <gs/util/stdio.h>
|
||||
#include <gs/util/unistd.h>
|
||||
#include <gs/csp/csp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAX_FILENAME 100
|
||||
|
||||
/** Remote param system setup */
|
||||
static gs_param_table_instance_t rparam_tinst;
|
||||
static gs_rparam_query_handle_t rquery = {.timeout_ms = 10000};
|
||||
static char * rparam_wd;
|
||||
|
||||
#define CHECK_TABLE() \
|
||||
if (rparam_tinst.rows == NULL) { \
|
||||
fprintf(ctx->out, "Run download or init to setup table\n"); \
|
||||
return GS_ERROR_NOT_FOUND; \
|
||||
}
|
||||
|
||||
static int cmd_rparam_list(gs_command_context_t *ctx)
|
||||
{
|
||||
CHECK_TABLE();
|
||||
return gs_param_list_to_stream(&rparam_tinst, true, 0, ctx->out);
|
||||
}
|
||||
|
||||
static void make_filename(char * fname, size_t fname_size)
|
||||
{
|
||||
char cwd[MAX_FILENAME + 1];
|
||||
const char * wd;
|
||||
if (gs_string_empty(rparam_wd) == false) {
|
||||
wd = rparam_wd;
|
||||
} else if (gs_getcwd(cwd, sizeof(cwd)) == GS_OK) {
|
||||
wd = cwd;
|
||||
} else {
|
||||
wd = NULL;
|
||||
}
|
||||
if (gs_string_empty(wd) == false) {
|
||||
snprintf(fname, fname_size, "%s/param-%d-%u.bin", wd, rquery.node, rquery.table_id);
|
||||
} else {
|
||||
fname[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int cmd_rparam_init_from_local_file(gs_command_context_t *ctx)
|
||||
{
|
||||
if (gs_string_to_uint8(ctx->argv[1], &rquery.node)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
if (ctx->argc > 2) {
|
||||
if (gs_string_to_uint8(ctx->argv[2], &rquery.table_id)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
char fname[100];
|
||||
make_filename(fname, sizeof(fname));
|
||||
return gs_rparam_load_table_spec(&rparam_tinst, fname, &rquery.checksum);
|
||||
}
|
||||
|
||||
static int cmd_rparam_init_from_remote_node(gs_command_context_t *ctx)
|
||||
{
|
||||
if (gs_string_to_uint8(ctx->argv[1], &rquery.node)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
if (ctx->argc > 2) {
|
||||
if (gs_string_to_uint8(ctx->argv[2], &rquery.table_id)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
char fname[100];
|
||||
make_filename(fname, sizeof(fname));
|
||||
return gs_rparam_download_table_spec(&rparam_tinst, fname, rquery.node, rquery.table_id, rquery.timeout_ms, &rquery.checksum);
|
||||
}
|
||||
|
||||
static int cmd_rparam_send(gs_command_context_t *ctx)
|
||||
{
|
||||
CHECK_TABLE();
|
||||
|
||||
gs_error_t error = gs_rparam_query_send(&rquery, &rparam_tinst);
|
||||
if (error == GS_OK) {
|
||||
if (rquery.action == RPARAM_GET) {
|
||||
const gs_param_table_row_t * last_print = NULL;
|
||||
for (unsigned int i = 0; i < rquery.length / 2; ++i) {
|
||||
const gs_param_table_row_t * row = gs_param_row_by_address(rquery.payload.addr[i], rparam_tinst.rows, rparam_tinst.row_count);
|
||||
if (row != last_print) { // work-around to avoid duplicate lines for elements within same array
|
||||
gs_param_list_single_to_stream(&rparam_tinst, row, true, 0, ctx->out);
|
||||
last_print = row;
|
||||
}
|
||||
}
|
||||
}
|
||||
gs_rparam_query_reset(&rquery);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cmd_rparam_get(gs_command_context_t *ctx)
|
||||
{
|
||||
CHECK_TABLE();
|
||||
|
||||
gs_rparam_query_set_quiet(&rquery, false);
|
||||
gs_error_t error = gs_rparam_query_get(&rquery, &rparam_tinst, ctx->argv[1]);
|
||||
if ((error == GS_OK) && rquery.auto_send) {
|
||||
error = cmd_rparam_send(ctx);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cmd_rparam_getall(gs_command_context_t *ctx)
|
||||
{
|
||||
CHECK_TABLE();
|
||||
|
||||
fprintf(ctx->out, "Downloading table content for table %i from server %u\n", rquery.table_id, rquery.node);
|
||||
gs_error_t error = gs_rparam_get_full_table(&rparam_tinst, rquery.node, rquery.table_id, rquery.checksum, rquery.timeout_ms);
|
||||
if (error == GS_OK) {
|
||||
gs_param_list_to_stream(&rparam_tinst, true, 0, ctx->out);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cmd_rparam_set(gs_command_context_t *ctx)
|
||||
{
|
||||
CHECK_TABLE();
|
||||
|
||||
gs_error_t error = gs_rparam_query_set(&rquery, &rparam_tinst, ctx->argv[1], &ctx->argv[2], ctx->argc - 2);
|
||||
if ((error == GS_OK) && rquery.auto_send) {
|
||||
error = cmd_rparam_send(ctx);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int cmd_rparam_copy(gs_command_context_t *ctx)
|
||||
{
|
||||
uint8_t from;
|
||||
if (gs_string_to_uint8(ctx->argv[1], &from)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
uint8_t to;
|
||||
if (gs_string_to_uint8(ctx->argv[2], &to)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
return gs_rparam_copy(rquery.node, rquery.timeout_ms, from, to);
|
||||
}
|
||||
|
||||
static int cmd_rparam_load(gs_command_context_t *ctx)
|
||||
{
|
||||
uint8_t table_id;
|
||||
if (gs_string_to_uint8(ctx->argv[2], &table_id)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
uint8_t file_id;
|
||||
if (gs_string_to_uint8(ctx->argv[1], &file_id)) {
|
||||
// This may be a store - no way of validating
|
||||
return gs_rparam_load_from_store(rquery.node, rquery.timeout_ms, table_id, ctx->argv[1], NULL);
|
||||
}
|
||||
|
||||
return gs_rparam_load(rquery.node, rquery.timeout_ms, file_id, table_id);
|
||||
}
|
||||
|
||||
static int cmd_rparam_save(gs_command_context_t *ctx)
|
||||
{
|
||||
uint8_t table_id;
|
||||
if (gs_string_to_uint8(ctx->argv[1], &table_id)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
uint8_t file_id;
|
||||
if (gs_string_to_uint8(ctx->argv[2], &file_id)) {
|
||||
// This may be a store - no way of validating
|
||||
return gs_rparam_save_to_store(rquery.node, rquery.timeout_ms, table_id, ctx->argv[2], NULL);
|
||||
}
|
||||
|
||||
return gs_rparam_save(rquery.node, rquery.timeout_ms, table_id, file_id);
|
||||
}
|
||||
|
||||
static int cmd_rparam_reset(gs_command_context_t *ctx)
|
||||
{
|
||||
gs_rparam_query_reset(&rquery);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_rparam_set_autosend(gs_command_context_t *ctx)
|
||||
{
|
||||
if (ctx->argc > 1) {
|
||||
if (gs_string_to_bool(ctx->argv[1], &rquery.auto_send)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
fprintf(ctx->out, "auto send: %d\r\n", rquery.auto_send);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_set_wd(gs_command_context_t *ctx)
|
||||
{
|
||||
if (ctx->argc > 1) {
|
||||
if (rparam_wd == NULL) {
|
||||
rparam_wd = malloc(MAX_FILENAME + 1);
|
||||
if (rparam_wd == NULL) {
|
||||
return GS_ERROR_ALLOC;
|
||||
}
|
||||
}
|
||||
strcpy(rparam_wd, ctx->argv[1]);
|
||||
}
|
||||
fprintf(ctx->out, "working directory: %s\r\n", rparam_wd ? rparam_wd : "not set");
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_rparam_set_timeout(gs_command_context_t *ctx)
|
||||
{
|
||||
if (ctx->argc > 1) {
|
||||
if (gs_string_to_uint32(ctx->argv[1], &rquery.timeout_ms)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
fprintf(ctx->out, "timeout: %"PRIu32" mS\r\n", rquery.timeout_ms);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static int cmd_rparam_set_checksum(gs_command_context_t *ctx)
|
||||
{
|
||||
if (ctx->argc > 1) {
|
||||
if (strcasecmp(ctx->argv[1], "magic") == 0) {
|
||||
rquery.checksum = GS_RPARAM_MAGIC_CHECKSUM;
|
||||
} else if (gs_string_to_uint16(ctx->argv[1], &rquery.checksum)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
}
|
||||
fprintf(ctx->out, "checksum: 0x%04x (magic: 0x%04x)\r\n", rquery.checksum, GS_RPARAM_MAGIC_CHECKSUM);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static const gs_command_t rparam_commands[] = {
|
||||
{
|
||||
.name = "init",
|
||||
.help = "Set server and load table spec. from file",
|
||||
.usage = "<server> [table-id]",
|
||||
.handler = cmd_rparam_init_from_local_file,
|
||||
.mandatory_args = 1,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "download",
|
||||
.help = "Set server and download table spec.",
|
||||
.usage = "<server> [table-id]",
|
||||
.handler = cmd_rparam_init_from_remote_node,
|
||||
.mandatory_args = 1,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "getall",
|
||||
.help = "Download full table contents from server",
|
||||
.handler = cmd_rparam_getall,
|
||||
.mandatory_args = GS_COMMAND_NO_ARGS,
|
||||
},{
|
||||
.name = "list",
|
||||
.help = "Lists the table specification",
|
||||
.handler = cmd_rparam_list,
|
||||
.mandatory_args = GS_COMMAND_NO_ARGS,
|
||||
},{
|
||||
.name = "get",
|
||||
.help = "Add a 'get' to the current query transaction",
|
||||
.usage = "<name>",
|
||||
.handler = cmd_rparam_get,
|
||||
.mandatory_args = 1,
|
||||
},{
|
||||
.name = "set",
|
||||
.help = "Add a 'set' to the current query transaction",
|
||||
.usage = "<parameter> <value> [value] ...",
|
||||
.handler = cmd_rparam_set,
|
||||
.mandatory_args = 2,
|
||||
.optional_args = 100,
|
||||
},{
|
||||
.name = "copy",
|
||||
.usage = "<from table-id> <to table-id>",
|
||||
.help = "Copy table to table (version <= 3 only)",
|
||||
.handler = cmd_rparam_copy,
|
||||
.mandatory_args = 2,
|
||||
},{
|
||||
.name = "load",
|
||||
.usage = "<file-id|store> <table-id>",
|
||||
.help = "Load table",
|
||||
.handler = cmd_rparam_load,
|
||||
.mandatory_args = 2,
|
||||
},{
|
||||
.name = "save",
|
||||
.usage = "<table-id> <file-id|store>",
|
||||
.help = "Save table",
|
||||
.handler = cmd_rparam_save,
|
||||
.mandatory_args = 2,
|
||||
/* },{ */
|
||||
/* .name = "print", */
|
||||
/* .help = "Print the current query", */
|
||||
/* .handler = cmd_rparam_print, */
|
||||
/* .mandatory_args = GS_COMMAND_NO_ARGS, */
|
||||
},{
|
||||
.name = "reset",
|
||||
.help = "Reset the current query",
|
||||
.handler = cmd_rparam_reset,
|
||||
.mandatory_args = GS_COMMAND_NO_ARGS,
|
||||
},{
|
||||
.name = "send",
|
||||
.help = "Send the current query",
|
||||
.handler = cmd_rparam_send,
|
||||
.mandatory_args = GS_COMMAND_NO_ARGS,
|
||||
},{
|
||||
.name = "wd",
|
||||
.help = "Set working directory for init/download",
|
||||
.usage = "[path]",
|
||||
.handler = cmd_set_wd,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "timeout",
|
||||
.help = "Set timeout",
|
||||
.usage = "[timeout mS]",
|
||||
.handler = cmd_rparam_set_timeout,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "checksum",
|
||||
.help = "Set checksum",
|
||||
.usage = "[magic|<checksum>]",
|
||||
.handler = cmd_rparam_set_checksum,
|
||||
.optional_args = 1,
|
||||
},{
|
||||
.name = "autosend",
|
||||
.usage = "[bool]",
|
||||
.help = "Enable/disable autosend for set and get queries",
|
||||
.handler = cmd_rparam_set_autosend,
|
||||
.optional_args = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static const gs_command_t GS_COMMAND_ROOT rparam_root_command[] = {
|
||||
{
|
||||
.name = "rparam",
|
||||
.help = "Remote access to Parameter System",
|
||||
.chain = GS_COMMAND_INIT_CHAIN(rparam_commands),
|
||||
},
|
||||
};
|
||||
|
||||
gs_error_t gs_rparam_register_commands(void)
|
||||
{
|
||||
return GS_COMMAND_REGISTER(rparam_root_command);
|
||||
}
|
6
gomspace/libparam_client/src/rparam/deprecated_rparam.c
Normal file
6
gomspace/libparam_client/src/rparam/deprecated_rparam.c
Normal file
@ -0,0 +1,6 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#include <deprecated/param/rparam_client.h>
|
||||
|
||||
// Old deprecated API uses common data - making it not thread-safe.
|
||||
//gs_rparam_handle_t rparam_handle;
|
212
gomspace/libparam_client/src/rparam/query.c
Normal file
212
gomspace/libparam_client/src/rparam/query.c
Normal file
@ -0,0 +1,212 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include "query.h"
|
||||
#include <gs/param/internal/rparam.h>
|
||||
#include <gs/param/internal/types.h>
|
||||
#include <gs/param/internal/table.h>
|
||||
#include "../serialize_local.h"
|
||||
#include <gs/csp/csp.h>
|
||||
#include <csp/csp_endian.h>
|
||||
|
||||
bool gs_rparam_query_is_set(gs_rparam_query_handle_t * handle)
|
||||
{
|
||||
return (handle->length > 0);
|
||||
}
|
||||
|
||||
void gs_rparam_query_reset(gs_rparam_query_handle_t * handle)
|
||||
{
|
||||
handle->action = RPARAM_GET;
|
||||
handle->length = 0;
|
||||
handle->get_size = 0;
|
||||
}
|
||||
|
||||
void gs_rparam_query_set_quiet(gs_rparam_query_handle_t * handle, bool quiet)
|
||||
{
|
||||
handle->quiet = quiet;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_query_get(gs_rparam_query_handle_t * handle, gs_param_table_instance_t * tinst, const char* param_name)
|
||||
{
|
||||
if (tinst->rows == NULL)
|
||||
return GS_ERROR_NOT_FOUND;
|
||||
|
||||
/* Ensure correct header */
|
||||
if (handle->action != RPARAM_GET) {
|
||||
gs_rparam_query_reset(handle);
|
||||
handle->action = RPARAM_GET;
|
||||
}
|
||||
|
||||
char shortname[GS_PARAM_MAX_NAME + 20];
|
||||
uint8_t array_index = 0;
|
||||
bool is_array;
|
||||
if (gs_param_parse_name_and_array_index(param_name, shortname, sizeof(shortname), &array_index, &is_array)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * param = gs_param_row_by_name(shortname, tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (array_index >= GS_PARAM_ARRAY_SIZE(param)) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
if (is_array) {
|
||||
start = array_index;
|
||||
end = start + 1;
|
||||
} else {
|
||||
start = 0;
|
||||
end = GS_PARAM_ARRAY_SIZE(param);
|
||||
}
|
||||
for (unsigned int i = start; i < end; ++i) {
|
||||
|
||||
/* Size check */
|
||||
if (handle->get_size + param->size + sizeof(uint16_t) > GS_RPARAM_QUERY_MAX_PAYLOAD) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Add to query */
|
||||
handle->payload.addr[handle->length/2] = param->addr + (param->size * i);
|
||||
handle->length += sizeof(uint16_t);
|
||||
handle->get_size += param->size + sizeof(uint16_t);
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_query_set(gs_rparam_query_handle_t * handle, gs_param_table_instance_t * tinst, const char* param_name, char * values[], uint8_t value_count)
|
||||
{
|
||||
/* Ensure correct header */
|
||||
if (handle->action != RPARAM_SET) {
|
||||
gs_rparam_query_reset(handle);
|
||||
handle->action = RPARAM_SET;
|
||||
}
|
||||
|
||||
char shortname[GS_PARAM_MAX_NAME + 20];
|
||||
uint8_t array_index = 0;
|
||||
if (gs_param_parse_name_and_array_index(param_name, shortname, sizeof(shortname), &array_index, NULL)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * param = gs_param_row_by_name(shortname, tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (array_index >= GS_PARAM_ARRAY_SIZE(param)) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < value_count; i++) {
|
||||
|
||||
/* Parse input */
|
||||
uint8_t value[param->size];
|
||||
gs_error_t error = gs_param_from_string(param, values[i], value);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
unsigned int bytes = 0;
|
||||
error = gs_param_serialize_item(param, param->addr + (param->size * (array_index + i)), value, F_TO_BIG_ENDIAN,
|
||||
&handle->payload.packed[handle->length], GS_RPARAM_QUERY_MAX_PAYLOAD - handle->length, &bytes);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
handle->length += bytes;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_query_send(gs_rparam_query_handle_t * handle, gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (tinst->rows == NULL) {
|
||||
return GS_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (handle->length == 0) {
|
||||
return GS_ERROR_NO_DATA;
|
||||
}
|
||||
|
||||
gs_rparam_query_t * query;
|
||||
|
||||
/* Allocate outgoing buffer */
|
||||
csp_packet_t * packet = csp_buffer_get(RPARAM_QUERY_LENGTH(query, GS_RPARAM_QUERY_MAX_PAYLOAD));
|
||||
if (packet == NULL) {
|
||||
return GS_ERROR_NO_BUFFERS;
|
||||
}
|
||||
|
||||
csp_conn_t * conn = csp_connect(CSP_PRIO_HIGH, handle->node, GS_CSP_PORT_RPARAM, handle->timeout_ms, CSP_O_CRC32);
|
||||
if (conn == NULL) {
|
||||
csp_buffer_free(packet);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
query = (gs_rparam_query_t *) packet->data;
|
||||
|
||||
query->action = handle->action;
|
||||
query->table_id = handle->table_id;
|
||||
query->seq = 0;
|
||||
query->total = 0;
|
||||
query->length = csp_hton16(handle->length);
|
||||
query->checksum = csp_hton16(handle->checksum);
|
||||
|
||||
/* Copy payload to message */
|
||||
packet->length = RPARAM_QUERY_LENGTH(query, handle->length);
|
||||
memcpy(&query->payload, &handle->payload, handle->length);
|
||||
|
||||
/* Deal with endianness */
|
||||
if (handle->action == RPARAM_GET) {
|
||||
for (unsigned int i = 0; i < (handle->length/2); i++) {
|
||||
query->payload.addr[i] = csp_hton16(query->payload.addr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send packet */
|
||||
if (!csp_send(conn, packet, 0)) {
|
||||
csp_buffer_free(packet);
|
||||
csp_close(conn);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
/* Read reply */
|
||||
packet = csp_read(conn, handle->timeout_ms);
|
||||
if (packet == NULL) {
|
||||
csp_close(conn);
|
||||
return GS_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
if (packet->length <= 1) {
|
||||
gs_error_t error = GS_OK;
|
||||
if (packet->length == 1) {
|
||||
if (packet->data[0] == RPARAM_ERROR) {
|
||||
error = GS_ERROR_DATA;
|
||||
}
|
||||
} else {
|
||||
error = GS_ERROR_NO_DATA;
|
||||
}
|
||||
csp_buffer_free(packet);
|
||||
csp_close(conn);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* We have a reply */
|
||||
gs_rparam_query_t * reply = (gs_rparam_query_t *) packet->data;
|
||||
reply->length = csp_ntoh16(reply->length);
|
||||
|
||||
gs_error_t error;
|
||||
if (reply->action == RPARAM_REPLY) {
|
||||
error = gs_param_deserialize(tinst, reply->payload.packed, reply->length, F_FROM_BIG_ENDIAN);
|
||||
} else {
|
||||
error = GS_ERROR_TYPE;
|
||||
}
|
||||
|
||||
csp_buffer_free(packet);
|
||||
csp_close(conn);
|
||||
return error;
|
||||
}
|
110
gomspace/libparam_client/src/rparam/query.h
Normal file
110
gomspace/libparam_client/src/rparam/query.h
Normal file
@ -0,0 +1,110 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
|
||||
#include <gs/param/internal/rparam.h>
|
||||
|
||||
/**
|
||||
Rparam query handle.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
CSP node.
|
||||
*/
|
||||
uint8_t node;
|
||||
/**
|
||||
Remote table id.
|
||||
*/
|
||||
gs_param_table_id_t table_id;
|
||||
/**
|
||||
Remote table (definition) checksum.
|
||||
*/
|
||||
uint16_t checksum;
|
||||
/**
|
||||
Timeout (mS).
|
||||
*/
|
||||
uint32_t timeout_ms;
|
||||
/**
|
||||
If quite - no output to stdout.
|
||||
*/
|
||||
bool quiet;
|
||||
/**
|
||||
Auto send.
|
||||
*/
|
||||
bool auto_send;
|
||||
/**
|
||||
Type/action.
|
||||
*/
|
||||
int action;
|
||||
/**
|
||||
Size of current query.
|
||||
*/
|
||||
unsigned int length;
|
||||
/**
|
||||
Estimated total 'get' size.
|
||||
*/
|
||||
unsigned int get_size;
|
||||
/**
|
||||
Space for payload data.
|
||||
@note must be last in struct.
|
||||
*/
|
||||
union {
|
||||
uint16_t addr[0];
|
||||
uint8_t packed[GS_RPARAM_QUERY_MAX_PAYLOAD];
|
||||
} payload;
|
||||
} gs_rparam_query_handle_t;
|
||||
|
||||
/**
|
||||
Set whether rparam API should print to stdout or not.
|
||||
|
||||
@param[in] handle handle
|
||||
@param[in] quiet \a true print to stdout.
|
||||
*/
|
||||
void gs_rparam_query_set_quiet(gs_rparam_query_handle_t * handle, bool quiet);
|
||||
|
||||
/**
|
||||
Return true if any query has been set.
|
||||
|
||||
@param[in] handle handle
|
||||
@return \a true if any query has been set.
|
||||
*/
|
||||
bool gs_rparam_query_is_set(gs_rparam_query_handle_t * handle);
|
||||
|
||||
/**
|
||||
Add a 'get' query to the current query, after a succesfull rparam_query_send()
|
||||
the parameter value can be read using rparam_queury_get_value()
|
||||
|
||||
@param[in] handle handle
|
||||
@param[in] tinst table.
|
||||
@param[in] param_name name of the parameter.
|
||||
@return_gs_error_t
|
||||
@see rparam_query_send()
|
||||
*/
|
||||
gs_error_t gs_rparam_query_get(gs_rparam_query_handle_t * handle, gs_param_table_instance_t * tinst, const char* param_name);
|
||||
|
||||
/**
|
||||
Add a 'set' query to the current query. Use rparam_query_send() to execute the set query.
|
||||
|
||||
@param[in] handle handle
|
||||
@param[in] tinst table.
|
||||
@param[in] param_name name of the parameter to set
|
||||
@param[in] values array of values to set, multiple values can be set for array type parameters
|
||||
@param[in] value_count number of elements in \a values
|
||||
@return_gs_error_t
|
||||
@see rparam_query_send()
|
||||
*/
|
||||
gs_error_t gs_rparam_query_set(gs_rparam_query_handle_t * handle, gs_param_table_instance_t * tinst, const char* param_name, char * values[], uint8_t value_count);
|
||||
|
||||
/**
|
||||
Send the current query
|
||||
|
||||
@param[in] handle handle
|
||||
@param[in] tinst table.
|
||||
@return_gs_error_t
|
||||
*/
|
||||
gs_error_t gs_rparam_query_send(gs_rparam_query_handle_t * handle, gs_param_table_instance_t * tinst);
|
||||
|
||||
/**
|
||||
Reset/clear the current query
|
||||
@param[in] handle handle
|
||||
*/
|
||||
void gs_rparam_query_reset(gs_rparam_query_handle_t * handle);
|
474
gomspace/libparam_client/src/rparam/rparam.c
Normal file
474
gomspace/libparam_client/src/rparam/rparam.c
Normal file
@ -0,0 +1,474 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/rparam.h>
|
||||
#include <gs/param/internal/types.h>
|
||||
#include <gs/param/internal/table.h>
|
||||
#include "../serialize_local.h"
|
||||
#include <stdio.h>
|
||||
#include <alloca.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <gs/csp/csp.h>
|
||||
#include <csp/csp_endian.h>
|
||||
#include <gs/util/log.h>
|
||||
#include <gs/util/fletcher.h>
|
||||
#include <gs/util/check.h>
|
||||
|
||||
static gs_error_t gs_rparam_command(uint8_t node, uint32_t timeout_ms, uint8_t action, uint8_t table_id,
|
||||
const void * payload, size_t payload_size, char reply_ok)
|
||||
{
|
||||
gs_rparam_query_t * query = alloca(RPARAM_QUERY_LENGTH(query, payload_size));
|
||||
query->action = action;
|
||||
query->table_id = table_id;
|
||||
query->length = csp_hton16(payload_size);
|
||||
query->checksum = csp_hton16(GS_RPARAM_MAGIC_CHECKSUM); // Ignore checksum
|
||||
query->seq = 0;
|
||||
query->total = 0;
|
||||
memcpy(&query->payload, payload, payload_size);
|
||||
|
||||
/* Run single packet transaction */
|
||||
char reply = 0;
|
||||
if (csp_transaction2(CSP_PRIO_HIGH, node, GS_CSP_PORT_RPARAM, timeout_ms, query, RPARAM_QUERY_LENGTH(query, payload_size),
|
||||
&reply, 1, CSP_O_CRC32) <= 0) {
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
return (reply == reply_ok) ? GS_OK : GS_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_copy(uint8_t node, uint32_t timeout_ms, uint8_t from, uint8_t to)
|
||||
{
|
||||
gs_rparam_query_payload_t payload;
|
||||
payload.copy.from = from;
|
||||
payload.copy.to = to;
|
||||
return gs_rparam_command(node, timeout_ms, RPARAM_COPY, from, &payload, sizeof(payload.copy), RPARAM_COPY_OK);
|
||||
}
|
||||
|
||||
static gs_error_t gs_rparam_store(uint8_t node, uint32_t timeout_ms, uint8_t action, char reply_ok, uint8_t table_id,
|
||||
const char * table, const char * store, const char * slot)
|
||||
{
|
||||
gs_rparam_query_payload_store_t payload;
|
||||
memset(&payload, 0, sizeof(payload));
|
||||
if (table && (gs_string_empty(table) == false)) {
|
||||
GS_STRNCPY(payload.table, table);
|
||||
}
|
||||
if (store && (gs_string_empty(store) == false)) {
|
||||
GS_STRNCPY(payload.store, store);
|
||||
}
|
||||
if (slot && (gs_string_empty(slot) == false)) {
|
||||
GS_STRNCPY(payload.slot, slot);
|
||||
}
|
||||
return gs_rparam_command(node, timeout_ms, action, table_id, &payload, sizeof(payload), reply_ok);
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_save_to_store(uint8_t node, uint32_t timeout_ms, uint8_t table_id,
|
||||
const char * store, const char * slot)
|
||||
{
|
||||
return gs_rparam_store(node, timeout_ms, RPARAM_SAVE_TO_STORE, RPARAM_SAVE_OK, table_id, NULL, store, slot);
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_load_from_store(uint8_t node, uint32_t timeout_ms, uint8_t table_id,
|
||||
const char * store, const char * slot)
|
||||
{
|
||||
return gs_rparam_store(node, timeout_ms, RPARAM_LOAD_FROM_STORE, RPARAM_LOAD_OK, table_id, NULL, store, slot);
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_save(uint8_t node, uint32_t timeout_ms, uint8_t from, uint8_t to)
|
||||
{
|
||||
gs_rparam_query_payload_t payload;
|
||||
payload.copy.from = from;
|
||||
payload.copy.to = to;
|
||||
return gs_rparam_command(node, timeout_ms, RPARAM_SAVE, from, &payload, sizeof(payload.copy), RPARAM_SAVE_OK);
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_load(uint8_t node, uint32_t timeout_ms, uint8_t from, uint8_t to)
|
||||
{
|
||||
gs_rparam_query_payload_t payload;
|
||||
payload.copy.from = from;
|
||||
payload.copy.to = to;
|
||||
return gs_rparam_command(node, timeout_ms, RPARAM_LOAD, to, &payload, sizeof(payload.copy), RPARAM_LOAD_OK);
|
||||
}
|
||||
|
||||
static gs_error_t update_table(const char * func,
|
||||
gs_param_table_instance_t * tinst,
|
||||
gs_param_table_row_t * rows, unsigned int row_count,
|
||||
uint16_t checksum)
|
||||
{
|
||||
size_t memory_size = gs_param_calc_table_size(rows, row_count);
|
||||
if ((tinst->memory == NULL) || (tinst->memory_size < memory_size)) {
|
||||
// (re)allocate memory
|
||||
if (memory_size == 0) {
|
||||
return GS_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
memory_size = gs_max(1000U, memory_size);
|
||||
void * memory = calloc(1, memory_size);
|
||||
if (memory == NULL) {
|
||||
return GS_ERROR_ALLOC;
|
||||
}
|
||||
|
||||
free(tinst->memory);
|
||||
tinst->memory = memory;
|
||||
tinst->memory_size = memory_size;
|
||||
tinst->flags |= GS_PARAM_TABLE_F_ALLOC_MEMORY;
|
||||
}
|
||||
|
||||
free((void*)tinst->rows);
|
||||
tinst->rows = rows;
|
||||
tinst->row_count = row_count;
|
||||
tinst->checksum_be = tinst->checksum_le = 0;
|
||||
tinst->flags |= GS_PARAM_TABLE_F_ALLOC_ROWS;
|
||||
|
||||
if ((checksum != gs_param_table_checksum_le(tinst)) && (checksum != gs_param_table_checksum_be(tinst))) {
|
||||
log_error("%s: table specification has invalid checksum: %u - different from LE: %u and BE: %u",
|
||||
func, checksum, gs_param_table_checksum_le(tinst), gs_param_table_checksum_be(tinst));
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_load_table_spec(gs_param_table_instance_t * tinst, const char* fname, uint16_t * return_checksum)
|
||||
{
|
||||
GS_CHECK_HANDLE(tinst != NULL);
|
||||
GS_CHECK_ARG(fname != NULL);
|
||||
|
||||
FILE * fd = fopen(fname, "r");
|
||||
if (fd == NULL) {
|
||||
return GS_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
struct stat file_stat;
|
||||
if (fstat(fileno(fd), &file_stat) != 0) {
|
||||
log_error("%s: failed to stat file [%s]", __FUNCTION__, fname);
|
||||
fclose(fd);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
void * rows = calloc(file_stat.st_size, 1);
|
||||
if (rows == NULL) {
|
||||
fclose(fd);
|
||||
return GS_ERROR_ALLOC;
|
||||
}
|
||||
|
||||
uint16_t checksum = 0;
|
||||
size_t rs1 = fread(&checksum, 1, sizeof(checksum), fd);
|
||||
size_t rs2 = fread(rows, 1, file_stat.st_size, fd);
|
||||
fclose(fd);
|
||||
|
||||
const unsigned int single_row_size = sizeof(*tinst->rows);
|
||||
const unsigned int all_row_size = (file_stat.st_size - sizeof(checksum));
|
||||
const unsigned int row_count = (all_row_size) / single_row_size;
|
||||
if ((rs1 != sizeof(checksum)) || (rs2 != all_row_size) || (rs2 != (single_row_size * row_count))) {
|
||||
log_error("%s: incomplete/invalid read, expected %u + %u - read %u + %u, single row size: %u", __FUNCTION__,
|
||||
(unsigned int) sizeof(checksum), row_count,
|
||||
(unsigned int) rs1, (unsigned int) rs2, single_row_size);
|
||||
free(rows);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
gs_error_t error = update_table(__FUNCTION__, tinst, rows, row_count, checksum);
|
||||
|
||||
if (error == GS_OK) {
|
||||
if (return_checksum) {
|
||||
*return_checksum = checksum;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_download_table_spec(gs_param_table_instance_t * tinst,
|
||||
const char * fname,
|
||||
uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint32_t timeout_ms,
|
||||
uint16_t * return_checksum)
|
||||
{
|
||||
csp_conn_t * conn = csp_connect(CSP_PRIO_HIGH, node, GS_CSP_PORT_RPARAM, timeout_ms, CSP_O_CRC32);
|
||||
if (conn == NULL) {
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
/* Allocate outgoing buffer */
|
||||
gs_rparam_query_t * query;
|
||||
csp_packet_t * packet = csp_buffer_get(RPARAM_QUERY_LENGTH(query, 0));
|
||||
if (packet == NULL) {
|
||||
csp_close(conn);
|
||||
return GS_ERROR_NO_BUFFERS;
|
||||
}
|
||||
|
||||
// setup request
|
||||
query = (gs_rparam_query_t *) packet->data;
|
||||
query->action = RPARAM_TABLE;
|
||||
query->table_id = table_id;
|
||||
query->length = 0;
|
||||
query->checksum = csp_hton16(GS_RPARAM_MAGIC_CHECKSUM); // Ignore checksum
|
||||
query->seq = 0;
|
||||
query->total = 0;
|
||||
|
||||
packet->length = RPARAM_QUERY_LENGTH(query, 0);
|
||||
if (!csp_send(conn, packet, 0)) {
|
||||
csp_buffer_free(packet);
|
||||
csp_close(conn);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
/* Receive remote parameter table, in host byte order
|
||||
* Note: This is necessary, because the SFP functions does not know the dataformat
|
||||
* and hence cannot be converted server-side. */
|
||||
void * dataout = NULL;
|
||||
int totalsize = 0;
|
||||
int result = csp_sfp_recv(conn, &dataout, &totalsize, timeout_ms);
|
||||
csp_close(conn);
|
||||
|
||||
if (result < 0) {
|
||||
free(dataout);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
gs_param_table_row_t * rows = dataout;
|
||||
const uint8_t row_count = totalsize / sizeof(*rows);
|
||||
|
||||
/* Calculate checksum on table (before converting endians!) */
|
||||
const uint16_t checksum = gs_fletcher16(rows, totalsize);
|
||||
|
||||
/* Autodetect Endians */
|
||||
int sum_first = 0;
|
||||
int sum_last = 0;
|
||||
for (unsigned int i = 0; i < row_count; i++) {
|
||||
sum_first += (rows[i].addr & 0xFF00) >> 8;
|
||||
sum_last += rows[i].addr & 0xFF;
|
||||
}
|
||||
|
||||
/* Correct endians */
|
||||
if (sum_first > sum_last) {
|
||||
for (unsigned int i = 0; i < row_count; i++) {
|
||||
rows[i].addr = (((rows[i].addr & 0xff00) >> 8) | ((rows[i].addr & 0x00ff) << 8));
|
||||
}
|
||||
}
|
||||
|
||||
gs_error_t error = update_table(__FUNCTION__, tinst, rows, row_count, checksum);
|
||||
if (error == GS_OK) {
|
||||
|
||||
if (return_checksum) {
|
||||
*return_checksum = checksum;
|
||||
}
|
||||
|
||||
// If filename provided, store table specification to file.
|
||||
if (gs_string_empty(fname) == false) {
|
||||
FILE * fd = fopen(fname, "w");
|
||||
if (fd == NULL) {
|
||||
log_error("%s: failed to open/create file: [%s]", __FUNCTION__, fname);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
const size_t ws1_size = sizeof(checksum);
|
||||
const size_t ws1 = fwrite(&checksum, 1, ws1_size, fd);
|
||||
const size_t ws2 = fwrite(rows, 1, totalsize, fd);
|
||||
fclose(fd);
|
||||
if ((ws1 != ws1_size) || (ws2 != (size_t) totalsize)) {
|
||||
log_error("%s: failed to write %u + %d - wrote %u + %u", __FUNCTION__,
|
||||
(unsigned int) sizeof(checksum), totalsize, (unsigned int) ws1, (unsigned int) ws2);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_get_full_table(gs_param_table_instance_t * tinst,
|
||||
uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint16_t checksum,
|
||||
uint32_t timeout_ms)
|
||||
{
|
||||
GS_CHECK_HANDLE(tinst != NULL);
|
||||
GS_CHECK_HANDLE(tinst->rows != NULL);
|
||||
GS_CHECK_HANDLE(tinst->memory != NULL);
|
||||
|
||||
unsigned int expected_bytes = 0;
|
||||
{
|
||||
unsigned int param_pos = 0;
|
||||
gs_error_t error = gs_param_serialize_full_table(tinst, ¶m_pos, GS_PARAM_SF_DRY_RUN, NULL, 10000, &expected_bytes);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
gs_rparam_query_t * query;
|
||||
csp_packet_t * request = csp_buffer_get(RPARAM_QUERY_LENGTH(query, 0));
|
||||
if (request == NULL) {
|
||||
return GS_ERROR_NO_BUFFERS;
|
||||
}
|
||||
|
||||
csp_conn_t * conn = csp_connect(CSP_PRIO_HIGH, node, GS_CSP_PORT_RPARAM, timeout_ms, CSP_O_CRC32);
|
||||
if (!conn) {
|
||||
csp_buffer_free(request);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
query = (gs_rparam_query_t *) request->data;
|
||||
query->action = RPARAM_GET;
|
||||
query->table_id = table_id;
|
||||
query->length = 0; // == get full table
|
||||
query->checksum = csp_hton16(checksum);
|
||||
query->seq = 0;
|
||||
query->total = 0;
|
||||
|
||||
request->length = RPARAM_QUERY_LENGTH(query, 0);
|
||||
if (!csp_send(conn, request, timeout_ms)) {
|
||||
csp_buffer_free(request);
|
||||
csp_close(conn);
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
csp_packet_t * reply;
|
||||
gs_error_t error = GS_OK;
|
||||
unsigned int total_bytes = 0;
|
||||
while ((reply = csp_read(conn, timeout_ms)) != NULL) {
|
||||
|
||||
/* We have a reply */
|
||||
query = (void *) reply->data;
|
||||
const uint16_t qlength = csp_ntoh16(query->length);
|
||||
total_bytes += qlength;
|
||||
const uint16_t seq = csp_ntoh16(query->seq);
|
||||
const uint16_t total = csp_ntoh16(query->total);
|
||||
|
||||
if (query->action == RPARAM_REPLY) {
|
||||
error = gs_param_deserialize(tinst, query->payload.packed, qlength, F_FROM_BIG_ENDIAN);
|
||||
}
|
||||
csp_buffer_free(reply);
|
||||
|
||||
if (error || (seq >= total)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reply == NULL) {
|
||||
error = GS_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
if ((error == GS_OK) && (expected_bytes != total_bytes)) {
|
||||
log_warning("%s: expected %u != received %u bytes", __FUNCTION__, expected_bytes, total_bytes);
|
||||
error = GS_ERROR_DATA;
|
||||
}
|
||||
|
||||
csp_close(conn);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_get(uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint16_t addr,
|
||||
gs_param_type_t type,
|
||||
uint16_t checksum,
|
||||
uint32_t timeout_ms,
|
||||
void * value,
|
||||
size_t value_size)
|
||||
{
|
||||
/* Calculate length */
|
||||
gs_rparam_query_t * query;
|
||||
const size_t query_size = RPARAM_QUERY_LENGTH(query, sizeof(query->payload.addr[0]));
|
||||
const size_t reply_payload_size = (value_size + sizeof(query->payload.addr[0]));
|
||||
const size_t reply_size = RPARAM_QUERY_LENGTH(query, reply_payload_size);
|
||||
|
||||
query = alloca(reply_size);
|
||||
query->action = RPARAM_GET;
|
||||
query->table_id = table_id;
|
||||
query->checksum = csp_hton16(checksum);
|
||||
query->seq = 0;
|
||||
query->total = 0;
|
||||
query->payload.addr[0] = csp_hton16(addr);
|
||||
query->length = csp_hton16(sizeof(query->payload.addr[0]));
|
||||
|
||||
/* Run single packet transaction */
|
||||
if (csp_transaction2(CSP_PRIO_HIGH, node, GS_CSP_PORT_RPARAM, timeout_ms, query, query_size, query, reply_size, CSP_O_CRC32) <= 0) {
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
/* We have a reply */
|
||||
query->length = csp_ntoh16(query->length);
|
||||
|
||||
if (query->length != reply_payload_size) {
|
||||
log_warning("%s: Invalid reply size %u - expected %u", __FUNCTION__, query->length, (unsigned int) reply_payload_size);
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
|
||||
/* Read address */
|
||||
query->payload.addr[0] = csp_betoh16(query->payload.addr[0]);
|
||||
if (query->payload.addr[0] != addr) {
|
||||
log_warning("%s: Invalid address in reply %u", __FUNCTION__, query->payload.addr[0]);
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
|
||||
/* Read value */
|
||||
memcpy(value, &query->payload.packed[2], value_size);
|
||||
gs_param_betoh(type, value);
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_set(uint8_t node,
|
||||
gs_param_table_id_t table_id,
|
||||
uint16_t addr,
|
||||
gs_param_type_t type,
|
||||
uint16_t checksum,
|
||||
uint32_t timeout_ms,
|
||||
const void * value,
|
||||
size_t value_size)
|
||||
{
|
||||
/* Calculate length */
|
||||
gs_rparam_query_t * query;
|
||||
const size_t payload_size = (value_size + sizeof(query->payload.addr[0]));
|
||||
const size_t query_size = RPARAM_QUERY_LENGTH(query, payload_size);
|
||||
|
||||
query = alloca(query_size);
|
||||
query->action = RPARAM_SET;
|
||||
query->table_id = table_id;
|
||||
query->seq = 0;
|
||||
query->total = 0;
|
||||
query->checksum = csp_hton16(checksum);
|
||||
|
||||
/* Actual set query */
|
||||
unsigned int bytes = 0;
|
||||
gs_error_t error = gs_param_serialize_item_direct(type, value_size, addr, value, F_TO_BIG_ENDIAN, query->payload.packed, payload_size, &bytes);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Add to query */
|
||||
query->length = csp_hton16(bytes);
|
||||
|
||||
/* Run single packet transaction */
|
||||
if (csp_transaction2(CSP_PRIO_HIGH, node, GS_CSP_PORT_RPARAM, timeout_ms, query, query_size, query, 1, CSP_O_CRC32) <= 0) {
|
||||
return GS_ERROR_IO;
|
||||
}
|
||||
|
||||
/* We have a reply */
|
||||
query->length = csp_ntoh16(query->length);
|
||||
|
||||
if ((query->action != RPARAM_SET_OK) || (query->length != bytes)) {
|
||||
log_warning("%s: Invalid reply: size %u - expected %u, action %u - expected %u",
|
||||
__FUNCTION__, query->length, bytes, query->action, RPARAM_SET_OK);
|
||||
return GS_ERROR_DATA;
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_rparam_query_get_value(gs_param_table_instance_t * tinst, const char* param_name, uint16_t param_no, void* val_p, size_t val_size)
|
||||
{
|
||||
const gs_param_table_row_t * t = gs_param_row_by_name(param_name, tinst->rows, tinst->row_count);
|
||||
if (t == NULL) {
|
||||
return GS_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (val_size < t->size) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
|
||||
return gs_param_get(tinst, t->addr + (param_no * t->size), t->type, val_p, t->size, 0);
|
||||
}
|
353
gomspace/libparam_client/src/serialize.c
Normal file
353
gomspace/libparam_client/src/serialize.c
Normal file
@ -0,0 +1,353 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include "serialize_local.h"
|
||||
#include <gs/param/table.h>
|
||||
#include <gs/param/internal/types.h>
|
||||
#include <gs/util/byteorder.h>
|
||||
#include <gs/util/endian.h>
|
||||
#include <alloca.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <param/param_types.h> // need PARM_X??? definitions
|
||||
|
||||
bool gs_param_betoh(gs_param_type_t type, void * item)
|
||||
{
|
||||
if (item) {
|
||||
switch (type) {
|
||||
case GS_PARAM_UINT16:
|
||||
case GS_PARAM_INT16:
|
||||
case PARAM_X16:
|
||||
{
|
||||
*(uint16_t *) item = util_betoh16(*(uint16_t *) item);
|
||||
return true;
|
||||
}
|
||||
case GS_PARAM_UINT32:
|
||||
case GS_PARAM_INT32:
|
||||
case PARAM_X32:
|
||||
{
|
||||
*(uint32_t *) item = util_betoh32(*(uint32_t *) item);
|
||||
return true;
|
||||
}
|
||||
case GS_PARAM_UINT64:
|
||||
case GS_PARAM_INT64:
|
||||
case PARAM_X64:
|
||||
{
|
||||
*(uint64_t *) item = util_betoh64(*(uint64_t *) item);
|
||||
return true;
|
||||
}
|
||||
case GS_PARAM_FLOAT:
|
||||
{
|
||||
*(float *) item = util_ntohflt(*(float *) item);
|
||||
return true;
|
||||
}
|
||||
case GS_PARAM_DOUBLE:
|
||||
{
|
||||
*(double *) item = util_ntohdbl(*(double *) item);
|
||||
return true;
|
||||
}
|
||||
|
||||
case GS_PARAM_UINT8:
|
||||
case GS_PARAM_INT8:
|
||||
case PARAM_X8:
|
||||
case GS_PARAM_STRING:
|
||||
case GS_PARAM_DATA:
|
||||
case GS_PARAM_BOOL:
|
||||
// no swap
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gs_param_htobe(gs_param_type_t type, void * item)
|
||||
{
|
||||
if (item) {
|
||||
switch (type) {
|
||||
case PARAM_UINT16:
|
||||
case PARAM_INT16:
|
||||
case PARAM_X16:
|
||||
{
|
||||
*(uint16_t *) item = util_htobe16(*(uint16_t *) item);
|
||||
return true;
|
||||
}
|
||||
case PARAM_UINT32:
|
||||
case PARAM_INT32:
|
||||
case PARAM_X32:
|
||||
{
|
||||
*(uint32_t *) item = util_htobe32(*(uint32_t *) item);
|
||||
return true;
|
||||
}
|
||||
case PARAM_UINT64:
|
||||
case PARAM_INT64:
|
||||
case PARAM_X64:
|
||||
{
|
||||
*(uint64_t *) item = util_htobe64(*(uint64_t *) item);
|
||||
return true;
|
||||
}
|
||||
case PARAM_FLOAT:
|
||||
{
|
||||
*(float *) item = util_htonflt(*(float *) item);
|
||||
return true;
|
||||
}
|
||||
case PARAM_DOUBLE:
|
||||
{
|
||||
*(double *) item = util_htondbl(*(double *) item);
|
||||
return true;
|
||||
}
|
||||
|
||||
case PARAM_UINT8:
|
||||
case PARAM_INT8:
|
||||
case PARAM_X8:
|
||||
case PARAM_STRING:
|
||||
case PARAM_DATA:
|
||||
case PARAM_BOOL:
|
||||
// no swap
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool gs_param_require_endian_swap(gs_param_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case PARAM_UINT16:
|
||||
case PARAM_INT16:
|
||||
case PARAM_X16:
|
||||
case PARAM_UINT32:
|
||||
case PARAM_INT32:
|
||||
case PARAM_X32:
|
||||
case PARAM_UINT64:
|
||||
case PARAM_INT64:
|
||||
case PARAM_X64:
|
||||
case PARAM_FLOAT:
|
||||
case PARAM_DOUBLE:
|
||||
// swap
|
||||
break;
|
||||
|
||||
case PARAM_UINT8:
|
||||
case PARAM_INT8:
|
||||
case PARAM_X8:
|
||||
case PARAM_STRING:
|
||||
case PARAM_DATA:
|
||||
case PARAM_BOOL:
|
||||
// no swap
|
||||
return false;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static gs_error_t gs_param_serialize_array(gs_param_table_instance_t * tinst, const gs_param_table_row_t * param, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos)
|
||||
{
|
||||
const unsigned int param_size = GS_PARAM_SIZE(param);
|
||||
const unsigned int param_array_size = GS_PARAM_ARRAY_SIZE(param);
|
||||
const gs_param_type_t param_type = GS_PARAM_TYPE(param);
|
||||
|
||||
/* Calculate total parameter size (full array) */
|
||||
{
|
||||
unsigned int size = param_size * param_array_size;
|
||||
if ((flags & F_PACKED) == 0) {
|
||||
size += param_array_size * sizeof(uint16_t); // address
|
||||
}
|
||||
|
||||
/* Return if parameter array would exceed maxbuf */
|
||||
if (*buf_pos + size > buf_size) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t value[param_size];
|
||||
gs_error_t error = GS_OK;
|
||||
for (unsigned int j = 0; (j < param_array_size) && (error == GS_OK); j++) {
|
||||
const uint16_t addr = GS_PARAM_ADDR(param) + (param_size * j);
|
||||
error = gs_param_get(tinst, addr, param_type, value, param_size, 0);
|
||||
if (error == GS_OK) {
|
||||
error = gs_param_serialize_item(param, addr, value, flags, buf, buf_size, buf_pos);
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_serialize_item_direct(gs_param_type_t param_type, unsigned int param_size, uint16_t addr, const void * item, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos)
|
||||
{
|
||||
/* Check length */
|
||||
if ((((flags & F_PACKED) ? 0 : sizeof(addr)) + param_size + *buf_pos) > buf_size) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
|
||||
/* Include address if not packed */
|
||||
if ((flags & F_PACKED) == 0) {
|
||||
|
||||
if (flags & F_TO_BIG_ENDIAN) {
|
||||
addr = util_htobe16(addr);
|
||||
}
|
||||
|
||||
if ((flags & F_DRY_RUN) == 0) {
|
||||
memcpy(&buf[*buf_pos], &addr, sizeof(addr));
|
||||
}
|
||||
|
||||
*buf_pos += sizeof(addr);
|
||||
}
|
||||
|
||||
if ((flags & F_DRY_RUN) == 0) {
|
||||
if (flags & F_TO_BIG_ENDIAN) {
|
||||
void * tmp = alloca(param_size); // this must be aligned
|
||||
memcpy(tmp, item, param_size);
|
||||
gs_param_htobe(param_type, tmp);
|
||||
item = tmp;
|
||||
}
|
||||
memcpy(&buf[*buf_pos], item, param_size);
|
||||
}
|
||||
|
||||
*buf_pos += param_size;
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_serialize_item(const gs_param_table_row_t * param, uint16_t addr, const void * item, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos)
|
||||
{
|
||||
const gs_param_type_t param_type = GS_PARAM_TYPE(param);
|
||||
const unsigned int param_size = GS_PARAM_SIZE(param);
|
||||
return gs_param_serialize_item_direct(param_type, param_size, addr, item, flags, buf, buf_size, buf_pos);
|
||||
}
|
||||
|
||||
gs_error_t gs_param_serialize_full_table(gs_param_table_instance_t * tinst, unsigned int * param_pos, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos)
|
||||
{
|
||||
if (flags & GS_PARAM_SF_DRY_RUN) {
|
||||
buf = NULL;
|
||||
buf_size = -1; // Max size
|
||||
}
|
||||
gs_error_t error = GS_OK;
|
||||
unsigned int i = *param_pos;
|
||||
for (; i < tinst->row_count; i++) {
|
||||
const gs_param_table_row_t * param = &tinst->rows[i];
|
||||
error = gs_param_serialize_array(tinst, param, flags, buf, buf_size, buf_pos);
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*param_pos = i;
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_serialize_list(gs_param_table_instance_t * tinst,
|
||||
const uint16_t addr[], unsigned int addr_count,
|
||||
unsigned int * param_pos, uint32_t flags,
|
||||
uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos)
|
||||
{
|
||||
if (tinst == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
|
||||
gs_error_t error = GS_OK;
|
||||
unsigned int i = *param_pos;
|
||||
for (; i < addr_count; ++i) {
|
||||
const gs_param_table_row_t * param = gs_param_row_by_address(addr[i], tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const gs_param_type_t param_type = GS_PARAM_TYPE(param);
|
||||
const unsigned int param_size = GS_PARAM_SIZE(param);
|
||||
uint8_t value[param_size];
|
||||
error = gs_param_get(tinst, addr[i], param_type, value, param_size, 0);
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
error = gs_param_serialize_item(param, addr[i], value, flags, buf, buf_size, buf_pos);
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*param_pos = i;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_deserialize_item(gs_param_table_instance_t * tinst,
|
||||
const gs_param_table_row_t * param,
|
||||
uint16_t addr,
|
||||
const void * item,
|
||||
uint32_t flags)
|
||||
{
|
||||
const gs_param_type_t param_type = GS_PARAM_TYPE(param);
|
||||
const unsigned int param_size = GS_PARAM_SIZE(param);
|
||||
|
||||
if (flags & F_FROM_BIG_ENDIAN) {
|
||||
if (gs_param_require_endian_swap(param_type)) {
|
||||
|
||||
// Copy to temporary storage, so we don't mess with input memory
|
||||
void * tmp = alloca(param_size);
|
||||
memcpy(tmp, item, param_size);
|
||||
|
||||
gs_param_betoh(param_type, tmp);
|
||||
|
||||
// Replace input pointer
|
||||
item = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
gs_error_t error = GS_OK;
|
||||
if ((flags & F_DRY_RUN) == 0) {
|
||||
error = gs_param_set(tinst, addr, param_type, item, param_size, GS_PARAM_FLAGS(param));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_deserialize(gs_param_table_instance_t * tinst, const uint8_t * buf, unsigned int buf_size, uint32_t flags)
|
||||
{
|
||||
unsigned int pos = 0;
|
||||
unsigned int count = 0;
|
||||
gs_error_t error = GS_OK;
|
||||
while ((pos < buf_size) && (error == GS_OK)) {
|
||||
|
||||
if (flags & F_PACKED) {
|
||||
/** PACKED */
|
||||
|
||||
/* Find in table */
|
||||
const gs_param_table_row_t * param = &tinst->rows[count];
|
||||
const unsigned int param_array_size = GS_PARAM_ARRAY_SIZE(param);
|
||||
const unsigned int param_size = GS_PARAM_SIZE(param);
|
||||
|
||||
/* For each item in array */
|
||||
for (unsigned int j = 0; (j < param_array_size) && (error == GS_OK); j++) {
|
||||
uint16_t addr = GS_PARAM_ADDR(param) + (param_size * j);
|
||||
error = gs_param_deserialize_item(tinst, param, addr, &buf[pos], flags);
|
||||
pos += param_size;
|
||||
}
|
||||
|
||||
} else {
|
||||
/** NOT PACKED */
|
||||
|
||||
/* Read address from data */
|
||||
uint16_t addr;
|
||||
memcpy(&addr, &buf[pos], sizeof(addr));
|
||||
if (flags & F_FROM_BIG_ENDIAN) {
|
||||
addr = util_betoh16(addr);
|
||||
}
|
||||
pos += sizeof(addr);
|
||||
|
||||
/* Find in table */
|
||||
const gs_param_table_row_t * param = gs_param_row_by_address(addr, tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Copy value */
|
||||
error = gs_param_deserialize_item(tinst, param, addr, &buf[pos], flags);
|
||||
pos += GS_PARAM_SIZE(param);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
9
gomspace/libparam_client/src/serialize_local.h
Normal file
9
gomspace/libparam_client/src/serialize_local.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef SRC_SERIALIZE_LOCAL_H
|
||||
#define SRC_SERIALIZE_LOCAL_H
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#include <gs/param/internal/serialize.h>
|
||||
|
||||
gs_error_t gs_param_serialize_item_direct(gs_param_type_t param_type, unsigned int param_size, uint16_t addr, const void * item, uint32_t flags, uint8_t * buf, unsigned int buf_size, unsigned int * buf_pos);
|
||||
|
||||
#endif
|
589
gomspace/libparam_client/src/string.c
Normal file
589
gomspace/libparam_client/src/string.c
Normal file
@ -0,0 +1,589 @@
|
||||
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/types.h>
|
||||
#include <gs/param/internal/table.h>
|
||||
#include <gs/util/string.h>
|
||||
#include <gs/util/log.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <gs/util/bytebuffer.h>
|
||||
#include <ctype.h>
|
||||
|
||||
size_t gs_param_calc_table_size(const gs_param_table_row_t * rows, size_t row_count)
|
||||
{
|
||||
if (rows && row_count) {
|
||||
const gs_param_table_row_t * last_row = rows;
|
||||
// table rows may not be in assending address- so we have to run through the entire table.
|
||||
for (size_t i = 0; i < row_count; ++i, ++rows) {
|
||||
if (GS_PARAM_ADDR(rows) > GS_PARAM_ADDR(last_row)) {
|
||||
last_row = rows;
|
||||
}
|
||||
}
|
||||
return (GS_PARAM_ADDR(last_row) + (GS_PARAM_SIZE(last_row) * GS_PARAM_ARRAY_SIZE(last_row)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * gs_param_row_by_name(const char * name, const gs_param_table_row_t * rows, size_t row_count)
|
||||
{
|
||||
if (rows) {
|
||||
for (unsigned int i = 0; i < row_count; ++i, ++rows) {
|
||||
if (GS_PGM_STRNCASECMP(name, rows->name, GS_PARAM_MAX_NAME) == 0) {
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * gs_param_row_by_address(uint16_t addr, const gs_param_table_row_t * rows, size_t row_count)
|
||||
{
|
||||
if (rows) {
|
||||
for (unsigned int i = 0; i < row_count; ++i, ++rows) {
|
||||
const unsigned int param_array_size = GS_PARAM_ARRAY_SIZE(rows);
|
||||
const unsigned int param_size = GS_PARAM_SIZE(rows);
|
||||
const unsigned int param_addr = GS_PARAM_ADDR(rows);
|
||||
for (unsigned int j = 0; j < param_array_size; ++j) {
|
||||
if ((param_addr + (j * param_size)) == addr) {
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
memcpy is used, because data/value may not be aligned correctly and cause crash if accessed directly.
|
||||
*/
|
||||
gs_error_t gs_param_to_string_buffer(const gs_param_table_row_t * param, const void * value, bool with_type, uint32_t flags, gs_bytebuffer_t *bb)
|
||||
{
|
||||
flags |= param->flags;
|
||||
const uint8_t param_type = GS_PARAM_TYPE(param);
|
||||
switch (param_type) {
|
||||
case GS_PARAM_BOOL: {
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "BL ");
|
||||
}
|
||||
gs_bytebuffer_printf(bb, "%s", *(uint8_t *) value ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
case GS_PARAM_INT8: {
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "I8 ");
|
||||
}
|
||||
gs_bytebuffer_printf(bb, "%d", *(int8_t *) value);
|
||||
break;
|
||||
}
|
||||
case PARAM_X8:
|
||||
flags |= GS_PARAM_F_SHOW_HEX;
|
||||
// fallthrough
|
||||
case GS_PARAM_UINT8: {
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "U8 ");
|
||||
}
|
||||
if (flags & GS_PARAM_F_SHOW_HEX) {
|
||||
gs_bytebuffer_printf(bb, "0x%02"PRIx8, *(uint8_t *) value);
|
||||
} else {
|
||||
gs_bytebuffer_printf(bb, "%u", *(uint8_t *) value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GS_PARAM_INT16: {
|
||||
int16_t tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "I16 ");
|
||||
}
|
||||
gs_bytebuffer_printf(bb, "%"PRId16, tmp);
|
||||
break;
|
||||
}
|
||||
case PARAM_X16:
|
||||
flags |= GS_PARAM_F_SHOW_HEX;
|
||||
// fallthrough
|
||||
case GS_PARAM_UINT16: {
|
||||
uint16_t tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "U16 ");
|
||||
}
|
||||
if (flags & GS_PARAM_F_SHOW_HEX) {
|
||||
gs_bytebuffer_printf(bb, "0x%04"PRIx16, tmp);
|
||||
} else {
|
||||
gs_bytebuffer_printf(bb, "%"PRIu16, tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GS_PARAM_INT32: {
|
||||
int32_t tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "I32 ");
|
||||
}
|
||||
gs_bytebuffer_printf(bb, "%"PRId32, tmp);
|
||||
break;
|
||||
}
|
||||
case PARAM_X32:
|
||||
flags |= GS_PARAM_F_SHOW_HEX;
|
||||
// fallthrough
|
||||
case GS_PARAM_UINT32: {
|
||||
uint32_t tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "U32 ");
|
||||
}
|
||||
if (flags & GS_PARAM_F_SHOW_HEX) {
|
||||
gs_bytebuffer_printf(bb, "0x%08"PRIx32, tmp);
|
||||
} else {
|
||||
gs_bytebuffer_printf(bb, "%"PRIu32, tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef PRIu64
|
||||
case GS_PARAM_INT64: {
|
||||
int64_t tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "I64 ");
|
||||
}
|
||||
gs_bytebuffer_printf(bb, "%"PRId64, tmp);
|
||||
break;
|
||||
}
|
||||
case PARAM_X64:
|
||||
flags |= GS_PARAM_F_SHOW_HEX;
|
||||
// fallthrough
|
||||
case GS_PARAM_UINT64: {
|
||||
uint64_t tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "U64 ");
|
||||
}
|
||||
if (flags & GS_PARAM_F_SHOW_HEX) {
|
||||
gs_bytebuffer_printf(bb, "0x%016"PRIx64, tmp);
|
||||
} else {
|
||||
gs_bytebuffer_printf(bb, "%"PRIu64, tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case GS_PARAM_FLOAT: {
|
||||
float tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "FLT ");
|
||||
}
|
||||
if (flags & GS_PARAM_F_SHOW_SCIENTIFIC) {
|
||||
gs_bytebuffer_printf(bb, "%e", (double) tmp);
|
||||
} else {
|
||||
gs_bytebuffer_printf(bb, "%f", (double) tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GS_PARAM_DOUBLE: {
|
||||
double tmp;
|
||||
memcpy(&tmp, value, sizeof(tmp));
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "DBL ");
|
||||
}
|
||||
if (flags & GS_PARAM_F_SHOW_SCIENTIFIC) {
|
||||
gs_bytebuffer_printf(bb, "%e", tmp);
|
||||
} else {
|
||||
gs_bytebuffer_printf(bb, "%f", tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GS_PARAM_STRING: {
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "STR ");
|
||||
}
|
||||
gs_bytebuffer_append(bb, "\"", 1);
|
||||
// handle missing NUL termination.
|
||||
const size_t len = strnlen((const char*)value, GS_PARAM_SIZE(param));
|
||||
gs_bytebuffer_append(bb, value, len);
|
||||
gs_bytebuffer_append(bb, "\"", 1);
|
||||
break;
|
||||
}
|
||||
case GS_PARAM_DATA: {
|
||||
if (with_type == 1) {
|
||||
gs_bytebuffer_printf(bb, "DAT ");
|
||||
}
|
||||
for (int i = 0; i < GS_PARAM_SIZE(param); i++) {
|
||||
gs_bytebuffer_printf(bb, "%02"PRIX8, ((uint8_t *) value)[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
log_error("%s: Unknown param type %u", __FUNCTION__, param_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_to_string2(const gs_param_table_row_t * param, const void * value, bool with_type, uint32_t flags, char * buf, unsigned int buf_size, unsigned int buf_pos, unsigned int * buf_written)
|
||||
{
|
||||
GS_CHECK_ARG(buf_pos <= buf_size);
|
||||
gs_bytebuffer_t bb;
|
||||
gs_bytebuffer_init(&bb, &buf[buf_pos], (buf_size - buf_pos));
|
||||
gs_error_t error = gs_param_to_string_buffer(param, value, with_type, flags, &bb);
|
||||
if (error == GS_OK) {
|
||||
gs_bytebuffer_get_as_string(&bb, &error); // this will add NUL termination, but may truncate buffer
|
||||
error = gs_bytebuffer_get_state(&bb);
|
||||
if (buf_written) {
|
||||
*buf_written = bb.used;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
const char * gs_param_type_to_string(gs_param_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GS_PARAM_BOOL: return "bool";
|
||||
case GS_PARAM_UINT8: return "uint8_t";
|
||||
case GS_PARAM_UINT16: return "uint16_t";
|
||||
case GS_PARAM_UINT32: return "uint32_t";
|
||||
case GS_PARAM_UINT64: return "uint65_t";
|
||||
case GS_PARAM_INT8: return "int8_t";
|
||||
case GS_PARAM_INT16: return "int16_t";
|
||||
case GS_PARAM_INT32: return "int32_t";
|
||||
case GS_PARAM_INT64: return "int64_t";
|
||||
case PARAM_X8: return "uint8_t";
|
||||
case PARAM_X16: return "uint16_t";
|
||||
case PARAM_X32: return "uint32_t";
|
||||
case PARAM_X64: return "uint64_t";
|
||||
case GS_PARAM_FLOAT: return "float";
|
||||
case GS_PARAM_DOUBLE: return "double";
|
||||
case GS_PARAM_STRING: return "char";
|
||||
case GS_PARAM_DATA: return "char";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline int to_int(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'A' && c <= 'F') return 10 + c - 'A';
|
||||
if (c >= 'a' && c <= 'f') return 10 + c - 'a';
|
||||
return -1;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_from_string(const gs_param_table_row_t * param, const char * string, void * value)
|
||||
{
|
||||
if ((param == NULL) || (string == NULL) || (value == NULL)) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
if (GS_PARAM_TYPE(param) != GS_PARAM_STRING) {
|
||||
// skip only space - not white-space, e.g. isspace()
|
||||
for (; *string == ' '; ++string);
|
||||
}
|
||||
|
||||
gs_error_t error = GS_OK;
|
||||
|
||||
switch(GS_PARAM_TYPE(param)) {
|
||||
|
||||
case GS_PARAM_BOOL:
|
||||
{
|
||||
bool parsein = false;
|
||||
error = gs_string_to_bool(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((uint8_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_UINT8:
|
||||
{
|
||||
uint8_t parsein;
|
||||
error = gs_string_to_uint8(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((uint8_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_UINT16:
|
||||
{
|
||||
uint16_t parsein;
|
||||
error = gs_string_to_uint16(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((uint16_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_UINT32:
|
||||
{
|
||||
uint32_t parsein;
|
||||
error = gs_string_to_uint32(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((uint32_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_UINT64:
|
||||
{
|
||||
uint64_t parsein;
|
||||
error = gs_string_to_uint64(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((uint64_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_INT8:
|
||||
{
|
||||
int8_t parsein;
|
||||
error = gs_string_to_int8(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((int8_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_INT16:
|
||||
{
|
||||
int16_t parsein;
|
||||
error = gs_string_to_int16(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((int16_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_INT32:
|
||||
{
|
||||
int32_t parsein;
|
||||
error = gs_string_to_int32(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((int32_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_INT64:
|
||||
{
|
||||
int64_t parsein;
|
||||
error = gs_string_to_int64(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((int64_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PARAM_X8:
|
||||
{
|
||||
uint32_t parsein;
|
||||
error = gs_string_hex_to_uint32(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
if (parsein <= UINT8_MAX) {
|
||||
*((uint8_t *) value) = parsein;
|
||||
} else {
|
||||
error = GS_ERROR_OVERFLOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PARAM_X16:
|
||||
{
|
||||
uint32_t parsein;
|
||||
error = gs_string_hex_to_uint32(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
if (parsein <= UINT16_MAX) {
|
||||
*((uint16_t *) value) = parsein;
|
||||
} else {
|
||||
error = GS_ERROR_OVERFLOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PARAM_X32:
|
||||
{
|
||||
uint32_t parsein;
|
||||
error = gs_string_hex_to_uint32(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((uint32_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PARAM_X64:
|
||||
{
|
||||
uint64_t parsein;
|
||||
error = gs_string_hex_to_uint64(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((uint64_t *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_FLOAT:
|
||||
{
|
||||
float parsein;
|
||||
error = gs_string_to_float(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((float *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_DOUBLE:
|
||||
{
|
||||
double parsein;
|
||||
error = gs_string_to_double(string, &parsein);
|
||||
if (error == GS_OK) {
|
||||
*((double *) value) = parsein;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_STRING:
|
||||
{
|
||||
const size_t ilen = strnlen(string, GS_PARAM_SIZE(param) + 1); // 0 terminator
|
||||
if (ilen <= GS_PARAM_SIZE(param)) {
|
||||
memset(value, 0, GS_PARAM_SIZE(param));
|
||||
memcpy(value, string, ilen);
|
||||
} else {
|
||||
error = GS_ERROR_OVERFLOW;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_DATA:
|
||||
{
|
||||
const size_t MAX_LEN = (GS_PARAM_SIZE(param) * 2);
|
||||
const size_t ilen = strnlen(string, MAX_LEN + 1);
|
||||
if (ilen > MAX_LEN) {
|
||||
error = GS_ERROR_OVERFLOW;
|
||||
} else if ((ilen % 2) == 0) {
|
||||
|
||||
// validate data first - not to end up with invalid/strange data
|
||||
for (unsigned int i = 0; i < ilen; ++i) {
|
||||
if (to_int(string[i]) < 0) {
|
||||
error = GS_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (error == GS_OK) {
|
||||
uint8_t * out = (uint8_t *) value;
|
||||
memset(out, 0, GS_PARAM_SIZE(param));
|
||||
for (unsigned int i = 0; i < ilen; i += 2, ++out) {
|
||||
*out = (16 * to_int(string[i])) + to_int(string[i+1]);
|
||||
}
|
||||
error = GS_OK;
|
||||
}
|
||||
} else {
|
||||
error = GS_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_list_single_to_stream(gs_param_table_instance_t * tinst, const gs_param_table_row_t * param,
|
||||
bool list_data, uint32_t flags, FILE * out)
|
||||
{
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
|
||||
gs_error_t error = GS_OK;
|
||||
const uint16_t addr = GS_PARAM_ADDR(param);
|
||||
|
||||
fprintf(out, " 0x%04X %-16.14"GS_PGM_FMT_STR, addr, param->name); // ensure missing NUL termination doesn't cause problems.
|
||||
|
||||
if (list_data) {
|
||||
const gs_param_type_t param_type = GS_PARAM_TYPE(param);
|
||||
const unsigned int param_array_size = GS_PARAM_ARRAY_SIZE(param);
|
||||
const unsigned int param_size = GS_PARAM_SIZE(param);
|
||||
uint8_t value[param_size];
|
||||
char buf[100];
|
||||
for (unsigned int j = 0; (j < param_array_size) && (error == GS_OK); j++) {
|
||||
error = gs_param_get(tinst, addr + (param_size * j), param_type, value, param_size, 0);
|
||||
if (error == GS_OK) {
|
||||
gs_param_to_string2(param, value, (j == 0) ? 1 : 0, flags, buf, sizeof(buf), 0, NULL);
|
||||
fprintf(out, "%s ", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(out, "\r\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_list_to_stream(gs_param_table_instance_t * tinst, bool list_data, uint32_t flags, FILE * out)
|
||||
{
|
||||
GS_CHECK_HANDLE(tinst != NULL);
|
||||
|
||||
gs_error_t error = GS_OK;
|
||||
for (unsigned int i = 0; (i < tinst->row_count) && (error == GS_OK); ++i) {
|
||||
error = gs_param_list_single_to_stream(tinst, &tinst->rows[i], list_data, flags, out);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_parse_name_and_array_index(const char * inp, char * name, size_t size_name, uint8_t * return_index, bool * return_is_array)
|
||||
{
|
||||
if (inp == NULL) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
uint8_t a_index;
|
||||
size_t name_len;
|
||||
gs_error_t error;
|
||||
bool is_array;
|
||||
const char * pai = strchr(inp, '['); // look for array index
|
||||
if (pai) {
|
||||
name_len = pai - inp;
|
||||
char tmp[20];
|
||||
GS_STRNCPY(tmp, pai+1);
|
||||
char * endp = strchr(tmp, ']');
|
||||
if (endp) {
|
||||
*endp = 0;
|
||||
}
|
||||
error = gs_string_to_uint8(tmp, &a_index);
|
||||
is_array = true;
|
||||
} else {
|
||||
error = GS_OK;
|
||||
name_len = strlen(inp);
|
||||
is_array = false;
|
||||
a_index = 0;
|
||||
}
|
||||
|
||||
if (error == GS_OK) {
|
||||
if (name_len >= size_name) {
|
||||
error = GS_ERROR_OVERFLOW;
|
||||
} else {
|
||||
strncpy(name, inp, name_len);
|
||||
name[name_len] = 0;
|
||||
|
||||
// remove trailing white-space
|
||||
if (name_len) {
|
||||
for (int i = name_len-1; i >= 0; --i) {
|
||||
if (name[i] && isspace((int)name[i])) {
|
||||
name[i] = 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (return_index) {
|
||||
*return_index = (is_array) ? a_index : 0;
|
||||
}
|
||||
if (return_is_array) {
|
||||
*return_is_array = is_array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
393
gomspace/libparam_client/src/table.c
Normal file
393
gomspace/libparam_client/src/table.c
Normal file
@ -0,0 +1,393 @@
|
||||
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
|
||||
|
||||
#define GS_PARAM_INTERNAL_USE 1
|
||||
|
||||
#include <gs/param/internal/types.h>
|
||||
#include <gs/param/internal/table.h>
|
||||
#include <gs/param/serialize.h>
|
||||
#include <gs/util/check.h>
|
||||
#include <gs/util/byteorder.h>
|
||||
#include <gs/util/endian.h>
|
||||
#include <gs/util/fletcher.h>
|
||||
|
||||
#include <alloca.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void _copy_data(gs_param_type_t type, void * dst, const void * src, size_t size)
|
||||
{
|
||||
#if (GS_PARAM_ATOMIC_ACCESS)
|
||||
switch (type) {
|
||||
case GS_PARAM_UINT8:
|
||||
case GS_PARAM_INT8:
|
||||
case PARAM_X8:
|
||||
case GS_PARAM_STRING:
|
||||
case GS_PARAM_DATA:
|
||||
case GS_PARAM_BOOL:
|
||||
break;
|
||||
|
||||
case GS_PARAM_UINT16:
|
||||
case GS_PARAM_INT16:
|
||||
case PARAM_X16:
|
||||
if (!((intptr_t)src & 1) && !((intptr_t)dst & 1)) {
|
||||
// (u)int16 aligned correctly
|
||||
const uint16_t * s = src;
|
||||
uint16_t * d = dst;
|
||||
const unsigned int count = (size / sizeof(*d));
|
||||
for (unsigned int i = 0; i < count; ++i, ++d, ++s) {
|
||||
*d = *s;
|
||||
}
|
||||
//printf("%s:int16\r\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_UINT32:
|
||||
case GS_PARAM_INT32:
|
||||
case PARAM_X32:
|
||||
case GS_PARAM_FLOAT:
|
||||
if (!((intptr_t)src & 3) && !((intptr_t)dst & 3)) {
|
||||
// (u)int32 aligned correctly
|
||||
const uint32_t * s = src;
|
||||
uint32_t * d = dst;
|
||||
const unsigned int count = (size / sizeof(*d));
|
||||
for (unsigned int i = 0; i < count; ++i, ++d, ++s) {
|
||||
*d = *s;
|
||||
}
|
||||
//printf("%s:int32\r\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case GS_PARAM_UINT64:
|
||||
case GS_PARAM_INT64:
|
||||
case PARAM_X64:
|
||||
case GS_PARAM_DOUBLE:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fallback - do byte copy
|
||||
memcpy(dst, src, size);
|
||||
}
|
||||
|
||||
gs_error_t gs_param_table_lock(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (tinst->lock) {
|
||||
return gs_mutex_lock(tinst->lock);
|
||||
}
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_table_unlock(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (tinst->lock) {
|
||||
return gs_mutex_unlock(tinst->lock);
|
||||
}
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static gs_error_t gs_param_table_lock_free(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (tinst && tinst->lock) {
|
||||
gs_mutex_destroy(tinst->lock);
|
||||
tinst->lock = NULL;
|
||||
}
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_table_free(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (tinst) {
|
||||
if (tinst->flags & GS_PARAM_TABLE_F_ALLOC_MEMORY) {
|
||||
free(tinst->memory);
|
||||
}
|
||||
if (tinst->flags & GS_PARAM_TABLE_F_ALLOC_ROWS) {
|
||||
free((void*)tinst->rows);
|
||||
}
|
||||
if (tinst->lock) {
|
||||
gs_param_table_lock_free(tinst);
|
||||
}
|
||||
memset(tinst, 0, sizeof(*tinst));
|
||||
}
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
static void checksum_update(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
const uint16_t no_swap = gs_fletcher16(tinst->rows, (sizeof(*tinst->rows) * tinst->row_count));
|
||||
|
||||
// fletcher16 with swapped fields > 1 byte
|
||||
gs_fletcher16_t f16;
|
||||
gs_fletcher16_init(&f16);
|
||||
for (unsigned int i = 0; i < tinst->row_count; ++i) {
|
||||
gs_param_table_row_t row = tinst->rows[i];
|
||||
row.addr = gs_bswap_16(row.addr);
|
||||
gs_fletcher16_update(&f16, &row, sizeof(row));
|
||||
}
|
||||
const uint16_t swap = gs_fletcher16_finalize(&f16);
|
||||
|
||||
if (gs_endian_big()) {
|
||||
tinst->checksum_be = no_swap;
|
||||
tinst->checksum_le = swap;
|
||||
} else {
|
||||
tinst->checksum_be = swap;
|
||||
tinst->checksum_le = no_swap;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t gs_param_table_checksum_be(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (tinst && tinst->rows && tinst->row_count) {
|
||||
if (tinst->checksum_be == 0) {
|
||||
checksum_update(tinst);
|
||||
}
|
||||
return tinst->checksum_be;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t gs_param_table_checksum_le(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (tinst && tinst->rows && tinst->row_count) {
|
||||
if (tinst->checksum_le == 0) {
|
||||
checksum_update(tinst);
|
||||
}
|
||||
return tinst->checksum_le;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t gs_param_table_checksum(gs_param_table_instance_t * tinst)
|
||||
{
|
||||
if (gs_endian_big()) {
|
||||
return gs_param_table_checksum_be(tinst);
|
||||
} else {
|
||||
return gs_param_table_checksum_le(tinst);
|
||||
}
|
||||
}
|
||||
|
||||
gs_error_t gs_param_get(gs_param_table_instance_t * tinst, uint16_t addr, gs_param_type_t type, void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
if (tinst == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
|
||||
if ((addr + value_size) > tinst->memory_size) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
gs_error_t error = GS_ERROR_NOT_SUPPORTED;
|
||||
if (tinst->function_interface.get) {
|
||||
error = (tinst->function_interface.get)(tinst->function_interface.context, tinst, addr, type, value, value_size, flags);
|
||||
} else if (tinst->memory) {
|
||||
gs_param_table_lock(tinst);
|
||||
_copy_data(type, value, ((uint8_t*)(tinst->memory)) + addr, value_size);
|
||||
gs_param_table_unlock(tinst);
|
||||
error = GS_OK;
|
||||
}
|
||||
|
||||
if ((error == GS_OK) && (flags & GS_PARAM_SF_TO_BIG_ENDIAN) && !gs_endian_big()) {
|
||||
gs_param_htobe(type, value);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_set(gs_param_table_instance_t * tinst, uint16_t addr, gs_param_type_t type, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
if (tinst == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
|
||||
if ((addr + value_size) > tinst->memory_size) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
if ((flags & GS_PARAM_SF_FROM_BIG_ENDIAN) && !gs_endian_big()) {
|
||||
void * tmp = alloca(value_size); // this must be aligned
|
||||
memcpy(tmp, value, value_size);
|
||||
value = tmp;
|
||||
gs_param_betoh(type, tmp);
|
||||
}
|
||||
|
||||
gs_error_t error = GS_ERROR_NOT_SUPPORTED;
|
||||
if (tinst->function_interface.set) {
|
||||
error = (tinst->function_interface.set)(tinst->function_interface.context, tinst, addr, type, value, value_size, flags);
|
||||
} else if (tinst->memory) {
|
||||
gs_param_table_lock(tinst);
|
||||
_copy_data(type, ((uint8_t*)(tinst->memory)) + addr, value, value_size);
|
||||
gs_param_table_unlock(tinst);
|
||||
|
||||
if (tinst->auto_persist.set && (flags & GS_PARAM_F_AUTO_PERSIST)) {
|
||||
(tinst->auto_persist.set)(tinst, addr, type, value, value_size, flags);
|
||||
}
|
||||
error = GS_OK;
|
||||
}
|
||||
|
||||
// Callbacks
|
||||
if ((error == GS_OK) && tinst->callback && ((flags & GS_PARAM_F_NO_CALLBACK) == 0)) {
|
||||
(tinst->callback)(addr, tinst);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t gs_param_type_size(gs_param_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case GS_PARAM_UINT8:
|
||||
case GS_PARAM_INT8:
|
||||
case PARAM_X8:
|
||||
case GS_PARAM_STRING:
|
||||
case GS_PARAM_DATA:
|
||||
return sizeof(int8_t);
|
||||
case GS_PARAM_INT16:
|
||||
case GS_PARAM_UINT16:
|
||||
case PARAM_X16:
|
||||
return sizeof(int16_t);
|
||||
case GS_PARAM_INT32:
|
||||
case GS_PARAM_UINT32:
|
||||
case PARAM_X32:
|
||||
return sizeof(int32_t);
|
||||
case GS_PARAM_INT64:
|
||||
case GS_PARAM_UINT64:
|
||||
case PARAM_X64:
|
||||
return sizeof(int64_t);
|
||||
case GS_PARAM_DOUBLE:
|
||||
return sizeof(double);
|
||||
case GS_PARAM_FLOAT:
|
||||
return sizeof(float);
|
||||
case GS_PARAM_BOOL:
|
||||
return sizeof(bool);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void * gs_param_table_get_memory(gs_param_table_instance_t * tinst, size_t * return_size)
|
||||
{
|
||||
if (tinst && tinst->memory) {
|
||||
if (return_size) {
|
||||
*return_size = tinst->memory_size;
|
||||
}
|
||||
return tinst->memory;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * gs_param_table_get_rows(gs_param_table_instance_t * tinst, size_t * return_count)
|
||||
{
|
||||
if (tinst && tinst->rows && tinst->row_count) {
|
||||
if (return_count) {
|
||||
*return_count = tinst->row_count;
|
||||
}
|
||||
return tinst->rows;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t gs_param_table_instance_size(void)
|
||||
{
|
||||
return sizeof(gs_param_table_instance_t);
|
||||
}
|
||||
|
||||
gs_param_table_instance_t * gs_param_table_instance_clear(void * var, size_t var_size)
|
||||
{
|
||||
gs_param_table_instance_t * tinst = NULL;
|
||||
if (var && (var_size >= sizeof(*tinst))) {
|
||||
tinst = (gs_param_table_instance_t *) var;
|
||||
memset(tinst, 0, sizeof(*tinst));
|
||||
}
|
||||
return tinst;
|
||||
}
|
||||
|
||||
gs_param_table_instance_t * gs_param_table_instance_alloc(void)
|
||||
{
|
||||
return calloc(1, sizeof(gs_param_table_instance_t));
|
||||
}
|
||||
|
||||
gs_error_t gs_param_get_string(gs_param_table_instance_t * tinst, uint16_t addr, char * buf, size_t buf_size, uint32_t flags)
|
||||
{
|
||||
if (tinst == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (buf == NULL) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * param = gs_param_row_by_address(addr, tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
if (buf_size <= param->size) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
|
||||
gs_error_t error = gs_param_get(tinst, addr, param->type, buf, param->size, flags);
|
||||
buf[param->size] = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
gs_error_t gs_param_set_string(gs_param_table_instance_t * tinst, uint16_t addr, const char * value, uint32_t flags)
|
||||
{
|
||||
if (tinst == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (value == NULL) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * param = gs_param_row_by_address(addr, tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
const size_t len = strlen(value) + 1;
|
||||
if (len > GS_PARAM_SIZE(param)) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
|
||||
return gs_param_set(tinst, addr, param->type, value, len, flags); // flags have full control
|
||||
}
|
||||
|
||||
gs_error_t gs_param_get_data(gs_param_table_instance_t * tinst, uint16_t addr, void * buf, size_t buf_size, uint32_t flags)
|
||||
{
|
||||
if (tinst == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (buf == NULL) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * param = gs_param_row_by_address(addr, tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
if (buf_size < param->size) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
|
||||
return gs_param_get(tinst, addr, param->type, buf, param->size, flags);
|
||||
}
|
||||
|
||||
gs_error_t gs_param_set_data(gs_param_table_instance_t * tinst, uint16_t addr, const void * value, size_t value_size, uint32_t flags)
|
||||
{
|
||||
if (tinst == NULL) {
|
||||
return GS_ERROR_HANDLE;
|
||||
}
|
||||
if (value == NULL) {
|
||||
return GS_ERROR_ARG;
|
||||
}
|
||||
|
||||
const gs_param_table_row_t * param = gs_param_row_by_address(addr, tinst->rows, tinst->row_count);
|
||||
if (param == NULL) {
|
||||
return GS_ERROR_RANGE;
|
||||
}
|
||||
|
||||
if (value_size > GS_PARAM_SIZE(param)) {
|
||||
return GS_ERROR_OVERFLOW;
|
||||
}
|
||||
|
||||
return gs_param_set(tinst, addr, param->type, value, value_size, flags); // flags have full control
|
||||
}
|
69
gomspace/libparam_client/wscript
Normal file
69
gomspace/libparam_client/wscript
Normal file
@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# Copyright (c) 2013-2018 GomSpace A/S. All rights reserved.
|
||||
|
||||
import os
|
||||
import gs_gcc
|
||||
import gs_doc
|
||||
|
||||
APPNAME = 'param_client'
|
||||
|
||||
|
||||
def options(ctx):
|
||||
ctx.load('gs_gcc gs_doc')
|
||||
gs_gcc.gs_recurse(ctx)
|
||||
|
||||
gr = ctx.add_option_group('libparam client options')
|
||||
gr.add_option('--param_client-disable-cmd', action='store_true', help='Disable GOSH commands')
|
||||
gr.add_option('--param-enable-atomic-access', action='store_true', help='Enable atomic read/write of 16/32/float')
|
||||
|
||||
|
||||
def configure(ctx):
|
||||
ctx.load('gs_gcc gs_doc')
|
||||
|
||||
ctx.env.append_unique('USE_PARAM_CLIENT', ['gscsp', 'util'])
|
||||
|
||||
ctx.env.append_unique('FILES_PARAM_CLIENT', ['src/*.c', 'src/rparam/*.c',
|
||||
'src/pp/*.c', 'src/pp/i2c/*.c', 'src/pp/spi/*.c'])
|
||||
|
||||
if not ctx.options.param_client_disable_cmd:
|
||||
ctx.env.append_unique('FILES_PARAM_CLIENT', ['src/rparam/cmd/*.c', 'src/pp/cmd/*.c'])
|
||||
|
||||
if ctx.options.param_enable_atomic_access:
|
||||
ctx.env.append_unique('DEFINES_PARAM_CLIENT', ['GS_PARAM_ATOMIC_ACCESS=1'])
|
||||
|
||||
ctx.gs_register_handler(function='param_gen_4_0', filepath='./tools/waf_param.py')
|
||||
ctx.gs_register_handler(function='param_gen_4_2', filepath='./tools/waf_param.py')
|
||||
ctx.gs_register_handler(function='param_gen_4_3', filepath='./tools/waf_param.py')
|
||||
|
||||
ctx.gs_add_doxygen(exclude=['*/include/deprecated/param/*', '*/include/gs/param/internal/*'])
|
||||
|
||||
gs_gcc.gs_recurse(ctx)
|
||||
|
||||
|
||||
def build(ctx):
|
||||
gs_gcc.gs_recurse(ctx)
|
||||
|
||||
public_include = ctx.gs_include(name=APPNAME,
|
||||
includes=['include', 'include/deprecated', 'include/deprecated/param'])
|
||||
|
||||
if ctx.env.GS_ARCH not in ['avr8']:
|
||||
ctx.gs_objects(source=ctx.path.ant_glob(ctx.env.FILES_PARAM_CLIENT),
|
||||
target=APPNAME,
|
||||
defines=ctx.env.DEFINES_PARAM_CLIENT,
|
||||
use=ctx.env.USE_PARAM_CLIENT + [public_include])
|
||||
|
||||
ctx.gs_shlib(source=ctx.path.ant_glob(ctx.env.FILES_PARAM_CLIENT),
|
||||
target=APPNAME,
|
||||
defines=ctx.env.DEFINES_PARAM_CLIENT,
|
||||
gs_use_shlib=ctx.env.USE_PARAM_CLIENT + [public_include])
|
||||
|
||||
ctx.gs_python_bindings(source=ctx.path.ant_glob('src/bindings/python/pyparam.c'),
|
||||
target=APPNAME,
|
||||
gs_use_shlib=ctx.env.USE_PARAM_CLIENT + [APPNAME, public_include],
|
||||
package='libparam')
|
||||
|
||||
|
||||
def gs_dist(ctx):
|
||||
gs_gcc.gs_recurse(ctx)
|
||||
ctx.add_default_files(source_module=True)
|
Reference in New Issue
Block a user