Commit 26da4bf2 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Rework of error handling, added license

parent c074cad4
This diff is collapsed.
......@@ -71,3 +71,7 @@ build/libmoberg.so: build/lib/moberg_config.o
build/libmoberg.so: build/lib/moberg_device.o
build/libmoberg.so: build/lib/moberg_parser.o
build/lib/%.o: %.h
build/lib/%.o: moberg_inline.h
build/lib/moberg.o: moberg_config.h
build/lib/moberg.o: moberg_module.h
build/lib/moberg.o: moberg_parser.h
......@@ -25,6 +25,11 @@
#include <string.h>
#include <moberg.h>
static inline int OK(struct moberg_status status)
{
return moberg_OK(status);
}
static void throwMoberg(JNIEnv *env, int chan, char *exceptionName)
{
jclass exceptionClass = 0;
......@@ -182,7 +187,8 @@ Java_se_lth_control_realtime_moberg_Moberg_analogInOpen(
if (! channel_up(&analog_in, index)) {
struct channel channel;
up();
if (! moberg_analog_in_open(g_moberg.moberg, index, &channel.analog_in)) {
if (! OK(moberg_analog_in_open(g_moberg.moberg, index,
&channel.analog_in))) {
down();
throwMobergDeviceDoesNotExistException(env, index);
} else {
......@@ -230,7 +236,8 @@ Java_se_lth_control_realtime_moberg_Moberg_analogOutOpen(
if (! channel_up(&analog_out, index)) {
struct channel channel;
up();
if (! moberg_analog_out_open(g_moberg.moberg, index, &channel.analog_out)) {
if (! OK(moberg_analog_out_open(g_moberg.moberg, index,
&channel.analog_out))) {
down();
throwMobergDeviceDoesNotExistException(env, index);
} else {
......@@ -275,7 +282,8 @@ Java_se_lth_control_realtime_moberg_Moberg_digitalInOpen(
if (! channel_up(&digital_in, index)) {
struct channel channel;
up();
if (! moberg_digital_in_open(g_moberg.moberg, index, &channel.digital_in)) {
if (! OK(moberg_digital_in_open(g_moberg.moberg, index,
&channel.digital_in))) {
down();
throwMobergDeviceDoesNotExistException(env, index);
} else {
......@@ -322,7 +330,8 @@ Java_se_lth_control_realtime_moberg_Moberg_digitalOutOpen(
if (! channel_up(&digital_out, index)) {
struct channel channel;
up();
if (! moberg_digital_out_open(g_moberg.moberg, index, &channel.digital_out)) {
if (! OK(moberg_digital_out_open(g_moberg.moberg, index,
&channel.digital_out))) {
down();
throwMobergDeviceDoesNotExistException(env, index);
} else {
......@@ -366,7 +375,8 @@ Java_se_lth_control_realtime_moberg_Moberg_encoderInOpen(
if (! channel_up(&encoder_in, index)) {
struct channel channel;
up();
if (! moberg_encoder_in_open(g_moberg.moberg, index, &channel.encoder_in)) {
if (! OK(moberg_encoder_in_open(g_moberg.moberg, index,
&channel.encoder_in))) {
down();
throwMobergDeviceDoesNotExistException(env, index);
} else {
......
......@@ -135,7 +135,11 @@ static void mdlOutputs(SimStruct *S, int_T tid)
for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
struct moberg_analog_in *ain = (struct moberg_analog_in*)pwork[i];
ain->read(ain->context, &y[i]);
if (! ain->read(ain->context, &y[i])) {
static char error[256];
sprintf(error, "Failed to read analogin #%d", (int)channel[i]);
ssSetErrorStatus(S, error);
}
}
}
}
......
/*
moberg4simulink.c -- moberg interface for simulink MEX functions
Copyright (C) 2019 Anders Blomdell <anders.blomdell@gmail.com>
This file is part of Moberg.
Moberg is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <moberg.h>
#include <moberg4simulink.h>
static int inline OK(struct moberg_status status)
{
return moberg_OK(status);
}
static struct channel {
struct channel *next;
struct channel *prev;
......@@ -68,12 +94,13 @@ struct moberg_analog_in *moberg4simulink_analog_in_open(int index)
{
up();
struct channel *result = malloc(sizeof(*result));
if (result && moberg_analog_in_open(g_moberg.moberg, index,
&result->analog_in)) {
if (result && OK(moberg_analog_in_open(g_moberg.moberg, index,
&result->analog_in))) {
list_insert(&analog_in_list, result);
return &result->analog_in;
} else {
down();
if (result) { free(result); }
return NULL;
}
}
......@@ -93,12 +120,13 @@ struct moberg_analog_out *moberg4simulink_analog_out_open(int index)
{
up();
struct channel *result = malloc(sizeof(*result));
if (result && moberg_analog_out_open(g_moberg.moberg, index,
&result->analog_out)) {
if (result && OK(moberg_analog_out_open(g_moberg.moberg, index,
&result->analog_out))) {
list_insert(&analog_out_list, result);
return &result->analog_out;
} else {
down();
if (result) { free(result); }
return NULL;
}
}
......@@ -118,12 +146,13 @@ struct moberg_digital_in *moberg4simulink_digital_in_open(int index)
{
up();
struct channel *result = malloc(sizeof(*result));
if (result && moberg_digital_in_open(g_moberg.moberg, index,
&result->digital_in)) {
if (result && OK(moberg_digital_in_open(g_moberg.moberg, index,
&result->digital_in))) {
list_insert(&digital_in_list, result);
return &result->digital_in;
} else {
down();
if (result) { free(result); }
return NULL;
}
}
......@@ -144,12 +173,13 @@ struct moberg_digital_out *moberg4simulink_digital_out_open(int index)
{
up();
struct channel *result = malloc(sizeof(*result));
if (result && moberg_digital_out_open(g_moberg.moberg, index,
&result->digital_out)) {
if (result && OK(moberg_digital_out_open(g_moberg.moberg, index,
&result->digital_out))) {
list_insert(&digital_out_list, result);
return &result->digital_out;
} else {
down();
if (result) { free(result); }
return NULL;
}
}
......@@ -170,12 +200,13 @@ struct moberg_encoder_in *moberg4simulink_encoder_in_open(int index)
{
up();
struct channel *result = malloc(sizeof(*result));
if (result && moberg_encoder_in_open(g_moberg.moberg, index,
&result->encoder_in)) {
if (result && OK(moberg_encoder_in_open(g_moberg.moberg, index,
&result->encoder_in))) {
list_insert(&encoder_in_list, result);
return &result->encoder_in;
} else {
down();
if (result) { free(result); }
return NULL;
}
}
......
/*
moberg4simulink.h -- moberg interface for simulink MEX functions
Copyright (C) 2019 Anders Blomdell <anders.blomdell@gmail.com>
This file is part of Moberg.
Moberg is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __MOBERG4SIMULINK_H__
#define __MOBERG4SIMULINK_H__
......
/*
moberg.c -- interface to moberg I/O system
Copyright (C) 2019 Anders Blomdell <anders.blomdell@gmail.com>
This file is part of Moberg.
Moberg is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE /* scandirat */
......@@ -10,10 +30,12 @@
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <moberg.h>
#include <moberg_config.h>
#include <moberg_parser.h>
#include <moberg_inline.h>
#include <moberg_module.h>
#include <moberg_parser.h>
struct moberg {
struct moberg_config *config;
......@@ -144,10 +166,11 @@ static void parse_config_dir_at(
}
static int install_channel(struct moberg *moberg,
int index,
struct moberg_device* device,
struct moberg_channel *channel)
static struct moberg_status install_channel(
struct moberg *moberg,
int index,
struct moberg_device* device,
struct moberg_channel *channel)
{
if (channel) {
struct moberg_channel *old = NULL;
......@@ -201,9 +224,9 @@ static int install_channel(struct moberg *moberg,
break;
}
}
return 1;
return MOBERG_OK;
err:
return 0;
return MOBERG_ERRNO(ENOMEM);
}
static int install_config(struct moberg *moberg)
......@@ -220,6 +243,11 @@ static int install_config(struct moberg *moberg)
}
}
int moberg_OK(struct moberg_status status)
{
return status.result == 0;
}
struct moberg *moberg_new()
{
struct moberg *result = malloc(sizeof(*result));
......@@ -283,146 +311,221 @@ void moberg_free(struct moberg *moberg)
/* Input/output */
int moberg_analog_in_open(struct moberg *moberg,
int index,
struct moberg_analog_in *analog_in)
struct moberg_status moberg_analog_in_open(
struct moberg *moberg,
int index,
struct moberg_analog_in *analog_in)
{
if (! analog_in) {
return MOBERG_ERRNO(EINVAL);
}
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->analog_in, index, &channel);
if (channel) {
channel->open(channel);
*analog_in = channel->action.analog_in;
return 1;
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
struct moberg_status result = channel->open(channel);
if (! OK(result)) {
return result;
}
return 0;
*analog_in = channel->action.analog_in;
return MOBERG_OK;
}
int moberg_analog_in_close(struct moberg *moberg,
int index,
struct moberg_analog_in analog_in)
struct moberg_status moberg_analog_in_close(
struct moberg *moberg,
int index,
struct moberg_analog_in analog_in)
{
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->analog_in, index, &channel);
if (channel && channel->action.analog_in.context == analog_in.context) {
channel->close(channel);
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
return 1;
if (channel->action.analog_in.context != analog_in.context) {
return MOBERG_ERRNO(EINVAL);
}
struct moberg_status result = channel->close(channel);
if (! OK(result)) {
return result;
}
return MOBERG_OK;
}
int moberg_analog_out_open(struct moberg *moberg,
int index,
struct moberg_analog_out *analog_out)
struct moberg_status moberg_analog_out_open(
struct moberg *moberg,
int index,
struct moberg_analog_out *analog_out)
{
if (! analog_out) {
return MOBERG_ERRNO(EINVAL);
}
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->analog_out, index, &channel);
if (channel) {
channel->open(channel);
*analog_out = channel->action.analog_out;
return 1;
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
struct moberg_status result = channel->open(channel);
if (! OK(result)) {
return result;
}
return 0;
*analog_out = channel->action.analog_out;
return MOBERG_OK;
}
int moberg_analog_out_close(struct moberg *moberg,
int index,
struct moberg_analog_out analog_out)
struct moberg_status moberg_analog_out_close(
struct moberg *moberg,
int index,
struct moberg_analog_out analog_out)
{
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->analog_out, index, &channel);
if (channel && channel->action.analog_out.context == analog_out.context) {
channel->close(channel);
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
if (channel->action.analog_out.context != analog_out.context) {
return MOBERG_ERRNO(EINVAL);
}
return 1;
struct moberg_status result = channel->close(channel);
if (! OK(result)) {
return result;
}
return MOBERG_OK;
}
int moberg_digital_in_open(struct moberg *moberg,
int index,
struct moberg_digital_in *digital_in)
struct moberg_status moberg_digital_in_open(
struct moberg *moberg,
int index,
struct moberg_digital_in *digital_in)
{
if (! digital_in) {
return MOBERG_ERRNO(EINVAL);
}
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->digital_in, index, &channel);
if (channel) {
channel->open(channel);
*digital_in = channel->action.digital_in;
return 1;
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
struct moberg_status result = channel->open(channel);
if (! OK(result)) {
return result;
}
return 0;
*digital_in = channel->action.digital_in;
return MOBERG_OK;
}
int moberg_digital_in_close(struct moberg *moberg,
int index,
struct moberg_digital_in digital_in)
struct moberg_status moberg_digital_in_close(
struct moberg *moberg,
int index,
struct moberg_digital_in digital_in)
{
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->digital_in, index, &channel);
if (channel && channel->action.digital_in.context == digital_in.context) {
channel->close(channel);
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
if (channel->action.digital_in.context != digital_in.context) {
return MOBERG_ERRNO(EINVAL);
}
return 1;
struct moberg_status result = channel->close(channel);
if (! OK(result)) {
return result;
}
return MOBERG_OK;
}
int moberg_digital_out_open(struct moberg *moberg,
int index,
struct moberg_digital_out *digital_out)
struct moberg_status moberg_digital_out_open(
struct moberg *moberg,
int index,
struct moberg_digital_out *digital_out)
{
if (! digital_out) {
return MOBERG_ERRNO(EINVAL);
}
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->digital_out, index, &channel);
if (channel) {
channel->open(channel);
*digital_out = channel->action.digital_out;
return 1;
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
struct moberg_status result = channel->open(channel);
if (! OK(result)) {
return result;
}
return 0;
*digital_out = channel->action.digital_out;
return MOBERG_OK;
}
int moberg_digital_out_close(struct moberg *moberg,
int index,
struct moberg_digital_out digital_out)
struct moberg_status moberg_digital_out_close(
struct moberg *moberg,
int index,
struct moberg_digital_out digital_out)
{
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->digital_out, index, &channel);
if (channel && channel->action.digital_out.context == digital_out.context) {
channel->close(channel);
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
if (channel->action.digital_out.context != digital_out.context) {
return MOBERG_ERRNO(EINVAL);
}
return 1;
struct moberg_status result = channel->close(channel);
if (! OK(result)) {
return result;
}
return MOBERG_OK;
}
int moberg_encoder_in_open(struct moberg *moberg,
int index,
struct moberg_encoder_in *encoder_in)
struct moberg_status moberg_encoder_in_open(
struct moberg *moberg,
int index,
struct moberg_encoder_in *encoder_in)
{
if (! encoder_in) {
return MOBERG_ERRNO(EINVAL);
}
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->encoder_in, index, &channel);
if (channel) {
channel->open(channel);
*encoder_in = channel->action.encoder_in;
return 1;
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
struct moberg_status result = channel->open(channel);
if (! OK(result)) {
return result;
}
return 0;
*encoder_in = channel->action.encoder_in;
return MOBERG_OK;
}
int moberg_encoder_in_close(struct moberg *moberg,
int index,
struct moberg_encoder_in encoder_in)
struct moberg_status moberg_encoder_in_close(
struct moberg *moberg,
int index,
struct moberg_encoder_in encoder_in)
{
struct moberg_channel *channel = NULL;
channel_list_get(&moberg->encoder_in, index, &channel);
if (channel && channel->action.encoder_in.context == encoder_in.context) {
channel->close(channel);
if (! channel) {
return MOBERG_ERRNO(ENODEV);
}
if (channel->action.encoder_in.context != encoder_in.context) {
return MOBERG_ERRNO(EINVAL);
}
struct moberg_status result = channel->close(channel);
if (! OK(result)) {
return result;
}
return 1;
return MOBERG_OK;
}
/* System init functionality (systemd/init/...) */
int moberg_start(
struct moberg_status moberg_start(
struct moberg *moberg,
FILE *f)
{
return moberg_config_start(moberg->config, f);
}
int moberg_stop(
struct moberg_status moberg_stop(
struct moberg *moberg,
FILE *f)
{
......
/*
moberg.h -- interface to moberg I/O system
Copyright (C) 2019 Anders Blomdell <anders.blomdell@gmail.com>
This file is part of Moberg.
Moberg is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __MOBERG_H__
#define __MOBERG_H__
......@@ -5,6 +26,17 @@
struct moberg;