diff options
Diffstat (limited to 'binding/accelero-binding.c')
-rw-r--r-- | binding/accelero-binding.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/binding/accelero-binding.c b/binding/accelero-binding.c new file mode 100644 index 0000000..d7f05e9 --- /dev/null +++ b/binding/accelero-binding.c @@ -0,0 +1,167 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <pthread.h> +#include <sys/ioctl.h> +#include <glib.h> + +#include <json-c/json.h> +#define AFB_BINDING_VERSION 2 +#include <afb/afb-binding.h> + +#define IIODEVICE "/sys/bus/iio/devices/iio:device" +#define IIODEVICE0 "/sys/bus/iio/devices/iio:device0/" +#define IIODEVICE1 "/sys/bus/iio/devices/iio:device1/" + +static struct afb_event accel_event; +static struct afb_event magn_event; +static struct afb_event anglvel_event; + +static pthread_t thread; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +static void get_buffer(const char *iio_file, const char *sub_name, + void *buffer, size_t count) +{ + int fd; + fd = open(iio_file, O_RDONLY); + if(fd < 0) { + AFB_ERROR("Cannot open %s\n", iio_file); + return; + } + if(read(fd, buffer, count) < 0){ + AFB_ERROR("cannot read %s\n", iio_file); + return; + } + close(fd); +} + +static void get_subdata_string(const char * iio_device_path, const char *sub_name, + json_object *jresp) { + char iio_file[100]; + sprintf(iio_file, "%s%s", iio_device_path, sub_name); + size_t buffer_size = 1000; + char buffer[buffer_size]; + + get_buffer(iio_file, sub_name, buffer, buffer_size); + + json_object *value = json_object_new_string(buffer); + if(jresp) + json_object_object_add(jresp, sub_name, value); +} + +static void get_subdata_int(const char * iio_device_path, const char *sub_name, + json_object *jresp) { + char iio_file[100]; + sprintf(iio_file, "%s%s", iio_device_path, sub_name); + AFB_INFO("iio_file=%s", iio_file); + size_t buffer_size = 1000; + char buffer[buffer_size]; + + get_buffer(iio_file, sub_name, buffer, buffer_size); + + json_object *value = json_object_new_int(atoi(buffer)); + if(jresp) + json_object_object_add(jresp, sub_name, value); +} + +static void get_data(const char *name, const int iio_device, json_object *jresp) { + char iio_device_path[100]; + sprintf(iio_device_path, IIODEVICE"%d/in_%s_", iio_device, name); + + get_subdata_string(iio_device_path, "scale", jresp); + get_subdata_string(iio_device_path, "scale_available", jresp); + get_subdata_int(iio_device_path, "x_raw", jresp); + get_subdata_int(iio_device_path, "y_raw", jresp); + get_subdata_int(iio_device_path, "z_raw", jresp); +} + +static int treat_event(const char *name, const int device_number, + struct afb_event event) +{ + json_object *jresp = json_object_new_object(); + get_data(name, device_number, jresp); + AFB_INFO("push event %s\n", name); + pthread_mutex_lock(&mutex); + afb_event_push(event, json_object_get(jresp)); + pthread_mutex_unlock(&mutex); + return 0; +} + +gboolean data_poll(gpointer ptr) +{ + AFB_INFO("data_poll"); + treat_event("accel", 0, accel_event); + treat_event("magn", 0, magn_event); + treat_event("anglvel", 1, anglvel_event); + return TRUE; +} + +static void *data_thread(void *ptr) +{ + g_timeout_add_seconds(1, data_poll, NULL); + g_main_loop_run(g_main_loop_new(NULL, FALSE)); + return NULL; +} + +static void subscribe(struct afb_req request) +{ + const char *value = afb_req_value(request, "event"); + if(value) { + if(!strcasecmp(value, "accel")) { + afb_req_subscribe(request, accel_event); + } else if(!strcasecmp(value, "magn")) { + afb_req_subscribe(request, magn_event); + } else if(!strcasecmp(value, "anglvel")) { + afb_req_subscribe(request, anglvel_event); + } else { + afb_req_fail(request, "failed", "Invalid event"); + return; + } + } + afb_req_success(request, NULL, NULL); +} + +static void unsubscribe(struct afb_req request) +{ + const char *value = afb_req_value(request, "value"); + if(value) { + if(!strcasecmp(value, "accel")) { + afb_req_unsubscribe(request, accel_event); + } else if(!strcasecmp(value, "magn")) { + afb_req_unsubscribe(request, magn_event); + } else { + afb_req_fail(request, "failed", "Invalid event"); + return; + } + } + afb_req_success(request, NULL, NULL); +} + +const afb_verb_v2 verbs[] = { + { .verb = "subscribe", .session = AFB_SESSION_NONE, .callback = subscribe, .info = "Subscribe for an event" }, + { .verb = "unsubscribe", .session = AFB_SESSION_NONE, .callback = unsubscribe, .info = "Unsubscribe for an event" }, + { .verb=NULL } +}; + +static int init() +{ + accel_event = afb_daemon_make_event("accel"); + magn_event = afb_daemon_make_event("magn"); + anglvel_event = afb_daemon_make_event("anglvel"); + + pthread_create(&thread, NULL, &data_thread, NULL); + + return 0; +} + +const afb_binding_v2 afbBindingV2 = { + .info = "accelero service", + .api = "accelero", + .verbs = verbs, + .init = init, +}; |