save failed integration state

This commit is contained in:
2020-11-26 10:24:23 +01:00
parent 77970418d8
commit 17fc4b0de1
194 changed files with 45450 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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);
}

View 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;
}

View 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);
}

View 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;
}

View 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);
}

View 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;

View 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;
}

View 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);

View 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, &param_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);
}

View 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;
}

View 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

View 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;
}

View 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
}

View 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)