summaryrefslogtreecommitdiffstats
path: root/src/platform-info-binding.c
diff options
context:
space:
mode:
authorFarshid Monhaseri <monhaseri.f@gmail.com>2020-11-10 13:05:37 +0330
committerFarshid Monhaseri <monhaseri.f@gmail.com>2020-11-10 09:55:46 +0000
commit172db50c33beeb53f8e75c115699179be880b960 (patch)
treeeb0b124e43cf409c4b12b72a4df1e12d3219936d /src/platform-info-binding.c
parente40da34d561aa802ea8f1d8f5bf7b5898f84b083 (diff)
Add device monitoring feature (hotplug device detection)
Changes: - Implement libudev 'monitor' interface to detect hotplug devices. - Forward udev rules as AFB 'subscribe' args to udev_monitoring objects. - Filter retrieved property fields through 'mask' argument from 'subscribe' args. - Generate detached threads (event loop) and data context for each client, so every user can subscribe for device events with their own udev rules and receive their desired device parameters. Bug-AGL: SPEC-3512 Signed-off-by: Farshid Monhaseri <monhaseri.f@gmail.com> Change-Id: I0fc007d9707deaf39d21147aa8240fde302f5f9e
Diffstat (limited to 'src/platform-info-binding.c')
-rw-r--r--src/platform-info-binding.c133
1 files changed, 100 insertions, 33 deletions
diff --git a/src/platform-info-binding.c b/src/platform-info-binding.c
index 5e78fd9..4ae3c70 100644
--- a/src/platform-info-binding.c
+++ b/src/platform-info-binding.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2019 "IoT.bzh"
+ * Copyright (C) 2016-2020 "IoT.bzh"
*
* Author "Romain Forlot" <romain.forlot@iot.bzh>
*
@@ -23,6 +23,7 @@
#include <afb/afb-binding.h>
#include "platform-info-binding.h"
+#include "platform-info-devices.h"
#ifndef PLATFORM_INFO_DIR
#define PLATFORM_INFO_DIR "/etc/platform-info"
@@ -33,30 +34,42 @@
#endif
void afv_get(afb_req_t req) {
- char *json_path = NULL, *full_json_path = NULL;
- json_object *platform_info = (json_object*) afb_api_get_userdata(req->api);
- json_object *args = afb_req_json(req), *result = NULL;
-
- switch (json_object_get_type(args)) {
- case json_type_null:
- result = platform_info;
- break;
- case json_type_string:
- full_json_path = strdupa(json_object_get_string(args));
- result = platform_info;
- for(json_path = strtok(full_json_path, "."); json_path && *json_path; json_path = strtok(NULL, ".")) {
- if(! json_object_object_get_ex(result, json_path, &result)) {
- afb_req_fail(req, "A key hasn't been found in JSON path.", json_path);
- return;
+ pinfo_api_ctx_t *api_ctx = (pinfo_api_ctx_t*)afb_api_get_userdata(req->api);
+
+ if(api_ctx) {
+ json_object *result = NULL;
+ json_object *args = afb_req_json(req);
+
+ switch (json_object_get_type(args)) {
+ case json_type_null:
+ result = api_ctx->info;
+ break;
+ case json_type_string: {
+ char *json_path = NULL;
+ char *full_json_path = NULL;
+
+ full_json_path = strdupa(json_object_get_string(args));
+ result = api_ctx->info;
+
+ for(json_path = strtok(full_json_path, ".");
+ json_path && *json_path;
+ json_path = strtok(NULL, ".")) {
+ if(! json_object_object_get_ex(result, json_path, &result)) {
+ afb_req_fail(req, "A key hasn't been found in JSON path.", json_path);
+ return;
+ }
}
+ break;
}
- break;
- default:
- afb_req_fail(req, "Type error", "Argument type is unknown, you must provide a string only");
- return;
- }
+ default:
+ afb_req_fail(req, "Type error", "Argument type is unknown, you must provide a string only");
+ return;
+ }
- afb_req_success(req, json_object_get(result), NULL);
+ afb_req_success(req, json_object_get(result), NULL);
+ } else {
+ afb_req_fail(req,"failed","The API contains no context!");
+ }
}
void afv_set(afb_req_t req) {
@@ -75,27 +88,60 @@ void afv_set(afb_req_t req) {
afb_req_success(req, NULL, NULL);
}
-// TODO RFOR: interface with inotify and udev
+// TODO RFOR: interface with inotify
void afv_unsubscribe(afb_req_t req) {
- afb_req_success(req, NULL, NULL);
+ pinfo_client_ctx_t* client_ctx = NULL;
+ client_ctx = (pinfo_client_ctx_t*)afb_req_context_get(req);
+
+ if(client_ctx) {
+ const char* event_str = afb_req_value(req,"event");
+
+ if(event_str && strcmp("monitor-devices",event_str) == 0) {
+ afb_req_unsubscribe(req,client_ctx->ev_devs_changed);
+ afb_req_context_clear(req);
+ afb_req_success(req,NULL, NULL);
+ } else {
+ afb_req_fail(req,"failed","No 'event' value provided.");
+ }
+ } else {
+ afb_req_fail(req,"failed","No context available for the client.");
+ }
}
void afv_subscribe(afb_req_t req) {
- afb_req_success(req, NULL, NULL);
+ const char* event_str = NULL;
+ event_str = afb_req_value(req,"event");
+
+ if(event_str && strcmp("monitor-devices",event_str) == 0) {
+ if(!afb_req_context_get(req)) {
+ if(pinfo_device_monitor(req) == PINFO_OK) {
+ afb_req_success(req,NULL,NULL);
+ } else {
+ afb_req_fail(req,"failed","Unable to create new context");
+ }
+ } else {
+ afb_req_fail(req,"failed","The client already subscribed.");
+ }
+ } else {
+ afb_req_fail(req,"failed","Invalid event subscription");
+ }
}
-int init(afb_api_t api) {
+static json_object*
+afv_static_info(const char* dir) {
struct dirent* dir_ent = NULL;
+ DIR* dir_handle = opendir(dir);
+ json_object* static_info = NULL;
- DIR* dir_handle = opendir(PLATFORM_INFO_DIR);
if (! dir_handle) {
AFB_ERROR("The directory %s does not exist.", PLATFORM_INFO_DIR);
- return -1;
+ return NULL;
}
- json_object *json_file = json_object_new_object(), *current_file = NULL;
+ static_info = json_object_new_object();
while( (dir_ent = readdir(dir_handle)) != NULL) {
if(dir_ent->d_type == DT_REG && dir_ent->d_name[0] != '.') {
+ json_object* current_file = NULL;
size_t filepath_len = strlen(PLATFORM_INFO_DIR) + strlen(dir_ent->d_name) + 2;
char *filepath = alloca(filepath_len);
@@ -117,14 +163,35 @@ int init(afb_api_t api) {
continue;
}
#endif
- wrap_json_object_add(json_file, current_file);
- AFB_DEBUG("JSON loaded: %s", json_object_get_string(json_file));
+ wrap_json_object_add(static_info, current_file);
+ AFB_DEBUG("JSON loaded: %s",
+ json_object_to_json_string_ext(current_file,JSON_C_TO_STRING_PRETTY));
}
}
+ return static_info;
+}
+
+int init(afb_api_t api) {
// Initializing the platform_info binding object and associated it to
// the api
- afb_api_set_userdata(api, (void*)json_file);
+ AFB_DEBUG("init() ...");
+ pinfo_api_ctx_t *api_ctx = NULL;
+ int ret = PINFO_OK;
+
+ api_ctx = malloc(sizeof(*api_ctx));
+
+ if(api_ctx) {
+ AFB_DEBUG("init() ... OK");
+ api_ctx->info = afv_static_info(PLATFORM_INFO_DIR);
+ AFB_API_DEBUG(api,"The API static data: %s",
+ json_object_to_json_string_ext(api_ctx->info, JSON_C_TO_STRING_PRETTY));
+ api_ctx->client_count = 0;
+ afb_api_set_userdata(api, (void*)api_ctx);
+ } else {
+ AFB_API_WARNING(api,"Failed to load the static data");
+ ret = PINFO_ERR;
+ }
- return 0;
+ return ret;
}