pdock 60 test task

This commit is contained in:
2020-11-23 11:42:22 +01:00
parent dd4cacb538
commit fcb328393b
323 changed files with 132 additions and 41250 deletions

View File

@ -1,34 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/linux/argp.h>
#include <gs/util/linux/exitcode.h>
#include <gs/util/string.h>
void gs_argp_parse(const struct argp * argp,
int argc, char ** argv,
unsigned int flags, int * return_arg_index,
const char * revision)
{
if (gs_string_empty(revision) == false) {
argp_program_version = revision;
}
int arg_index = 0;
int res = argp_parse(argp, argc, argv, 0, &arg_index, 0);
if (res) {
printf("Failed to parse argument/option (result: %d)\n", res);
exit(GS_EXITCODE_USAGE);
}
if ((return_arg_index == NULL) && (arg_index < argc)) {
// application doesn't expect unhandled arguments
for (int i = arg_index; i < argc; ++i) {
printf("Unhandled/unknown argument: [%s]\n", argv[i]);
}
exit(GS_EXITCODE_USAGE);
}
if (return_arg_index) {
*return_arg_index = arg_index;
}
}

View File

@ -1,68 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/clock.h>
#include <gs/util/rtc.h>
#include <time.h>
#include <errno.h>
void gs_clock_get_time(gs_timestamp_t * time)
{
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
time->tv_sec = (uint32_t) now.tv_sec;
time->tv_nsec = (uint32_t) now.tv_nsec;
}
gs_error_t gs_clock_set_time(const gs_timestamp_t * time)
{
struct timespec now;
now.tv_sec = time->tv_sec;
now.tv_nsec = time->tv_nsec;
int res = clock_settime(CLOCK_REALTIME, &now);
if (res != 0) {
return gs_error(errno);
}
gs_error_t error = GS_OK;
if (gs_rtc_supported() == GS_OK) {
error = gs_rtc_set_time(time);
}
return error;
}
void gs_clock_get_monotonic(gs_timestamp_t * time)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
time->tv_sec = (uint32_t) now.tv_sec;
time->tv_nsec = (uint32_t) now.tv_nsec;
}
uint64_t gs_clock_get_nsec(void)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return (((uint64_t)now.tv_sec) * GS_TIMESTAMP_NSEC_PER_SEC) + ((uint64_t)now.tv_nsec);
}
/**
Required by libcsp.
Proto-typed in ./libcsp/include/csp/arch/csp_clock.h, but with different argumet!
__attribute__((weak)) extern void clock_get_time(csp_timestamp_t * time);
__attribute__((weak)) extern void clock_set_time(csp_timestamp_t * time);
*/
void clock_get_time(gs_timestamp_t * time)
{
gs_clock_get_time(time);
}
void clock_set_time(const gs_timestamp_t * time)
{
gs_clock_set_time(time);
}

View File

@ -1,76 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/linux/command_line.h>
#include <gs/util/linux/signal.h>
#include <gs/util/string.h>
#define KEY_IGNORE_CTRLC 200
static bool ignore_ctrlc;
static int parser(int key, char *arg, struct argp_state *state)
{
switch (key) {
case KEY_IGNORE_CTRLC:
ignore_ctrlc = true;
gs_signal_ignore(SIGINT);
break;
case 'h':
argp_help(state->root_argp, state->out_stream, ARGP_HELP_STD_HELP, state->name);
exit(0);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static const struct argp_option options[] = {
{
.name = "ignore-ctrlc",
.key = KEY_IGNORE_CTRLC,
.doc = "Ignore/disable CTRL-C"
},
{0}
};
static const struct argp argp_console = {.options = options, .parser = parser};
const struct argp_child gs_console_command_line_ignore_ctrlc_argp = {.argp = &argp_console};
bool gs_command_line_ignore_ctrlc(void)
{
return ignore_ctrlc;
}
static const struct argp_option help_options[] = {
{
.name = "help",
.key = 'h',
.doc = "Give this help list"
},
{0}
};
static const struct argp gs_argp_help = {.options = help_options, .parser = parser};
const struct argp_child gs_help_command_line_argp = {.argp = &gs_argp_help};
const char * gs_command_line_program_name(const char * argv)
{
if (gs_string_empty(argv) == false) {
const char * name = strrchr(argv, '/');
if (name) {
// skip slash
++name;
if (gs_string_empty(name) == false) {
return name;
}
} else {
return argv;
}
}
return "<program>";
}

View File

@ -1,28 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/unistd.h>
#include <unistd.h>
#include <errno.h>
gs_error_t gs_getcwd(char * buf, size_t bufsize)
{
if (buf && bufsize) {
char * wd = getcwd(buf, bufsize);
if (wd) {
return GS_OK;
}
switch(errno) {
case ENAMETOOLONG:
case ERANGE:
return GS_ERROR_RANGE;
case EACCES:
case ENOENT:
return GS_ERROR_NOT_FOUND;
default:
break;
}
}
return GS_ERROR_ARG;
}

View File

@ -1,22 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/delay.h>
#include <unistd.h>
#include <gs/util/time.h>
void gs_delay_us(uint32_t time_us)
{
uint64_t ns = time_us;
ns *= 1000LL;
gs_time_sleep_ns(ns);
}
uint16_t gs_delay_ts_get(void)
{
return 0;
}
void gs_delay_from_ts(uint16_t ts, uint16_t delay)
{
}

View File

@ -1,308 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/drivers/can/can.h>
#include <gs/util/thread.h>
#include <gs/util/log.h>
#include <gs/util/string.h>
#include <gs/util/time.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
typedef struct {
// true if handle is in use
bool inuse;
// opened socket
int can_socket;
// receiver thread
gs_thread_t rxthread;
// received data callback
gs_can_rxdata_callback_t rx_callback;
void * user_data;
} gs_can_handle_t;
#define MAX_CAN_HANDLES 10
static gs_can_handle_t can_handles[MAX_CAN_HANDLES];
static int gs_can_alloc_handle(void)
{
int handle_id;
for (handle_id = 0; (handle_id < MAX_CAN_HANDLES) && (can_handles[handle_id].inuse == true); ++handle_id);
if (handle_id < MAX_CAN_HANDLES) {
gs_can_handle_t * handle = &can_handles[handle_id];
memset(handle, 0, sizeof(*handle));
handle->inuse = true;
handle->can_socket = -1;
}
return handle_id;
}
static inline gs_can_handle_t * gs_can_handle(uint8_t hdl)
{
if (hdl >= MAX_CAN_HANDLES) {
return NULL;
}
if (can_handles[hdl].inuse == false) {
return NULL;
}
return &can_handles[hdl];
}
static void * gs_can_rx_thread(void * parameter)
{
int hdl = (int) GS_TYPES_PTR2INT(parameter);
log_debug("%s: running, hdl: %d", __FUNCTION__, hdl);
gs_can_handle_t * handle = gs_can_handle(hdl);
if (handle == NULL) {
log_error("%s: CAN handle: %d is invalid or not opened", __FUNCTION__, hdl);
gs_thread_exit(NULL);
}
while (1) {
/* Read CAN frame */
struct can_frame frame;
ssize_t nbytes = read(handle->can_socket, &frame, sizeof(frame));
if (nbytes < 0) {
log_error("%s: read() on socket failed, error: %s", __FUNCTION__, strerror(errno));
continue;
}
if (nbytes != sizeof(frame)) {
log_warning("%s: read() returned incomplete CAN frame of %d bytes - ignoring frame", __FUNCTION__, (int) nbytes);
continue;
}
/* Frame type */
if (frame.can_id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) {
/* Drop error and remote frames */
log_warning("%s: discarding ERR/RTR frame, can_id: 0x%x", __FUNCTION__, frame.can_id);
continue;
}
const bool extId = (frame.can_id & CAN_EFF_FLAG) ? true : false;
if (extId) {
frame.can_id &= CAN_EFF_MASK;
} else {
frame.can_id &= CAN_SFF_MASK;
}
handle->rx_callback(hdl, frame.can_id, extId, frame.data, frame.can_dlc, gs_time_rel_ms(), handle->user_data, false);
}
/* We should never reach this point */
return NULL;
}
static gs_error_t gs_can_send(uint8_t hdl, uint32_t canMsgId, bool extended, const void * data, size_t data_size, int timeout_ms)
{
gs_can_handle_t * handle = gs_can_handle(hdl);
if (handle == NULL) {
return GS_ERROR_HANDLE;
}
if ((data == NULL) || (data_size > 8)) {
log_error("%s: invalid data: %p, data_size: %u", __FUNCTION__, (void*) data, (unsigned int) data_size);
return GS_ERROR_ARG;
}
struct can_frame frame;
memset(&frame, 0, sizeof(frame));
frame.can_id = canMsgId;
if (extended) {
frame.can_id |= CAN_EFF_FLAG;
}
memcpy(frame.data, data, data_size);
frame.can_dlc = (uint8_t) data_size;
const int DELAY_MS = 10;
while (write(handle->can_socket, &frame, sizeof(frame)) != sizeof(frame)) {
if ((timeout_ms > 0) && (errno == ENOBUFS)) {
// Wait a bit and try again
gs_thread_sleep_ms(DELAY_MS);
timeout_ms -= DELAY_MS;
} else {
gs_error_t gserror = gs_error(errno);
log_error("%s: write() failed, error: %s", __FUNCTION__, gs_error_string(gserror));
return gserror;
}
}
return GS_OK;
}
gs_error_t gs_can_send_standard(uint8_t hdl, uint32_t canMsgId, const void * data, size_t data_size, int timeout_ms)
{
return gs_can_send(hdl, canMsgId, false, data, data_size, timeout_ms);
}
gs_error_t gs_can_send_extended(uint8_t hdl, uint32_t canExtMsgId, const void * data, size_t data_size, int timeout_ms)
{
return gs_can_send(hdl, canExtMsgId, true, data, data_size, timeout_ms);
}
static void gs_can_close(gs_can_handle_t * handle)
{
if (handle->can_socket >= 0) {
close(handle->can_socket);
}
// free instance - must be the last thing done, no lock needed
handle->inuse = false;
}
gs_error_t gs_can_open(const char * ifname, int * return_handle)
{
if ((ifname == NULL) || (ifname[0] == 0) || (return_handle == NULL)) {
log_error("%s: invalid CAN interface name", __FUNCTION__);
return GS_ERROR_ARG;
}
int handle_id = gs_can_alloc_handle();
if (handle_id >= MAX_CAN_HANDLES) {
log_error("%s: no free handles", __FUNCTION__);
return GS_ERROR_FULL;
}
gs_can_handle_t * handle = &can_handles[handle_id];
/* Create socket */
if ((handle->can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
gs_error_t gserror = gs_error(errno);
log_error("%s: socket() failed, error: %s", __FUNCTION__, gs_error_string(gserror));
gs_can_close(handle);
return gserror;
}
/* Locate interface */
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
if (ioctl(handle->can_socket, SIOCGIFINDEX, &ifr) < 0) {
gs_error_t gserror = gs_error(errno);
log_error("%s: ioctl(ifname: [%s]) failed, error: %s", __FUNCTION__, ifr.ifr_name, gs_error_string(gserror));
gs_can_close(handle);
return gserror;
}
/* Bind the socket to CAN interface */
struct sockaddr_can addr;
memset(&addr, 0, sizeof(addr));
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(handle->can_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
gs_error_t gserror = gs_error(errno);
log_error("%s: bind() failed, error: %s", __FUNCTION__, gs_error_string(gserror));
gs_can_close(handle);
return gserror;
}
*return_handle = handle_id;
return GS_OK;
}
static gs_error_t gs_can_set_filter_mask(uint8_t hdl, bool extended, uint32_t canMsgId, uint32_t mask, gs_can_rxdata_callback_t rx_callback, void * user_data)
{
gs_can_handle_t * handle = gs_can_handle(hdl);
if (handle == NULL) {
return GS_ERROR_HANDLE;
}
if (extended) {
if ((canMsgId > CAN_EFF_MASK) || (mask > CAN_EFF_MASK)) {
return GS_ERROR_ARG;
}
} else {
if ((canMsgId > CAN_SFF_MASK) || (mask > CAN_SFF_MASK)) {
return GS_ERROR_ARG;
}
}
handle->rx_callback = rx_callback;
handle->user_data = user_data;
struct can_filter filter;
filter.can_id = canMsgId;
filter.can_mask = mask;
if (extended == false) {
filter.can_mask |= (CAN_EFF_MASK & ~CAN_SFF_MASK);
}
if (setsockopt(handle->can_socket, SOL_CAN_RAW, CAN_RAW_FILTER, &filter, sizeof(filter)) < 0) {
gs_error_t gserror = gs_error(errno);
log_error("%s: setsockopt(id: 0x%x, mask: 0x%x) failed, error: %s", __FUNCTION__, canMsgId, mask, gs_error_string(gserror));
return gserror;
}
return GS_OK;
}
gs_error_t gs_can_set_standard_filter_mask(uint8_t hdl, uint32_t canMsgId, uint32_t mask, gs_can_rxdata_callback_t rx_callback, void * user_data)
{
return gs_can_set_filter_mask(hdl, false, canMsgId, mask, rx_callback, user_data);
}
gs_error_t gs_can_set_extended_filter_mask(uint8_t hdl, uint32_t canExtMsgId, uint32_t mask, gs_can_rxdata_callback_t rx_callback, void * user_data)
{
return gs_can_set_filter_mask(hdl, true, canExtMsgId, mask, rx_callback, user_data);
}
gs_error_t gs_can_start(uint8_t hdl)
{
gs_can_handle_t * handle = gs_can_handle(hdl);
if (handle == NULL) {
return GS_ERROR_HANDLE;
}
if (handle->rxthread) {
return GS_OK;
}
/* Create receiver thread */
gs_error_t gserror = gs_thread_create("rxcan", gs_can_rx_thread, GS_TYPES_INT2PTR(hdl), 0, GS_THREAD_PRIORITY_HIGH, 0, &handle->rxthread);
if (gserror) {
log_error("s: gs_thread_create() failed, error: %s", gs_error_string(gserror));
return gserror;
}
return GS_OK;
}
gs_error_t gs_can_stop(uint8_t hdl)
{
gs_can_handle_t * handle = gs_can_handle(hdl);
if (handle == NULL) {
return GS_ERROR_HANDLE;
}
return GS_ERROR_NOT_IMPLEMENTED;
}
gs_error_t gs_can_error_state(uint8_t hdl, bool * restart_required)
{
gs_can_handle_t * handle = gs_can_handle(hdl);
if (handle == NULL) {
return GS_ERROR_HANDLE;
}
if (restart_required) {
*restart_required = false;
}
// missing error state check on CAN layer
return GS_OK;
}

View File

@ -1,102 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/check.h>
#include <gs/util/linux/drivers/gpio/gpio.h>
#define MAX_DRIVERS 20
typedef struct {
gs_gpio_driver_entry_t entry;
bool in_use;
} gs_gpio_driver_handle_t;
static gs_gpio_driver_handle_t gpio_drivers[MAX_DRIVERS];
static uint8_t max_index_in_use = 0;
static inline gs_gpio_driver_entry_t * gs_find_driver_entry(gs_gpio_t * gpio)
{
gs_gpio_driver_handle_t * handle;
for (int i = max_index_in_use; i >= 0; i--) {
handle = &gpio_drivers[i];
if (((gpio->pin == handle->entry.pin) || (handle->entry.pin == GS_GPIO_ALL_PINS)) &&
((gpio->port == handle->entry.port) || (handle->entry.port == GS_GPIO_ALL_PORTS)) &&
(handle->in_use == true)) {
return &handle->entry;
}
}
return NULL;
}
gs_error_t gs_gpio_get(gs_gpio_t gpio, bool *value)
{
gs_gpio_driver_entry_t * driver_entry = gs_find_driver_entry(&gpio);
if (driver_entry) {
if (driver_entry->driver->get_handler) {
return driver_entry->driver->get_handler(gpio, value, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
bool gs_gpio_get_nc(gs_gpio_t gpio)
{
gs_gpio_driver_entry_t * driver_entry = gs_find_driver_entry(&gpio);
if (driver_entry) {
if (driver_entry->driver->get_nc_handler) {
return driver_entry->driver->get_nc_handler(gpio, driver_entry->driver_data);
}
}
return false;
}
gs_error_t gs_gpio_set(gs_gpio_t gpio, bool value)
{
gs_gpio_driver_entry_t * driver_entry = gs_find_driver_entry(&gpio);
if (driver_entry) {
if (driver_entry->driver->set_handler) {
return driver_entry->driver->set_handler(gpio, value, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
void gs_gpio_set_nc(gs_gpio_t gpio, bool value)
{
gs_gpio_driver_entry_t * driver_entry = gs_find_driver_entry(&gpio);
if (driver_entry) {
if (driver_entry->driver->set_nc_handler) {
driver_entry->driver->set_nc_handler(gpio, value, driver_entry->driver_data);
}
}
}
gs_error_t gs_gpio_init_as_interrupt(gs_gpio_t gpio, const gs_interrupt_conf_t * conf)
{
gs_gpio_driver_entry_t * driver_entry = gs_find_driver_entry(&gpio);
if (driver_entry) {
if (driver_entry->driver->init_as_interrupt_handler) {
return driver_entry->driver->init_as_interrupt_handler(gpio, conf, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_gpio_register_driver(const gs_gpio_driver_entry_t * driver_entry)
{
GS_CHECK_ARG(driver_entry != NULL);
GS_CHECK_ARG(driver_entry->driver != NULL);
gs_gpio_driver_handle_t * handle;
for (uint8_t i = 0; i < MAX_DRIVERS; i++) {
handle = &gpio_drivers[i];
if (handle->in_use == false) {
handle->entry = *driver_entry;
handle->in_use = true;
max_index_in_use = i;
return GS_OK;
}
}
/* Not enough space in buffer */
return GS_ERROR_FULL;
}

View File

@ -1,145 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
/**
@file
@brief GPIO Implementation for Linux of the GPIO API in libutil.
The GPIO driver provides a simple interface toward driving HW GPIO's.
*/
#include <gs/util/linux/drivers/gpio/gpio_sysfs.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <gs/util/log.h>
#include <gs/util/linux/sysfs_helper.h>
gs_error_t gs_gpio_sysfs_initialize(gs_gpio_t gpio, bool output,bool init_value, bool active_low)
{
char gpio_pin_str[6];
snprintf(gpio_pin_str, sizeof(gpio_pin_str), "%d", gpio.pin);
/* Try to unexport first */
gs_sysfs_write_file("/sys/class/gpio/unexport", gpio_pin_str);
if (gs_sysfs_write_file("/sys/class/gpio/export", gpio_pin_str) != GS_OK)
{
log_warning("failed to export GPIO %s: %s", gpio_pin_str, strerror(errno));
return GS_ERROR_NOT_SUPPORTED;
}
char gpio_sys_fname[128];
snprintf(gpio_sys_fname, sizeof(gpio_sys_fname), "/sys/class/gpio/gpio%d/active_low", gpio.pin);
const char * active_low_str = active_low ? "1" : "0";
if (gs_sysfs_write_file(gpio_sys_fname, active_low_str) != GS_OK)
{
log_warning("failed to set GPIO %d active_low: %s", gpio.pin, strerror(errno));
return GS_ERROR_NOT_SUPPORTED;
}
snprintf(gpio_sys_fname, sizeof(gpio_sys_fname), "/sys/class/gpio/gpio%d/direction", gpio.pin);
/* Glitch-free output set (high/low makes pin an output and sets value to 1/0 respectively)*/
const char * dir = output ? (init_value ? "high" : "low") : "in";
if (gs_sysfs_write_file(gpio_sys_fname, dir) != GS_OK)
{
log_warning("failed to set GPIO %d direction: %s", gpio.pin, strerror(errno));
return GS_ERROR_NOT_SUPPORTED;
}
return GS_OK;
}
gs_error_t gs_gpio_sysfs_get(gs_gpio_t gpio, bool *value, void * driver_data)
{
char gpio_sys_fname[128];
snprintf(gpio_sys_fname, sizeof(gpio_sys_fname), "/sys/class/gpio/gpio%d/value", gpio.pin);
if (access(gpio_sys_fname, R_OK) != 0)
{
log_error("GPIO %d not initialized - Can't read the input.", gpio.pin);
return GS_ERROR_ACCESS;
}
char value_str[10];
gs_error_t ret = gs_sysfs_read_file(gpio_sys_fname, value_str, sizeof(value_str));
if (ret == GS_OK)
{
if (strcmp(value_str, "1") == 0)
*value = true;
else
*value = false;
}
return ret;
}
bool gs_gpio_sysfs_get_nc(gs_gpio_t gpio, void * driver_data)
{
char gpio_sys_fname[128];
snprintf(gpio_sys_fname, sizeof(gpio_sys_fname), "/sys/class/gpio/gpio%d/value", gpio.pin);
if (access(gpio_sys_fname, R_OK) != 0)
{
log_error("GPIO %d not initialized - Can't read the input.", gpio.pin);
return 0;
}
char value_str[10];
gs_sysfs_read_file(gpio_sys_fname, value_str, sizeof(value_str));
if (strncmp(value_str, "1", 10) == 0) {
return true;
} else {
return false;
}
}
gs_error_t gs_gpio_sysfs_set(gs_gpio_t gpio, bool value, void * driver_data)
{
const char *value_str = value ? "1" : "0";
char gpio_sys_fname[128];
snprintf(gpio_sys_fname, sizeof(gpio_sys_fname), "/sys/class/gpio/gpio%d/value", gpio.pin);
if (access(gpio_sys_fname, W_OK) == 0)
{
return gs_sysfs_write_file(gpio_sys_fname, value_str);
}
log_error("GPIO %d not initialized - Can't set the output.", gpio.pin);
return GS_ERROR_ACCESS;
}
void gs_gpio_sysfs_set_nc(gs_gpio_t gpio, bool value, void * driver_data)
{
const char *value_str = value ? "1" : "0";
char gpio_sys_fname[128];
snprintf(gpio_sys_fname, sizeof(gpio_sys_fname), "/sys/class/gpio/gpio%d/value", gpio.pin);
if (access(gpio_sys_fname, W_OK) == 0)
{
gs_sysfs_write_file(gpio_sys_fname, value_str);
return;
}
log_error("GPIO %d not initialized - Can't set the output.", gpio.pin);
}
gs_error_t gs_gpio_sysfs_init_as_interrupt(gs_gpio_t gpio, const gs_interrupt_conf_t * conf, void * driver_data)
{
return GS_ERROR_NOT_IMPLEMENTED;
}
const gs_gpio_driver_t gs_gpio_sysfs_driver = {
.get_handler = gs_gpio_sysfs_get,
.get_nc_handler = gs_gpio_sysfs_get_nc,
.set_handler = gs_gpio_sysfs_set,
.set_nc_handler = gs_gpio_sysfs_set_nc,
.init_as_interrupt_handler = gs_gpio_sysfs_init_as_interrupt,
};

View File

@ -1,171 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/linux/drivers/gpio/gpio_virtual.h>
#define MAX_VPINS 500
#define FALLING_EDGE_FLAG 0x1
#define RISING_EDGE_FLAG 0x2
typedef struct {
gs_gpio_t gpio;
bool output;
bool value;
bool in_use;
gs_gpio_isr_t isr;
uint8_t edge_flags;
uint32_t transistions;
} gs_gpio_virtual_t;
static gs_gpio_virtual_t vpins[MAX_VPINS];
gs_error_t gs_gpio_virtual_initialize(gs_gpio_t gpio, bool output, bool value)
{
gs_gpio_virtual_t * pin;
for (uint16_t i = 0; i < MAX_VPINS; i++) {
pin = &vpins[i];
if ((!pin->in_use) || ((pin->gpio.pin == gpio.pin) && (pin->gpio.port == gpio.port))) {
pin->gpio = gpio;
pin->output = output;
pin->value = value;
pin->in_use = true;
return GS_OK;
}
}
return GS_ERROR_FULL;
}
static gs_gpio_virtual_t * find_vpin(gs_gpio_t * gpio)
{
gs_gpio_virtual_t * pin;
for (uint16_t i = 0; i < MAX_VPINS; i++) {
pin = &vpins[i];
if (pin->gpio.pin == gpio->pin) {
if (pin->gpio.port == gpio->port) {
if (pin->in_use) {
return pin;
}
}
}
}
return NULL;
}
gs_error_t gs_gpio_virtual_get(gs_gpio_t gpio, bool *value, void * driver_data)
{
gs_gpio_virtual_t * pin = find_vpin(&gpio);
if (pin) {
*value = pin->value;
return GS_OK;
}
return GS_ERROR_NOT_FOUND;
}
bool gs_gpio_virtual_get_nc(gs_gpio_t gpio, void * driver_data)
{
gs_gpio_virtual_t * pin = find_vpin(&gpio);
if (pin) {
return pin->value;
}
return false;
}
gs_error_t gs_gpio_virtual_set(gs_gpio_t gpio, bool value, void * driver_data)
{
gs_gpio_virtual_t * pin = find_vpin(&gpio);
if (pin) {
if (pin->output) {
if (pin->value != value) {
pin->value = value;
pin->transistions++;
}
return GS_OK;
}
return GS_ERROR_PERM;
}
return GS_ERROR_NOT_FOUND;
}
void gs_gpio_virtual_set_nc(gs_gpio_t gpio, bool value, void * driver_data)
{
gs_gpio_virtual_t * pin = find_vpin(&gpio);
if (pin) {
if (pin->output) {
if (pin->value != value) {
pin->value = value;
pin->transistions++;
}
}
}
}
gs_error_t gs_gpio_virtual_init_as_interrupt(gs_gpio_t gpio, const gs_interrupt_conf_t * conf, void * driver_data)
{
gs_gpio_virtual_t * pin;
for (uint16_t i = 0; i < MAX_VPINS; i++) {
pin = &vpins[i];
if ((!pin->in_use) || ((pin->gpio.pin == gpio.pin) && (pin->gpio.port == gpio.port))) {
pin->gpio = gpio;
pin->output = false;
pin->value = 0;
pin->in_use = true;
pin->isr = conf->isr;
if (conf->falling_edge) {
pin->edge_flags |= FALLING_EDGE_FLAG;
}
if (conf->rising_edge) {
pin->edge_flags |= RISING_EDGE_FLAG;
}
return GS_OK;
}
}
return GS_ERROR_FULL;
}
gs_error_t gs_gpio_virtual_force_set(gs_gpio_t gpio, bool value)
{
gs_gpio_virtual_t * pin = find_vpin(&gpio);
if (pin) {
bool old_value = pin->value;
if (old_value != value) {
pin->value = value;
pin->transistions++;
if (pin->isr) {
if ((old_value == false) && (pin->edge_flags & RISING_EDGE_FLAG)) {
pin->isr(NULL);
} else if ((old_value == true) && (pin->edge_flags & FALLING_EDGE_FLAG)) {
pin->isr(NULL);
}
}
}
return GS_OK;
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_gpio_virtual_get_transistions(gs_gpio_t gpio, uint32_t * transitions)
{
gs_gpio_virtual_t * pin = find_vpin(&gpio);
if (pin) {
*transitions = pin->transistions;
pin->transistions = 0;
return GS_OK;
}
return GS_ERROR_NOT_FOUND;
}
const gs_gpio_driver_t gs_gpio_virtual_driver = {
.get_handler = gs_gpio_virtual_get,
.get_nc_handler = gs_gpio_virtual_get_nc,
.set_handler = gs_gpio_virtual_set,
.set_nc_handler = gs_gpio_virtual_set_nc,
.init_as_interrupt_handler = gs_gpio_virtual_init_as_interrupt,
};
const gs_gpio_driver_entry_t gs_gpio_virtual_driver_entry_all = {
.port = GS_GPIO_ALL_PORTS,
.pin = GS_GPIO_ALL_PINS,
.driver = &gs_gpio_virtual_driver,
.driver_data = NULL,
};

View File

@ -1,144 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <stdio.h>
#include <gs/util/check.h>
#include <gs/util/linux/drivers/i2c/i2c.h>
#define MAX_DRIVERS 20
#define HIGHEST_I2C_ADDR 127
typedef struct {
gs_i2c_master_driver_entry_t entry;
bool in_use;
} gs_i2c_master_driver_handle_t;
typedef struct {
gs_i2c_slave_driver_entry_t entry;
bool in_use;
} gs_i2c_slave_driver_handle_t;
static gs_i2c_master_driver_handle_t master_drivers[MAX_DRIVERS];
static gs_i2c_slave_driver_handle_t slave_drivers[MAX_DRIVERS];
static uint8_t max_index_master_in_use = 0;
static uint8_t max_index_slave_in_use = 0;
gs_error_t gs_i2c_master_transaction(uint8_t device, uint8_t addr, const void * tx,
size_t txlen,
void * rx,
size_t rxlen,
int timeout_ms)
{
GS_CHECK_RANGE(addr <= HIGHEST_I2C_ADDR);
gs_i2c_master_driver_handle_t * handle;
for (int i = max_index_master_in_use; i >= 0; i--) {
handle = &master_drivers[i];
if (((device == handle->entry.device) || (handle->entry.device == GS_I2C_ALL_DEVICES))
&& ((addr == handle->entry.addr) || (handle->entry.addr == GS_I2C_ALL_ADDR))
&& (handle->in_use == true)) {
if (handle->entry.driver->master_transaction_handler) {
return handle->entry.driver->master_transaction_handler(device, addr, tx, txlen, rx, rxlen, timeout_ms, handle->entry.driver_data);
}
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_i2c_master_register_driver(const gs_i2c_master_driver_entry_t * driver_entry)
{
GS_CHECK_ARG(driver_entry != NULL);
GS_CHECK_ARG(driver_entry->driver != NULL);
GS_CHECK_RANGE((driver_entry->addr == GS_I2C_ALL_ADDR) || (driver_entry->addr <= HIGHEST_I2C_ADDR));
gs_i2c_master_driver_handle_t * handle;
for (uint8_t i = 0; i < MAX_DRIVERS; i++) {
handle = &master_drivers[i];
if (handle->in_use == false) {
handle->entry = *driver_entry;
handle->in_use = true;
max_index_master_in_use = i;
return GS_OK;
}
}
/* Not enough space in buffer */
return GS_ERROR_FULL;
}
static inline gs_i2c_slave_driver_entry_t * gs_slave_find_driver_entry(uint8_t device)
{
gs_i2c_slave_driver_handle_t * handle;
for (int i = max_index_slave_in_use; i >= 0; i--) {
handle = &slave_drivers[i];
if (((device == handle->entry.device) || (handle->entry.device == GS_I2C_ALL_DEVICES))
&& (handle->in_use == true)) {
return &handle->entry;
}
}
return NULL;
}
gs_error_t gs_i2c_slave_start(uint8_t device)
{
gs_i2c_slave_driver_entry_t * driver_entry = gs_slave_find_driver_entry(device);
if (driver_entry) {
if (driver_entry->driver->start_handler) {
return driver_entry->driver->start_handler(device, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_i2c_slave_set_rx(uint8_t device, gs_i2c_slave_receive_t rx)
{
gs_i2c_slave_driver_entry_t * driver_entry = gs_slave_find_driver_entry(device);
if (driver_entry) {
if (driver_entry->driver->set_rx_handler) {
return driver_entry->driver->set_rx_handler(device, rx, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_i2c_slave_set_get_rx_buf(uint8_t device, gs_i2c_slave_get_rx_buf_t get_rx_buf, size_t buf_length)
{
gs_i2c_slave_driver_entry_t * driver_entry = gs_slave_find_driver_entry(device);
if (driver_entry) {
if (driver_entry->driver->set_get_rx_buf_handler) {
return driver_entry->driver->set_get_rx_buf_handler(device, get_rx_buf, buf_length, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_i2c_slave_set_response(uint8_t device, const uint8_t * tx, size_t tx_length)
{
gs_i2c_slave_driver_entry_t * driver_entry = gs_slave_find_driver_entry(device);
if (driver_entry) {
if (driver_entry->driver->set_response_handler) {
return driver_entry->driver->set_response_handler(device, tx, tx_length, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_i2c_slave_register_driver(const gs_i2c_slave_driver_entry_t * driver_entry)
{
GS_CHECK_ARG(driver_entry != NULL);
GS_CHECK_ARG(driver_entry->driver != NULL);
gs_i2c_slave_driver_handle_t * handle;
for (uint8_t i = 0; i < MAX_DRIVERS; i++) {
handle = &slave_drivers[i];
if (handle->in_use == false) {
handle->entry = *driver_entry;
handle->in_use = true;
max_index_slave_in_use = i;
return GS_OK;
}
}
/* Not enough space in buffer */
return GS_ERROR_FULL;
}

View File

@ -1,137 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <stdio.h>
#include <gs/util/check.h>
#include <gs/util/linux/drivers/spi/spi.h>
#define MAX_DRIVERS 20
typedef struct {
gs_spi_master_driver_entry_t entry;
bool in_use;
} gs_spi_master_driver_handle_t;
typedef struct {
gs_spi_slave_driver_entry_t entry;
bool in_use;
} gs_spi_slave_driver_handle_t;
static gs_spi_master_driver_handle_t master_drivers[MAX_DRIVERS];
static gs_spi_slave_driver_handle_t slave_drivers[MAX_DRIVERS];
static uint8_t max_index_master_in_use = 0;
static uint8_t max_index_slave_in_use = 0;
static inline gs_spi_master_driver_entry_t * gs_master_find_driver_entry(uint8_t slave)
{
gs_spi_master_driver_handle_t * handle;
for (int i = max_index_master_in_use; i >= 0; i--) {
handle = &master_drivers[i];
if (((slave == handle->entry.slave) || (handle->entry.slave == GS_SPI_ALL_SLAVES)) && (handle->in_use == true)) {
return &handle->entry;
}
}
return NULL;
}
gs_error_t gs_spi_master_transaction(uint8_t slave, const void * tx, void * rx, size_t size, int timeout_ms)
{
gs_spi_master_trans_t trans = {.tx = tx, .rx = rx, .size = size};
return gs_spi_master_transactions(slave, &trans, 1, timeout_ms);
}
gs_error_t gs_spi_master_transactions(uint8_t slave, gs_spi_master_trans_t *trans, size_t count, int timeout_ms)
{
gs_spi_master_driver_entry_t * driver_entry = gs_master_find_driver_entry(slave);
if (driver_entry) {
if (driver_entry->driver->master_transactions_handler) {
return driver_entry->driver->master_transactions_handler(slave, trans, count, timeout_ms, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_spi_master_register_driver(const gs_spi_master_driver_entry_t * driver_entry)
{
GS_CHECK_ARG(driver_entry != NULL);
GS_CHECK_ARG(driver_entry->driver != NULL);
gs_spi_master_driver_handle_t * handle;
for (uint8_t i = 0; i < MAX_DRIVERS; i++) {
handle = &master_drivers[i];
if (handle->in_use == false) {
handle->entry = *driver_entry;
handle->in_use = true;
max_index_master_in_use = i;
return GS_OK;
}
}
/* Not enough space in buffer */
return GS_ERROR_FULL;
}
static inline gs_spi_slave_driver_entry_t * gs_slave_find_driver_entry(uint8_t device)
{
gs_spi_slave_driver_handle_t * handle;
for (int i = max_index_slave_in_use; i >= 0; i--) {
handle = &slave_drivers[i];
if (((device == handle->entry.device) || (handle->entry.device == GS_SPI_ALL_DEVICES))
&& (handle->in_use == true)) {
return &handle->entry;
}
}
return NULL;
}
gs_error_t gs_spi_slave_start(uint8_t device)
{
gs_spi_slave_driver_entry_t * driver_entry = gs_slave_find_driver_entry(device);
if (driver_entry) {
if (driver_entry->driver->start_handler) {
return driver_entry->driver->start_handler(device, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_spi_slave_set_rx(uint8_t device, gs_spi_slave_receive_t rx)
{
gs_spi_slave_driver_entry_t * driver_entry = gs_slave_find_driver_entry(device);
if (driver_entry) {
if (driver_entry->driver->set_rx_handler) {
return driver_entry->driver->set_rx_handler(device, rx, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_spi_slave_set_response(uint8_t device, size_t offset, const uint8_t * tx, size_t size)
{
gs_spi_slave_driver_entry_t * driver_entry = gs_slave_find_driver_entry(device);
if (driver_entry) {
if (driver_entry->driver->set_response_handler) {
return driver_entry->driver->set_response_handler(device, offset, tx, size, driver_entry->driver_data);
}
}
return GS_ERROR_NOT_FOUND;
}
gs_error_t gs_spi_slave_register_driver(const gs_spi_slave_driver_entry_t * driver_entry)
{
GS_CHECK_ARG(driver_entry != NULL);
GS_CHECK_ARG(driver_entry->driver != NULL);
gs_spi_slave_driver_handle_t * handle;
for (uint8_t i = 0; i < MAX_DRIVERS; i++) {
handle = &slave_drivers[i];
if (handle->in_use == false) {
handle->entry = *driver_entry;
handle->in_use = true;
max_index_slave_in_use = i;
return GS_OK;
}
}
/* Not enough space in buffer */
return GS_ERROR_FULL;
}

View File

@ -1,30 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <sys/sysinfo.h>
#include <gs/util/drivers/sys/memory.h>
gs_error_t gs_mem_get_int_ram_stat(gs_mem_ram_stat_t * ram_stat)
{
return GS_ERROR_NOT_SUPPORTED;
}
gs_error_t gs_mem_get_ext_ram_stat(gs_mem_ram_stat_t * ram_stat)
{
struct sysinfo info;
int res = sysinfo(&info);
if (res != GS_OK) {
return res;
}
ram_stat->total = info.totalram;
ram_stat->max_available = -1;
ram_stat->min_available = -1;
ram_stat->available = info.freeram;
return GS_OK;
}
gs_mem_ram_type_t gs_mem_get_ram_default()
{
return GS_MEM_RAM_TYPE_EXTERNAL;
}

View File

@ -1,41 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/linux/function.h>
#include <gs/util/string.h>
typedef struct {
const char * short_name;
const char * long_name;
gs_function_t function;
} gs_function_register_t;
static gs_function_register_t registry[10];
gs_error_t gs_function_register(const char * short_name, const char * long_name, gs_function_t function)
{
for (unsigned int i = 0; i < GS_ARRAY_SIZE(registry); ++i) {
gs_function_register_t * cb = &registry[i];
if ((cb->short_name == NULL) && (cb->long_name == NULL)) {
cb->short_name = short_name;
cb->long_name = long_name;
cb->function = function;
return GS_OK;
}
}
return GS_ERROR_FULL;
}
gs_error_t gs_function_invoke(const char * name, void * arg)
{
for (unsigned int i = 0; i < GS_ARRAY_SIZE(registry); ++i) {
gs_function_register_t * cb = &registry[i];
if ((gs_string_empty(cb->short_name) == false) && (strcasecmp(cb->short_name, name) == 0)) {
return (cb->function)(arg);
}
if ((gs_string_empty(cb->long_name) == false) && (strcasecmp(cb->long_name, name) == 0)) {
return (cb->function)(arg);
}
}
return GS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -1,59 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/mutex.h>
#include <errno.h>
#include <stdlib.h>
gs_error_t gs_mutex_create(gs_mutex_t * mutex)
{
if (mutex == NULL) {
return GS_ERROR_ARG;
}
*mutex = malloc(sizeof(pthread_mutex_t));
if (*mutex == NULL) {
return GS_ERROR_ALLOC;
}
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
int res = pthread_mutex_init(*mutex, &attr);
if (res < 0) {
res = gs_error(errno);
free(*mutex);
}
return res;
}
gs_error_t gs_mutex_destroy(gs_mutex_t mutex)
{
int res = GS_OK;
if (mutex) {
res = pthread_mutex_destroy(mutex);
if (res < 0) {
res = gs_error(errno);
}
free(mutex);
}
return res;
}
gs_error_t gs_mutex_lock(gs_mutex_t mutex)
{
int res = pthread_mutex_lock(mutex);
if (res < 0) {
res = gs_error(errno);
}
return res;
}
gs_error_t gs_mutex_unlock(gs_mutex_t mutex)
{
int res = pthread_mutex_unlock(mutex);
if (res < 0) {
res = gs_error(errno);
}
return res;
}

View File

@ -1,217 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
/**
* Inspired by c-pthread-queue by Matthew Dickinson
* http://code.google.com/p/c-pthread-queue/
*/
#include <gs/util/queue.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <limits.h>
#define PTHREAD_QUEUE_ARG GS_ERROR_ARG
#define PTHREAD_QUEUE_EMPTY GS_ERROR_NOT_FOUND
#define PTHREAD_QUEUE_FULL GS_ERROR_FULL
#define PTHREAD_QUEUE_TIMEOUT GS_ERROR_TIMEOUT
#define PTHREAD_QUEUE_OK GS_OK
typedef struct gs_pthread_queue {
uint8_t * buffer;
size_t size;
size_t item_size;
size_t items;
size_t in;
size_t out;
pthread_mutex_t mutex;
pthread_cond_t cond_full;
pthread_cond_t cond_empty;
} pthread_queue_t;
static pthread_queue_t * pthread_queue_create(size_t length, size_t item_size)
{
pthread_queue_t * q = malloc(sizeof(pthread_queue_t));
if (q != NULL) {
q->buffer = malloc(length*item_size);
if (q->buffer != NULL) {
q->size = length;
q->item_size = item_size;
q->items = 0;
q->in = 0;
q->out = 0;
if (pthread_mutex_init(&(q->mutex), NULL) || pthread_cond_init(&(q->cond_full), NULL) || pthread_cond_init(&(q->cond_empty), NULL)) {
free(q->buffer);
free(q);
q = NULL;
}
} else {
free(q);
q = NULL;
}
}
return q;
}
static void pthread_queue_delete(pthread_queue_t * q)
{
if (q) {
free(q->buffer);
free(q);
}
}
static int pthread_queue_enqueue(pthread_queue_t * queue, const void * value, uint32_t timeout)
{
/* Calculate timeout */
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts)) {
return PTHREAD_QUEUE_ARG;
}
uint32_t sec = timeout / 1000;
uint32_t nsec = (timeout - 1000 * sec) * 1000000;
ts.tv_sec += sec;
if (ts.tv_nsec + nsec > 1000000000)
ts.tv_sec++;
ts.tv_nsec = (ts.tv_nsec + nsec) % 1000000000;
/* Get queue lock */
pthread_mutex_lock(&(queue->mutex));
while (queue->items == queue->size) {
int ret = -1;
if (timeout) {
ret = pthread_cond_timedwait(&(queue->cond_full), &(queue->mutex), &ts);
}
if (ret) {
pthread_mutex_unlock(&(queue->mutex));
return PTHREAD_QUEUE_TIMEOUT;
}
}
/* Coby object from input buffer */
memcpy(queue->buffer+(queue->in * queue->item_size), value, queue->item_size);
queue->items++;
queue->in = (queue->in + 1) % queue->size;
pthread_mutex_unlock(&(queue->mutex));
/* Nofify blocked threads */
pthread_cond_broadcast(&(queue->cond_empty));
return PTHREAD_QUEUE_OK;
}
static int pthread_queue_dequeue(pthread_queue_t * queue, void * buf, uint32_t timeout)
{
/* Calculate timeout */
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts)) {
return PTHREAD_QUEUE_ARG;
}
uint32_t sec = timeout / 1000;
uint32_t nsec = (timeout - 1000 * sec) * 1000000;
ts.tv_sec += sec;
if (ts.tv_nsec + nsec > 1000000000)
ts.tv_sec++;
ts.tv_nsec = (ts.tv_nsec + nsec) % 1000000000;
/* Get queue lock */
pthread_mutex_lock(&(queue->mutex));
while (queue->items == 0) {
int ret = -1;
if (timeout) {
ret = pthread_cond_timedwait(&(queue->cond_empty), &(queue->mutex), &ts);
}
if (ret) {
pthread_mutex_unlock(&(queue->mutex));
return PTHREAD_QUEUE_TIMEOUT;
}
}
/* Coby object to output buffer */
memcpy(buf, queue->buffer+(queue->out * queue->item_size), queue->item_size);
queue->items--;
queue->out = (queue->out + 1) % queue->size;
pthread_mutex_unlock(&(queue->mutex));
/* Nofify blocked threads */
pthread_cond_broadcast(&(queue->cond_full));
return PTHREAD_QUEUE_OK;
}
static size_t pthread_queue_items(pthread_queue_t * queue)
{
pthread_mutex_lock(&(queue->mutex));
size_t items = queue->items;
pthread_mutex_unlock(&(queue->mutex));
return items;
}
gs_error_t gs_queue_create(size_t items, size_t item_size, gs_queue_t * queue)
{
if (queue == NULL) {
return GS_ERROR_ARG;
}
pthread_queue_t * q = pthread_queue_create(items, item_size);
if (q == NULL) {
return GS_ERROR_ALLOC;
}
*queue = q;
return GS_OK;
}
gs_error_t gs_queue_destroy(gs_queue_t queue)
{
pthread_queue_delete(queue);
return GS_OK;
}
gs_error_t gs_queue_enqueue(gs_queue_t queue, const void *value, int timeout_ms)
{
return pthread_queue_enqueue(queue, value, (timeout_ms >= 0) ? timeout_ms : INT_MAX);
}
gs_error_t gs_queue_enqueue_isr(gs_queue_t queue, const void * value, gs_context_switch_t * cswitch)
{
(void) cswitch;
gs_error_t error = gs_queue_enqueue(queue, value, 0);
return (error != GS_ERROR_TIMEOUT) ? error : GS_ERROR_FULL;
}
gs_error_t gs_queue_dequeue(gs_queue_t queue, int timeout_ms, void *buf)
{
return pthread_queue_dequeue(queue, buf, (timeout_ms >= 0) ? timeout_ms : INT_MAX);
}
gs_error_t gs_queue_dequeue_isr(gs_queue_t queue, gs_context_switch_t * cswitch, void *buf)
{
(void) cswitch;
gs_error_t error = gs_queue_dequeue(queue, 0, buf);
return (error != GS_ERROR_TIMEOUT) ? error : GS_ERROR_NOT_FOUND;
}
unsigned int gs_queue_size(gs_queue_t queue)
{
if (queue) {
return pthread_queue_items(queue);
}
return 0;
}
unsigned int gs_queue_size_isr(gs_queue_t queue)
{
return gs_queue_size(queue);
}

View File

@ -1,78 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/linux/rtc.h>
#include <time.h>
#include <linux/rtc.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
static gs_error_t gs_rtc_get(void * driver_data, gs_timestamp_t * return_time)
{
if (return_time == NULL) {
return GS_ERROR_ARG;
}
return_time->tv_sec = 0;
return_time->tv_nsec = 0;
int fd = open("/dev/rtc", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return gs_error(errno);
}
struct tm tm;
memset(&tm, 0, sizeof(tm));
int res = ioctl(fd, RTC_RD_TIME, &tm);
close(fd);
if (res < 0) {
return gs_error(errno);
}
time_t time = mktime(&tm);
if (time < 0) {
return GS_ERROR_DATA;
}
return_time->tv_sec = (uint32_t) time;
return GS_OK;
}
static gs_error_t gs_rtc_set(void * driver_data, const gs_timestamp_t * set_time)
{
if (set_time == NULL) {
return GS_ERROR_ARG;
}
int fd = open("/dev/rtc", O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return gs_error(errno);
}
const time_t now = set_time->tv_sec;
struct tm tm;
gmtime_r(&now, &tm);
int res = ioctl(fd, RTC_SET_TIME, &tm);
close(fd);
if (res < 0) {
return gs_error(errno);
}
return GS_OK;
}
gs_error_t gs_rtc_register_linux(bool get, bool set)
{
static gs_rtc_driver_t rtc_driver;
if (get) {
rtc_driver.get_time = gs_rtc_get;
}
if (set) {
rtc_driver.set_time = gs_rtc_set;
}
return gs_rtc_register(&rtc_driver, NULL);
}

View File

@ -1,89 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/sem.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
gs_error_t gs_sem_create(unsigned int initialValue, gs_sem_t * sem)
{
if (sem == NULL) {
return GS_ERROR_ARG;
}
*sem = malloc(sizeof(sem_t));
if (*sem == NULL) {
return GS_ERROR_ALLOC;
}
int res = sem_init(*sem, 0, initialValue);
if (res < 0) {
res = gs_error(errno);
free(*sem);
}
return res;
}
gs_error_t gs_sem_destroy(gs_sem_t sem)
{
int res = GS_OK;
if (sem) {
res = sem_destroy(sem);
if (res < 0) {
res = gs_error(errno);
}
free(sem);
}
return res;
}
gs_error_t gs_sem_wait(gs_sem_t sem, int timeout_ms)
{
int res;
if (timeout_ms < 0) {
res = sem_wait(sem);
} else {
struct timespec ts;
res = clock_gettime(CLOCK_REALTIME, &ts);
if (res == 0) {
const uint32_t ms = (uint32_t)timeout_ms;
uint32_t sec = ms / 1000;
uint32_t nsec = (ms - (1000 * sec)) * 1000000;
ts.tv_sec += sec;
if (ts.tv_nsec + nsec >= 1000000000) {
ts.tv_sec++;
}
ts.tv_nsec = (ts.tv_nsec + nsec) % 1000000000;
res = sem_timedwait(sem, &ts);
}
}
if (res < 0) {
res = gs_error(errno);
}
return res;
}
gs_error_t gs_sem_post(gs_sem_t sem)
{
int res = sem_post(sem);
if (res < 0) {
res = gs_error(errno);
}
return res;
}
gs_error_t gs_sem_post_isr(gs_sem_t sem, gs_context_switch_t * cswitch)
{
(void) cswitch;
int res = sem_post(sem);
if (res < 0) {
res = gs_error(errno);
}
return res;
}

View File

@ -1,38 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/linux/signal.h>
#include <gs/util/linux/exitcode.h>
static void gs_signal_default_handler(int signo, siginfo_t *si, void *context)
{
exit(GS_EXITCODE_SIGNAL(signo)); // ensure atexit are invoked
}
gs_error_t gs_signal_catch(int signal, gs_signal_handler handler)
{
if (handler == NULL) {
handler = gs_signal_default_handler;
}
struct sigaction sa = { .sa_flags = SA_SIGINFO,
.sa_sigaction = handler};
if (sigemptyset(&sa.sa_mask)) {
return GS_ERROR_UNKNOWN;
}
if (sigaction(signal, &sa, NULL)) {
return GS_ERROR_UNKNOWN;
}
return GS_OK;
}
gs_error_t gs_signal_ignore(int signal)
{
struct sigaction sa = { .sa_flags = 0,
.sa_handler = SIG_IGN}; // handle signal by ignoring
if (sigemptyset(&sa.sa_mask)) {
return GS_ERROR_UNKNOWN;
}
if (sigaction(signal, &sa, NULL)) {
return GS_ERROR_UNKNOWN;
}
return GS_OK;
}

View File

@ -1,36 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/stdio.h>
#include <unistd.h>
#include <poll.h>
gs_error_t gs_stdio_putchar(int ch)
{
const int res = putchar(ch);
if (res < 0) {
return GS_ERROR_IO;
}
return GS_OK;
}
gs_error_t gs_stdio_getchar_timed(int timeout_ms, int * ch)
{
struct pollfd fds = {STDIN_FILENO, POLLIN, 0};
const int res = poll(&fds, 1, timeout_ms);
if (res == 0) {
return GS_ERROR_TIMEOUT;
}
if ((res > 0) && (fds.revents & POLLIN)) {
int tmp = getchar();
if (tmp >= 0) {
if (ch) {
*ch = tmp;
}
return GS_OK;
}
}
return GS_ERROR_IO;
}

View File

@ -1,48 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/linux/sysfs_helper.h>
#include <gs/util/log.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
gs_error_t gs_sysfs_write_file(const char *path, const char *value)
{
log_trace("sysfs: write %s to %s", value, path);
int fd = open(path, O_WRONLY);
if (fd < 0) {
return GS_ERROR_HANDLE;
}
size_t len = strlen(value);
ssize_t bytes = write(fd, value, len);
close(fd);
if (bytes < 0) {
return GS_ERROR_NO_DATA;
}
return (len == (size_t)bytes) ? GS_OK : GS_ERROR_NO_DATA;
}
gs_error_t gs_sysfs_read_file(const char *path, char *value, size_t len)
{
log_trace("sysfs: read %s", path);
int fd = open(path, O_RDONLY);
if (fd < 0) {
return GS_ERROR_HANDLE;
}
ssize_t bytes = read(fd, value, len);
close(fd);
if (bytes < 0) {
return GS_ERROR_DATA;
}
return GS_OK;
}

View File

@ -1,89 +0,0 @@
/* Copyright (c) 2013-2018 GomSpace A/S. All rights reserved. */
#include <gs/util/thread.h>
#include <unistd.h>
#include <gs/util/time.h>
gs_error_t gs_thread_create(const char * const name,
gs_thread_func_t func,
void * parameter,
size_t stack_size,
gs_thread_priority_t priority,
uint32_t flags,
gs_thread_t * return_handle)
{
gs_time_uptime(); // force initialize of static offset
pthread_attr_t attr;
int res = pthread_attr_init(&attr);
if (res) {
return GS_ERROR_ALLOC;
}
if (flags & GS_THREAD_CREATE_JOINABLE) {
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
} else {
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
}
gs_thread_t handle;
res = pthread_create(&handle, &attr, func, parameter);
pthread_attr_destroy(&attr);
if (res) {
return GS_ERROR_ALLOC;
}
if (return_handle) {
*return_handle = handle;
}
return GS_OK;
}
gs_error_t gs_thread_create_with_stack(const char * const name,
gs_thread_func_t func,
void * parameter,
size_t stack_size,
gs_stack_type_t *stack,
gs_thread_priority_t priority,
uint32_t flags,
gs_thread_t * return_handle)
{
return gs_thread_create(name, func, parameter, stack_size, priority, flags, return_handle);
}
void gs_thread_exit(void * exitValue)
{
pthread_exit(exitValue);
}
void gs_thread_sleep_ms(uint32_t time_ms)
{
gs_time_sleep_ms(time_ms);
}
gs_error_t gs_thread_join(gs_thread_t thread, void ** return_retval)
{
gs_error_t error = GS_ERROR_ARG;
void * retval = 0;
if (thread) {
int res = pthread_join(thread, &retval);
if (res == 0) {
error = GS_OK;
} else {
retval = 0;
}
}
if (return_retval) {
*return_retval = retval;
}
return error;
}
void gs_thread_block(void)
{
/* Wait here forever */
for (;;) {
gs_time_sleep_ms(10000);
}
}

View File

@ -1,53 +0,0 @@
/* Copyright (c) 2013-2017 GomSpace A/S. All rights reserved. */
#include <gs/util/time.h>
#include <time.h>
#include <gs/util/timestamp.h>
uint32_t gs_time_rel_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
return 0;
}
return (uint32_t)((ts.tv_sec * 1000) + (ts.tv_nsec/1000000));
}
uint32_t gs_time_rel_ms_isr(void)
{
return gs_time_rel_ms();
}
static uint32_t uptime_offset = 0;
uint32_t gs_time_uptime(void)
{
uint32_t seconds;
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
seconds = 0;
} else {
seconds = (uint32_t) ts.tv_sec;
}
if (uptime_offset == 0) {
uptime_offset = seconds;
}
return (seconds - uptime_offset);
}
void gs_time_sleep_ns(uint64_t time_ns)
{
struct timespec ts;
ts.tv_sec = (time_ns / GS_TIMESTAMP_NSEC_PER_SEC);
ts.tv_nsec = (time_ns % GS_TIMESTAMP_NSEC_PER_SEC);
// improvement: check return code (INTR) and use remaining.
nanosleep(&ts, NULL);
}
void gs_time_sleep_ms(uint32_t time_ms)
{
uint64_t ns = time_ms;
ns *= 1000000LL;
gs_time_sleep_ns( ns);
}