| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | *(C) Copyright 2016 notion International Ltd. |
| 3 | * All Rights Reserved |
| 4 | ******************************************************************************/ |
| 5 | /* ------------------------------------------------------------------------------------------------------------------- |
| 6 | * |
| 7 | * Filename: mgui_version.c |
| 8 | * |
| 9 | * Authors: yueguangkai |
| 10 | * |
| 11 | * Description: MGUI version interface |
| 12 | * |
| 13 | * HISTORY: |
| 14 | * |
| 15 | * Feb 23, 2016 - Initial Version |
| 16 | * |
| 17 | * Notes: |
| 18 | * |
| 19 | ******************************************************************************/ |
| 20 | |
| 21 | /****************************************************************************** |
| 22 | * Include files |
| 23 | ******************************************************************************/ |
| 24 | #include <stdio.h> |
| 25 | #include <stdlib.h> |
| 26 | #include <string.h> |
| 27 | #include <inttypes.h> |
| 28 | #include "mgui_utils.h" |
| 29 | #include "mgui_ubus.h" |
| 30 | #include "mgui_icons.h" |
| 31 | #include "mgui_version.h" |
| 32 | #include "mgui.h" |
| 33 | |
| 34 | /****************************************************************************** |
| 35 | * Structures |
| 36 | ******************************************************************************/ |
| 37 | |
| 38 | /****************************************************************************** |
| 39 | * Definitions |
| 40 | ******************************************************************************/ |
| 41 | //#define VERSION_DEBUG |
| 42 | |
| 43 | #define VERSION_UBUS_ID "version" |
| 44 | #define VERSION_UBUS_REQUEST "get_version" |
| 45 | |
| 46 | /****************************************************************************** |
| 47 | * Globals |
| 48 | ******************************************************************************/ |
| 49 | |
| 50 | /* version get_version */ |
| 51 | enum { |
| 52 | ATTR_VERSION_INFO = 0, |
| 53 | ATTR_SW_VERSION, |
| 54 | ATTR_HDWARE_VER, |
| 55 | ATTR_BUILD_TIME, |
| 56 | ATTR_CP_LTG_VER, |
| 57 | ATTR_CP_LWG_VER, |
| 58 | ATTR_MAC_ADDR, |
| 59 | }; |
| 60 | |
| 61 | static const struct blobmsg_policy version_info_attr_policy[] = { |
| 62 | [ATTR_VERSION_INFO] = {.name = "version_info", .type = BLOBMSG_TYPE_TABLE}, |
| 63 | [ATTR_SW_VERSION] = {.name = "sw_version", .type = BLOBMSG_TYPE_STRING}, |
| 64 | [ATTR_HDWARE_VER] = {.name = "hdware_ver", .type = BLOBMSG_TYPE_STRING}, |
| 65 | [ATTR_BUILD_TIME] = {.name = "build_time", .type = BLOBMSG_TYPE_STRING}, |
| 66 | [ATTR_CP_LTG_VER] = {.name = "CP_LTG_VER", .type = BLOBMSG_TYPE_STRING}, |
| 67 | [ATTR_CP_LWG_VER] = {.name = "CP_LWG_VER", .type = BLOBMSG_TYPE_STRING}, |
| 68 | [ATTR_MAC_ADDR] = {.name = "mac_addr", .type = BLOBMSG_TYPE_STRING}, |
| 69 | }; |
| 70 | |
| 71 | static struct blob_buf b; |
| 72 | |
| 73 | /****************************************************************************** |
| 74 | * Code |
| 75 | ******************************************************************************/ |
| 76 | |
| 77 | #ifdef VERSION_DEBUG |
| 78 | static const char *indent_str = "\t\t\t\t\t\t\t\t\t\t\t\t\t"; |
| 79 | |
| 80 | #define indent_printf(indent, ...) do { \ |
| 81 | if (indent > 0) \ |
| 82 | fwrite(indent_str, indent, 1, stderr); \ |
| 83 | fprintf(stderr, __VA_ARGS__); \ |
| 84 | } while(0) |
| 85 | |
| 86 | static void dump_attr_data(struct blob_attr *data, int indent, int next_indent); |
| 87 | |
| 88 | static void |
| 89 | dump_table(struct blob_attr *head, int len, int indent, bool array) |
| 90 | { |
| 91 | struct blob_attr *attr; |
| 92 | struct blobmsg_hdr *hdr; |
| 93 | |
| 94 | indent_printf(indent, "{\n"); |
| 95 | __blob_for_each_attr(attr, head, len) { |
| 96 | hdr = blob_data(attr); |
| 97 | if (!array) |
| 98 | indent_printf(indent + 1, "%s : ", hdr->name); |
| 99 | dump_attr_data(attr, 0, indent + 1); |
| 100 | } |
| 101 | indent_printf(indent, "}\n"); |
| 102 | } |
| 103 | |
| 104 | static void dump_attr_data(struct blob_attr *data, int indent, int next_indent) |
| 105 | { |
| 106 | int type = blobmsg_type(data); |
| 107 | switch(type) { |
| 108 | case BLOBMSG_TYPE_STRING: |
| 109 | indent_printf(indent, "%s\n", blobmsg_get_string(data)); |
| 110 | break; |
| 111 | case BLOBMSG_TYPE_INT8: |
| 112 | indent_printf(indent, "%d\n", blobmsg_get_u8(data)); |
| 113 | break; |
| 114 | case BLOBMSG_TYPE_INT16: |
| 115 | indent_printf(indent, "%d\n", blobmsg_get_u16(data)); |
| 116 | break; |
| 117 | case BLOBMSG_TYPE_INT32: |
| 118 | indent_printf(indent, "%d\n", blobmsg_get_u32(data)); |
| 119 | break; |
| 120 | case BLOBMSG_TYPE_INT64: |
| 121 | indent_printf(indent, "%"PRIu64"\n", blobmsg_get_u64(data)); |
| 122 | break; |
| 123 | case BLOBMSG_TYPE_TABLE: |
| 124 | case BLOBMSG_TYPE_ARRAY: |
| 125 | if (!indent) |
| 126 | indent_printf(indent, "\n"); |
| 127 | dump_table(blobmsg_data(data), blobmsg_data_len(data), |
| 128 | next_indent, type == BLOBMSG_TYPE_ARRAY); |
| 129 | break; |
| 130 | } |
| 131 | } |
| 132 | #endif /* VERSION_DEBUG */ |
| 133 | |
| 134 | static int version_info_parse_blobmsg(struct mgui_version_context *ctx, struct blob_attr *msg) |
| 135 | { |
| 136 | struct blob_attr *tb[ARRAY_SIZE(version_info_attr_policy)]; |
| 137 | int ret; |
| 138 | |
| 139 | MASSERT(ctx); |
| 140 | |
| 141 | ret = blobmsg_parse(version_info_attr_policy, ARRAY_SIZE(version_info_attr_policy), |
| 142 | tb, blob_data(msg), blob_len(msg)); |
| 143 | if (ret){ |
| 144 | MGUI_EMSG("parsing version blobmsg failed %d\n", ret); |
| 145 | return -1; |
| 146 | } |
| 147 | |
| 148 | if (!tb[ATTR_VERSION_INFO]) |
| 149 | return -1; |
| 150 | ret = blobmsg_parse(version_info_attr_policy, ARRAY_SIZE(version_info_attr_policy), tb, |
| 151 | blobmsg_data(tb[ATTR_VERSION_INFO]), |
| 152 | blobmsg_data_len(tb[ATTR_VERSION_INFO])); |
| 153 | if (ret){ |
| 154 | MGUI_EMSG("parsing version blobmsg failed %d\n", ret); |
| 155 | return -1; |
| 156 | } |
| 157 | |
| 158 | ctx->info.sw_version= blobmsg_get_string(tb[ATTR_SW_VERSION]); |
| 159 | ctx->info.hdware_ver= blobmsg_get_string(tb[ATTR_HDWARE_VER]); |
| 160 | ctx->info.build_time= blobmsg_get_string(tb[ATTR_BUILD_TIME]); |
| 161 | ctx->info.CP_LTG_VER= blobmsg_get_string(tb[ATTR_CP_LTG_VER]); |
| 162 | ctx->info.CP_LWG_VER= blobmsg_get_string(tb[ATTR_CP_LWG_VER]); |
| 163 | ctx->info.mac_addr= blobmsg_get_string(tb[ATTR_MAC_ADDR]); |
| 164 | |
| 165 | MGUI_IMSG("parsing version blobmsg sw_version = %s, hdware_ver = %s, build_time = %s, CP_LTG_VER = %s,CP_LWG_VER = %s,mac_addr = %s\n", |
| 166 | ctx->info.sw_version, |
| 167 | ctx->info.hdware_ver, |
| 168 | ctx->info.build_time, |
| 169 | ctx->info.CP_LTG_VER, |
| 170 | ctx->info.CP_LWG_VER, |
| 171 | ctx->info.mac_addr); |
| 172 | |
| 173 | return 0; |
| 174 | } |
| 175 | |
| 176 | static void version_info_data_cb(struct ubus_request *req, int type, struct blob_attr *msg) |
| 177 | { |
| 178 | struct mgui_version_context *version = (struct mgui_version_context *)req->priv; |
| 179 | int ret; |
| 180 | |
| 181 | MASSERT(version); |
| 182 | |
| 183 | MGUI_DMSG("version data received\n"); |
| 184 | |
| 185 | ret = version_info_parse_blobmsg(version, msg); |
| 186 | if (ret){ |
| 187 | MGUI_EMSG("parsing blobmsg failed %d\n", ret); |
| 188 | return; |
| 189 | } |
| 190 | |
| 191 | mgui_update_icon(version->mgui, MGUI_VERSION_ICON, version); |
| 192 | } |
| 193 | |
| 194 | static void version_complete_cb(struct ubus_request *req, int ret) |
| 195 | { |
| 196 | struct mgui_version_context *version = (struct mgui_version_context *)req->priv; |
| 197 | |
| 198 | MGUI_DMSG("version complete received\n"); |
| 199 | /* trigger screen refresh since this is a result of an async request */ |
| 200 | mgui_screen_refresh(version->mgui); |
| 201 | } |
| 202 | |
| 203 | |
| 204 | static inline int mgui_version_info_request(struct mgui_version_context *ctx) |
| 205 | { |
| 206 | return mgui_ubus_invoke_async(ctx->mgui->ubus, &b, ctx->version_ubus_id, |
| 207 | VERSION_UBUS_REQUEST, version_info_data_cb, version_complete_cb, ctx); |
| 208 | } |
| 209 | |
| 210 | /** |
| 211 | * mgui_version_exit |
| 212 | * De-initialize version interface |
| 213 | * |
| 214 | * @param version pointer to previously allocated version context |
| 215 | * |
| 216 | * @return 0 for success, error code otherwise |
| 217 | */ |
| 218 | int mgui_version_exit(struct mgui_version_context *version) |
| 219 | { |
| 220 | if(!version) { |
| 221 | MGUI_IMSG("version module not running\n"); |
| 222 | return 0; |
| 223 | } |
| 224 | |
| 225 | if (version->info.build_time) |
| 226 | free(version->info.build_time); |
| 227 | if (version->info.CP_LTG_VER) |
| 228 | free(version->info.CP_LTG_VER); |
| 229 | if (version->info.CP_LWG_VER) |
| 230 | free(version->info.CP_LWG_VER); |
| 231 | if (version->info.hdware_ver) |
| 232 | free(version->info.hdware_ver); |
| 233 | if (version->info.mac_addr) |
| 234 | free(version->info.mac_addr); |
| 235 | if (version->info.sw_version) |
| 236 | free(version->info.sw_version); |
| 237 | free(version); |
| 238 | |
| 239 | MGUI_IMSG("version exit done\n"); |
| 240 | |
| 241 | return 0; |
| 242 | } |
| 243 | |
| 244 | /** |
| 245 | * mgui_version_init |
| 246 | * Initialize mgui version interface |
| 247 | * |
| 248 | * NOTE - must be called BEFORE uloop_run()! |
| 249 | * |
| 250 | * @param mgui mgui context |
| 251 | * |
| 252 | * @return pointer to mgui_version_context |
| 253 | */ |
| 254 | struct mgui_version_context *mgui_version_init(struct mgui_context *mgui) |
| 255 | { |
| 256 | struct mgui_version_context *ver; |
| 257 | int ret; |
| 258 | |
| 259 | MASSERT(mgui); |
| 260 | MASSERT(mgui->ubus); |
| 261 | |
| 262 | ver = malloc(sizeof(struct mgui_version_context)); |
| 263 | if (!ver) { |
| 264 | MGUI_EMSG("memory allocation failed\n"); |
| 265 | return NULL; |
| 266 | } |
| 267 | |
| 268 | memset(ver, 0, sizeof(*ver)); |
| 269 | |
| 270 | ver->mgui = mgui; |
| 271 | |
| 272 | ret = mgui_ubus_lookup_id(ver->mgui->ubus, VERSION_UBUS_ID, |
| 273 | &ver->version_ubus_id); |
| 274 | if (ret) { |
| 275 | MGUI_EMSG("mubus_lookup_id failed (ret=%d)\n", ret); |
| 276 | goto out_error; |
| 277 | } |
| 278 | |
| 279 | ret = mgui_version_info_request(ver); |
| 280 | if (ret) { |
| 281 | MGUI_EMSG("initial request failed\n"); |
| 282 | goto out_error; |
| 283 | } |
| 284 | |
| 285 | MGUI_IMSG("version init done\n"); |
| 286 | |
| 287 | return ver; |
| 288 | |
| 289 | out_error: |
| 290 | free(ver); |
| 291 | return NULL; |
| 292 | } |