From 980b0dbc25e1b423562b87bc402c09329c039212 Mon Sep 17 00:00:00 2001 From: Farshid Monhaseri Date: Tue, 10 Nov 2020 14:20:08 +0330 Subject: Add 'scan' verb for runtime device scan Changes: - Add 'scan' verb so client can pass 'filter'(udev rules in JSON format) and 'mask' (desired data fields mask) arguments. 'filter' & 'mask' can include 'properties' and 'attributes' sub- fields so their key & values act as parameters for device scanning and mask the scanned devices properties & attributes when service report back. The 'filter' argument can contain an additional field with 'tags' key and JSON array value hence the tags will match for device scanning too. Bug-AGL: SPEC-3512 Signed-off-by: Farshid Monhaseri Change-Id: I83e91ec4405a8144e1ee813633c4895214b5b9df --- src/platform-info-apidef.h | 8 ++++ src/platform-info-binding.c | 22 +++++++++- src/platform-info-devices.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ src/platform-info-devices.h | 3 +- 4 files changed, 133 insertions(+), 3 deletions(-) diff --git a/src/platform-info-apidef.h b/src/platform-info-apidef.h index c09da63..4dba262 100644 --- a/src/platform-info-apidef.h +++ b/src/platform-info-apidef.h @@ -5,6 +5,7 @@ static const struct afb_auth _afb_auths_platform_info[] = { void afv_get(afb_req_t req); void afv_set(afb_req_t req); + void afv_scan(afb_req_t req); void afv_subscribe(afb_req_t req); void afv_unsubscribe(afb_req_t req); @@ -23,6 +24,13 @@ static const struct afb_verb_v3 _afb_verbs_platform_info[] = { .info = "Set a platform data.", .session = AFB_SESSION_NONE }, + { + .verb = "scan", + .callback = afv_scan, + .auth = NULL, + .info = "Scan system devices", + .session = AFB_SESSION_NONE + }, { .verb = "unsubscribe", .callback = afv_unsubscribe, diff --git a/src/platform-info-binding.c b/src/platform-info-binding.c index 4ae3c70..8aecdfe 100644 --- a/src/platform-info-binding.c +++ b/src/platform-info-binding.c @@ -172,17 +172,35 @@ afv_static_info(const char* dir) { return static_info; } +void afv_scan(afb_req_t req) { + json_object* jres = NULL; + json_object* jfilter = NULL; + json_object* jmask = NULL; + json_object* jargs = afb_req_json(req); + + if(json_object_is_type(jargs,json_type_object)) { + json_object_object_get_ex(jargs,"filter",&jfilter); + json_object_object_get_ex(jargs,"mask",&jmask); + } + + jres = pinfo_device_scan(jfilter,jmask); + + if(jres) { + afb_req_success(req,jres,"Scan success"); + } else { + afb_req_fail(req,"failed","Scan failed"); + } +} + int init(afb_api_t api) { // Initializing the platform_info binding object and associated it to // the api - 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)); diff --git a/src/platform-info-devices.c b/src/platform-info-devices.c index 89796f1..785423b 100644 --- a/src/platform-info-devices.c +++ b/src/platform-info-devices.c @@ -34,6 +34,7 @@ static void pinfo_device_monitor_detect(pinfo_client_ctx_t* ctx, struct static json_object* pinfo_device_udevice_to_jdevice(struct udev_device* udevice, struct json_object* jmask); static void pinfo_device_jdev_destructor(json_object* jdevice, void* udevice); static int pinfo_device_filter_monitoring(pinfo_client_ctx_t* ctx); +static void pinfo_device_filter_scan(struct udev_enumerate* udev_enum, struct json_object* jfilter); static json_object* pinfo_device_udevice_to_jlist( struct udev_device* udevice, struct udev_list_entry*(*udevice_elist)(struct udev_device*), @@ -395,3 +396,105 @@ pinfo_device_monitor_loop(pinfo_client_ctx_t* ctx) { } return NULL; } + +static void +pinfo_device_filter_scan(struct udev_enumerate* udev_enum, json_object* jfilter) { + if(udev_enum && jfilter) { + if(json_object_is_type(jfilter,json_type_object)) { + json_object* jval = NULL; + + if(json_object_object_get_ex(jfilter,"tags",&jval)) { + if(json_object_is_type(jval,json_type_array)) { + int tag_idx = 0; + const int tags_count = json_object_array_length(jval); + + if(tags_count > 0) { + json_object* jtag = NULL; + + for(jtag = json_object_array_get_idx(jval,0); + jtag && tag_idx < tags_count; + jtag = json_object_array_get_idx(jtag,++tag_idx)) { + udev_enumerate_add_match_tag(udev_enum,json_object_get_string(jtag)); + } + } else { + //Empty json array for tags array + } + } else if(json_object_is_type(jval,json_type_string)) { + udev_enumerate_add_match_tag(udev_enum,json_object_get_string(jval)); + } else { + AFB_WARNING("Client passed invalid value for 'tags' field,\ + the value type should be a json array with json string items\ + or a json string, avoid the tags filtering"); + } + } + + if(json_object_object_get_ex(jfilter,"properties",&jval) && + json_object_is_type(jval,json_type_object)) { + if(json_object_object_length(jval) > 0) { + json_object_object_foreach(jval,key,value) { + udev_enumerate_add_match_property(udev_enum,key,json_object_get_string(value)); + } + } + } + + if(json_object_object_get_ex(jfilter,"attributes",&jval) && + json_object_is_type(jval,json_type_object)) { + if(json_object_object_length(jval) > 0) { + json_object_object_foreach(jval,key,value) { + udev_enumerate_add_match_sysattr(udev_enum,key,json_object_get_string(value)); + } + } + } + } + } +} + +json_object* +pinfo_device_scan(json_object *jfilter, json_object* jmask) { + json_object* jdevs_arr = NULL; + struct udev* udev_ctx = NULL; + + udev_ctx = udev_new(); + jdevs_arr = json_object_new_array(); + + if(udev_ctx) { + struct udev_enumerate *dev_enum = NULL; + + dev_enum = udev_enumerate_new(udev_ctx); + if(dev_enum) { + struct udev_list_entry *dev_elist = NULL; + struct udev_list_entry *dev_elist_head = NULL; + pinfo_device_filter_scan(dev_enum,jfilter); + + udev_enumerate_scan_devices(dev_enum); + dev_elist = udev_enumerate_get_list_entry(dev_enum); + if(dev_elist) { + struct udev_device *udevice = NULL; + struct json_object *jdevice = NULL; + int udev_num = 0; + int jdev_num = 0; + + udev_list_entry_foreach(dev_elist_head,dev_elist) { + const char* path = udev_list_entry_get_name(dev_elist_head); + udev_num++; + udevice = udev_device_new_from_syspath((struct udev*)udev_ctx,path); + jdevice = pinfo_device_udevice_to_jdevice(udevice,jmask); + if(jdevice) { + json_object_array_add(jdevs_arr,jdevice); + jdev_num++; + } else { + udev_device_unref(udevice); + } + } + AFB_INFO("[SCAN]: %d device detected, %d device info reported back.",udev_num,jdev_num); + } else { + AFB_WARNING("No device found or enumeration failed"); + } + } else { + AFB_DEBUG("Unable to allocate enumeration object."); + } + udev_enumerate_unref(dev_enum); + } + + return jdevs_arr; +} diff --git a/src/platform-info-devices.h b/src/platform-info-devices.h index ad658f9..59944d6 100644 --- a/src/platform-info-devices.h +++ b/src/platform-info-devices.h @@ -45,6 +45,7 @@ typedef struct { }pinfo_client_ctx_t; -int pinfo_device_monitor(afb_req_t req); +int pinfo_device_monitor(afb_req_t req); +struct json_object* pinfo_device_scan(json_object *jfilter, json_object* jmask); #endif -- cgit 1.2.3-korg