summaryrefslogtreecommitdiffstats
path: root/binding/accelero-binding.c
blob: d7f05e9b74879865cbd0e465b5502ccc8f1b276d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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,
};