diff --git a/dmtree/tr181/wifi.c b/dmtree/tr181/wifi.c index 8a0315a8..e0a20a1f 100644 --- a/dmtree/tr181/wifi.c +++ b/dmtree/tr181/wifi.c @@ -5353,9 +5353,22 @@ static int operate_WiFi_NeighboringWiFiDiagnostic(char *refparam, struct dmctx * char *signal_strength[2] = {0}; char *radio_name = dmjson_get_value(radios, 1, "name"); + if (!DM_STRLEN(radio_name)) + continue; + snprintf(object, sizeof(object), "wifi.radio.%s", radio_name); + + struct blob_buf bb; + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + blobmsg_add_string(&bb, "radio", radio_name); + blobmsg_add_string(&bb, "action", "scan_finished"); + dmubus_call_set(object, "scan", UBUS_ARGS{0}, 0); - sleep(2); // Wait for results to get populated in scanresults + + dmubus_register_event_blocking("wifi.radio", 30, bb.head); + blob_buf_free(&bb); + dmubus_call(object, "scanresults", UBUS_ARGS{0}, 0, &scan_res); if (!scan_res) diff --git a/libbbf_api/dmcommon.c b/libbbf_api/dmcommon.c index d11dd652..34257fb8 100644 --- a/libbbf_api/dmcommon.c +++ b/libbbf_api/dmcommon.c @@ -1746,3 +1746,83 @@ char *get_ipv6(char *interface_name) return (*ipstr) ? dmstrdup(ipstr) : ""; } + +static bool validate_blob_dataval(struct blob_attr *src_attr, struct blob_attr *dst_attr) +{ + if (!src_attr || !dst_attr) + return false; + + int src_type = blob_id(src_attr); + int dst_type = blob_id(dst_attr); + if (src_type != dst_type) + return false; + + void *src_val = blobmsg_data(src_attr); + void *dst_val = blobmsg_data(dst_attr); + + switch (src_type) { + case BLOBMSG_TYPE_STRING: + if (src_val == NULL && dst_val == NULL) + return true; + + if (src_val && dst_val && strcmp((char *)src_val, (char*)dst_val) == 0) + return true; + break; + default: + break; + } + + return false; +} + +/*********************************************************************//** +** +** validate_blob_message +** +** This API is to validate the 'src' blob message against 'dst' blob message. It +** validates the attributes(key:value pair) present in 'src' are also exist in 'dst'. +** 'dst' may have more attributes than 'src'. +** +** NOTE: currently we only support string type value in key:val i.e if the attribute +** in 'src' blob message is other than of type string (like array, table etc) this +** API will return false. +** +** \param src - blob message to validate +** \param dst - blob message against which the validation is performed +** +** \return true: if all key:value pairs in 'src' are present in 'dst' +** false: otherwise +** +**************************************************************************/ +bool validate_blob_message(struct blob_attr *src, struct blob_attr *dst) +{ + if (!src || !dst) + return false; + + size_t src_len = (size_t)blobmsg_data_len(src); + size_t dst_len = (size_t)blobmsg_data_len(dst); + + if (dst_len < src_len) + return false; + + bool res = true; + struct blob_attr *src_attr, *dst_attr; + + __blob_for_each_attr(src_attr, blobmsg_data(src), src_len) { + bool matched = false; + __blob_for_each_attr(dst_attr, blobmsg_data(dst), dst_len) { + if (strcmp(blobmsg_name(src_attr), blobmsg_name(dst_attr)) != 0) { + continue; + } + + matched = validate_blob_dataval(src_attr, dst_attr); + break; + } + if (matched == false) { + res = false; + break; + } + } + + return res; +} diff --git a/libbbf_api/dmcommon.h b/libbbf_api/dmcommon.h index 6c31731c..49809133 100644 --- a/libbbf_api/dmcommon.h +++ b/libbbf_api/dmcommon.h @@ -289,4 +289,5 @@ int check_browse_section(struct uci_section *s, void *data); int parse_proc_intf6_line(const char *line, const char *device, char *ipstr, size_t str_len); char *ioctl_get_ipv4(char *interface_name); char *get_ipv6(char *interface_name); +bool validate_blob_message(struct blob_attr *src, struct blob_attr *dst); #endif diff --git a/libbbf_api/dmubus.c b/libbbf_api/dmubus.c index 7e34ecc5..2ba4d71c 100644 --- a/libbbf_api/dmubus.c +++ b/libbbf_api/dmubus.c @@ -206,6 +206,78 @@ int dmubus_call_set(char *obj, char *method, struct ubus_arg u_args[], int u_arg return rc; } +struct dmubus_event_data { + struct uloop_timeout tm; + struct ubus_event_handler ev; + struct blob_attr *ev_msg; +}; + +static void dmubus_receive_event(struct ubus_context *ctx, struct ubus_event_handler *ev, + const char *type, struct blob_attr *msg) +{ + struct dmubus_event_data *data = container_of(ev, struct dmubus_event_data, ev); + + if (!msg) + return; + + if (validate_blob_message(data->ev_msg, msg) == true) { + uloop_end(); + } + + return; +} + +static void dmubus_listen_timeout(struct uloop_timeout *timeout) +{ + uloop_end(); +} + +/*********************************************************************//** +** +** dmubus_register_event_blocking +** +** This API is to wait for the specified event to arrive on ubus or the timeout +** whichever is earlier +** +** NOTE: since this is a blocking call so it should only be called from DM_ASYNC +** operations. +** +** \param event - event to be listened on ubus +** \param timeout - max time (seconds) to wait for the event +** \param type - event type for which the process need to wait +** +** E.G: event: wifi.radio, type: {"radio":"wl1","action":"scan_finished"} +** +**************************************************************************/ +void dmubus_register_event_blocking(char *event, int timeout, struct blob_attr *type) +{ + struct ubus_context *ctx = ubus_connect(NULL); + if (!ctx) + return; + + struct dmubus_event_data data = { + .tm.cb = dmubus_listen_timeout, + .ev.cb = dmubus_receive_event, + .ev_msg = type, + }; + + uloop_init(); + ubus_add_uloop(ctx); + + int ret = ubus_register_event_handler(ctx, &data.ev, event); + if (ret) + goto end; + + uloop_timeout_set(&data.tm, timeout * 1000); + uloop_run(); + uloop_done(); + ubus_unregister_event_handler(ctx, &data.ev); + +end: + ubus_free(ctx); + return; +} + static inline json_object *ubus_call_req(char *obj, char *method, struct blob_attr *attr) { __dm_ubus_call(obj, method, attr); diff --git a/libbbf_api/dmubus.h b/libbbf_api/dmubus.h index fd84d9cf..dba2b6ba 100644 --- a/libbbf_api/dmubus.h +++ b/libbbf_api/dmubus.h @@ -28,5 +28,6 @@ void dmubus_configure(struct ubus_context *ctx); void dmubus_update_cached_entries(); void dmubus_clean_endlife_entries(); void dmubus_set_caching_time(int seconds); +void dmubus_register_event_blocking(char *event, int timeout, struct blob_attr *type); #endif