From 172db50c33beeb53f8e75c115699179be880b960 Mon Sep 17 00:00:00 2001 From: Farshid Monhaseri Date: Tue, 10 Nov 2020 13:05:37 +0330 Subject: 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 Change-Id: I0fc007d9707deaf39d21147aa8240fde302f5f9e --- src/platform-info-binding.c | 133 +++++++++++++++++++++++++++++++++----------- 1 file changed, 100 insertions(+), 33 deletions(-) (limited to 'src/platform-info-binding.c') 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" * @@ -23,6 +23,7 @@ #include #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; } -- cgit 1.2.3-korg