diff options
Diffstat (limited to 'src/af-steering-wheel-binding.c')
-rw-r--r-- | src/af-steering-wheel-binding.c | 426 |
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 +}; |