aboutsummaryrefslogtreecommitdiffstats
path: root/src/af-steering-wheel-binding.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/af-steering-wheel-binding.c')
-rw-r--r--src/af-steering-wheel-binding.c426
1 files changed, 426 insertions, 0 deletions
diff --git a/src/af-steering-wheel-binding.c b/src/af-steering-wheel-binding.c
new file mode 100644
index 0000000..908bf71
--- /dev/null
+++ b/src/af-steering-wheel-binding.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <json-c/json.h>
+
+#include <systemd/sd-event.h>
+
+#include "af-steering-wheel-binding.h"
+#include "bind_event.h"
+#include "steering_wheel_json.h"
+#include "prop_search.h"
+#include "js_raw.h"
+
+#define ENABLE_EVENT_DROP
+
+struct wheel_conf
+{
+ char *devname;
+};
+
+int notify_property_changed(struct prop_info_t *property_info)
+{
+ struct bind_event_t *event;
+
+ //NOTICEMSG("notify_property_changed %s", property_info->name);
+ event = get_event(property_info->name);
+ if (event == NULL)
+ {
+ DBGMSG("<IGNORE event>: event(\"%s\") is not subscribed", property_info->name);
+ return 1;
+ }
+
+ if (afb_event_is_valid(event->event))
+ {
+ int recved_client;
+
+ recved_client = afb_event_push(event->event, property2json(property_info));
+ if(recved_client < 1)
+ {
+ if(recved_client == 0)
+ {
+ DBGMSG("event(\"%s\") is no client.", property_info->name);
+#ifdef ENABLE_EVENT_DROP
+ /* Drop event */
+ remove_event(property_info->name);
+#endif
+ }
+ else
+ {
+ ERRMSG("count of clients that received the event : %d",recved_client);
+ }
+
+ return 1;
+ } /* else (1 <= recved_lient)
+ * NORMAL
+ */
+ }
+ else
+ {
+ ERRMSG("event(\"%s\") is invalid. don't adb_event_push()", property_info->name);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int connection(struct wheel_conf *conf)
+{
+ int js;
+ int ret;
+ sd_event_source *source;
+
+ js = js_open(conf->devname);
+ if (js < 0)
+ {
+ js_close(js);
+ ERRMSG("can't connect to joy stick, the event loop failed");
+ return 0;
+ }
+
+ ret = sd_event_add_io(
+ afb_daemon_get_event_loop(),
+ &source,
+ js,
+ EPOLLIN,
+ on_event, NULL);
+ if (ret < 0)
+ {
+ js_close(js);
+ ERRMSG("can't add event, the event loop failed");
+ return 0;
+ }
+
+ NOTICEMSG("connect to JS(%s), event loop started",conf->devname);
+
+ return 0;
+}
+
+/***************************************************************************************/
+/** **/
+/** **/
+/** SECTION: BINDING VERBS IMPLEMENTATION **/
+/** **/
+/** **/
+/***************************************************************************************/
+/**
+ * get method.
+ */
+static void get(struct afb_req req)
+{
+
+}
+
+///**
+// * set method.
+// */
+//static void set(struct afb_req req)
+//{
+//
+//}
+
+/**
+ * list method.
+ */
+static struct json_object *tmplists;
+
+static void _listup_properties(struct prop_info_t *property_info)
+{
+ if (property_info->name == NULL)
+ {
+ return;
+ }
+ else
+ {
+ json_object_array_add(tmplists, json_object_new_string(property_info->name));
+ }
+}
+
+static void list(struct afb_req req)
+{
+ if (tmplists != NULL)
+ {
+ json_object_put(tmplists);
+ }
+ tmplists = json_object_new_array();
+ if (tmplists == NULL)
+ {
+ ERRMSG("not enough memory");
+ afb_req_fail(req,"not enough memory", NULL);
+ return;
+ }
+ (void)canid_walker(_listup_properties);
+ afb_req_success(req, tmplists, NULL);
+}
+
+/**
+ * subscribe method.
+ */
+static int subscribe_all(struct afb_req req, struct json_object *apply);
+
+static int subscribe_signal(struct afb_req req, const char *name, struct json_object *apply)
+{
+ struct bind_event_t *event;
+
+ if(strcmp(name, "*") == 0)
+ {
+ return subscribe_all(req, apply);
+ }
+
+ event = get_event(name);
+ if (event == NULL)
+ {
+ event = register_event(name);
+ if (event == NULL)
+ {
+ ERRMSG("register event failed: %s", name);
+ return 1;
+ }
+ }
+ else
+ {
+ DBGMSG("subscribe event: \"%s\" alrady exist", name);
+ }
+
+ if (afb_req_subscribe(req, event->event) != 0)
+ {
+ ERRMSG("afb_req_subscrive() is failed.");
+ return 1;
+ }
+
+ json_object_object_add(apply, event->name, property2json(event->raw_info));
+
+ return 0;
+}
+
+static int subscribe_all(struct afb_req req, struct json_object *apply)
+{
+ int i;
+ int nProp;
+ const char **list = getSupportPropertiesList(&nProp);
+ int err = 0;
+ for(i = 0; i < nProp; i++)
+ err += subscribe_signal(req, list[i], apply);
+
+ return err;
+}
+
+static void subscribe(struct afb_req req)
+{
+ struct json_object *apply;
+ int err = 0;
+ const char *event;
+
+ event = afb_req_value(req, "event");
+ if (event == NULL)
+ {
+ ERRMSG("Unknwon subscrive event args");
+ afb_req_fail(req, "error", NULL);
+ return;
+ }
+ apply = json_object_new_object();
+ err = subscribe_signal(req, event, apply);
+
+ if (!err)
+ {
+ afb_req_success(req, apply, NULL);
+ }
+ else
+ {
+ json_object_put(apply);
+ afb_req_fail(req, "error", NULL);
+ }
+}
+
+/**
+ * unsubscribe method.
+ */
+
+static int unsubscribe_all(struct afb_req req);
+
+static int unsubscribe_signal(struct afb_req req, const char *name)
+{
+ struct bind_event_t *event;
+ if(strcmp(name, "*") == 0)
+ {
+ return unsubscribe_all(req);
+ }
+
+ event = get_event(name);
+ if (event == NULL)
+ {
+ ERRMSG("not subscribed event \"%s\"", name);
+ return 0; /* Alrady unsubscribed */
+ }
+ if (afb_req_unsubscribe(req, event->event) != 0)
+ {
+ ERRMSG("afb_req_subscrive() is failed.");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int unsubscribe_all(struct afb_req req)
+{
+ int i;
+ int nProp;
+ const char **list = getSupportPropertiesList(&nProp);
+ int err = 0;
+ for(i = 0; i < nProp; i++)
+ {
+ err += unsubscribe_signal(req, list[i]);
+ }
+
+ return err;
+}
+
+static void unsubscribe(struct afb_req req)
+{
+ struct json_object *args, *val;
+ int n,i;
+ int err = 0;
+
+ args = afb_req_json(req);
+ if ((args == NULL) || !json_object_object_get_ex(args, "event", &val))
+ {
+ err = unsubscribe_all(req);
+ }
+ else if (json_object_get_type(val) != json_type_array)
+ {
+ err = unsubscribe_signal(req, json_object_get_string(val));
+ }
+ else
+ {
+ struct json_object *ent;
+ n = json_object_array_length(val);
+ for (i = 0; i < n; i++)
+ {
+ ent = json_object_array_get_idx(val,i);
+ err += unsubscribe_signal(req, json_object_get_string(ent));
+ }
+ }
+
+ if (!err)
+ afb_req_success(req, NULL, NULL);
+ else
+ afb_req_fail(req, "error", NULL);
+}
+
+/*
+ * parse configuration file (steering_wheel.json)
+ */
+static int init_conf(int fd_conf, struct wheel_conf *conf)
+{
+#define CONF_FILE_MAX (1024)
+ char filebuf[CONF_FILE_MAX];
+ json_object *jobj;
+
+ memset(filebuf,0, sizeof(filebuf));
+ FILE *fp = fdopen(fd_conf,"r");
+ if (fp == NULL)
+ {
+ ERRMSG("canno read configuration file(steering_wheel.json)");
+ return -1;
+ }
+
+ fread(filebuf, 1, sizeof(filebuf), fp);
+ fclose(fp);
+
+ jobj = json_tokener_parse(filebuf);
+ if (jobj == NULL)
+ {
+ ERRMSG("json: Invalid steering_wheel.json format");
+ return -1;
+ }
+ json_object_object_foreach(jobj, key, val)
+ {
+ if (strcmp(key,"dev_name") == 0)
+ {
+ conf->devname = strdup(json_object_get_string(val));
+ }
+ else if (strcmp(key,"wheel_map") == 0)
+ {
+ wheel_define_init(json_object_get_string(val));
+ }
+ else if (strcmp(key,"gear_para") == 0)
+ {
+ wheel_gear_para_init(json_object_get_string(val));
+ }
+ }
+ json_object_put(jobj);
+
+ return 0;
+}
+
+static int init()
+{
+ NOTICEMSG("init");
+
+ int fd_conf;
+ struct wheel_conf conf;
+ fd_conf = afb_daemon_rootdir_open_locale("steering_wheel.json", O_RDONLY, NULL);
+ if (fd_conf < 0)
+ {
+ ERRMSG("wheel configuration (steering_wheel.json) is not access");
+ return -1;
+ }
+ if (init_conf(fd_conf, &conf))
+ {
+ return -1;
+ }
+ return connection(&conf);
+}
+
+/*
+ * array of the verbs exported to afb-daemon
+ */
+static const struct afb_verb_v2 binding_verbs[] =
+{
+ /* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL Authorization */
+ { .verb= "get", .session= AFB_SESSION_NONE, .callback= get, .info = "get", .auth = NULL },
+// { .name= "set", .session= AFB_SESSION_NONE, .callback= set, .auth = NULL },
+ { .verb= "list", .session= AFB_SESSION_NONE, .callback= list, .info = "list", .auth = NULL },
+ { .verb= "subscribe", .session= AFB_SESSION_NONE, .callback= subscribe, .info = "subscribe", .auth = NULL },
+ { .verb= "unsubscribe", .session= AFB_SESSION_NONE, .callback= unsubscribe, .info = "unsubscribe", .auth = NULL },
+ { .verb= NULL } /* marker for end of the array */
+};
+
+/*
+ * description of the binding for afb-daemon
+ */
+const struct afb_binding_v2 afbBindingV2 =
+{
+ .api = "steering-wheel",
+ .specification = NULL,
+ .verbs = binding_verbs, /* the array describing the verbs of the API */
+ .preinit = NULL,
+ .init = init,
+ .onevent = NULL,
+ .noconcurrency = 1
+};