diff options
author | Farshid Monhaseri <monhaseri.f@gmail.com> | 2020-11-10 14:20:08 +0330 |
---|---|---|
committer | Jan-Simon Moeller <jsmoeller@linuxfoundation.org> | 2020-11-10 15:04:30 +0000 |
commit | 980b0dbc25e1b423562b87bc402c09329c039212 (patch) | |
tree | bf579d7e5125e9926b1da9f3afdd58c861af3ea8 | |
parent | 172db50c33beeb53f8e75c115699179be880b960 (diff) |
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 <monhaseri.f@gmail.com>
Change-Id: I83e91ec4405a8144e1ee813633c4895214b5b9df
-rw-r--r-- | src/platform-info-apidef.h | 8 | ||||
-rw-r--r-- | src/platform-info-binding.c | 22 | ||||
-rw-r--r-- | src/platform-info-devices.c | 103 | ||||
-rw-r--r-- | 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); @@ -24,6 +25,13 @@ static const struct afb_verb_v3 _afb_verbs_platform_info[] = { .session = AFB_SESSION_NONE }, { + .verb = "scan", + .callback = afv_scan, + .auth = NULL, + .info = "Scan system devices", + .session = AFB_SESSION_NONE + }, + { .verb = "unsubscribe", .callback = afv_unsubscribe, .auth = NULL, 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 |