blob: 6e67569be2920ddb3b21ada67917bbc29fff8589 [file] [log] [blame]
LUOJian60136c32023-11-24 13:59:45 +08001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <pthread.h>
9#include <libubox/blobmsg_json.h>
10#include "libubus.h"
11#include "mbtk_fota.h"
LUOJian09598702023-12-14 13:58:42 +080012#include <semaphore.h>
luojian49e53402024-06-05 15:37:57 +080013#include <cutils/properties.h>
LUOJian60136c32023-11-24 13:59:45 +080014
luojian487f2352024-08-16 17:51:48 +080015#include "mbtk_log.h"
16
LUOJian60136c32023-11-24 13:59:45 +080017
18#ifdef DEBUG
19 #define fota_log(...) printf(__VA_ARGS__)
20#else
21 #define fota_log(...)
22#endif
23
24#define UNUSEDPARAM(param) (void)param;
25#define OTA_MAX_STRING_LEN 128
26
27static struct ubus_context *fota_ubus_ctx = NULL;
28static uint32_t fota_request_id;
29static struct ubus_subscriber notification_event;
30static pthread_t fota_status_pthread;
31static struct blob_buf b;
32static fota_callback fota_cb = NULL;
LUOJian09598702023-12-14 13:58:42 +080033sem_t sem;
LUOJian9a2d3ba2024-01-05 17:14:41 +080034volatile int fota_dowload_flag = -1;
35//3: upding
36//4: updata success
37//5: updata fail
LUOJian60136c32023-11-24 13:59:45 +080038
39enum {
40 ATTR_SMSGPS,
41 ATTR_SMSGPS_MAX,
42};
43
44static const struct blobmsg_policy ota_info_attr_policy[] = {
45 [ATTR_SMSGPS] ={.name = "notification", .type = BLOBMSG_TYPE_STRING,},
46};
47
48/**
49 * \brief strstr_n
50 *
51 * find string return number
52 *
53 * \param param
54 * \return return type
55 */
56static int strstr_n(const char *s1, const char *s2)
57{
58 int n;
59 int strlen = 0;
60
61 if(*s2) {
62 while(*s1) {
63 for(n = 0; *(s1+n) == *(s2 + n); n++) {
64 if(!*(s2 + n + 1)) {
65 strlen++;
66 return strlen;
67 }
68 }
69 s1++;
70 strlen++;
71 }
72 return 0;
73 }
74 else
75 return 0;
76}
77
78static int otad_notify(struct ubus_context* ctx, struct ubus_object* obj,
79 struct ubus_request_data* req, const char* method,
80 struct blob_attr* msg)
81{
82 UNUSEDPARAM(ctx);
83 UNUSEDPARAM(obj);
84 UNUSEDPARAM(req);
85 UNUSEDPARAM(method);
86 // User can get downloading process information from here
87 int ret, len;
88 char progress[4] = {0};
89 char *notify_str;
90
91 struct blob_attr *tb[ATTR_SMSGPS_MAX];
92 ret = blobmsg_parse(ota_info_attr_policy, ARRAY_SIZE(ota_info_attr_policy), tb,
93 blob_data(msg), blob_len(msg));
94
95 if (ret || !tb[ATTR_SMSGPS]) {
96 printf("invalid SMS\n");
97 return -1;
98 }
99
100 notify_str = blobmsg_get_string(tb[ATTR_SMSGPS]);
101 len = strlen(notify_str);
luojian487f2352024-08-16 17:51:48 +0800102 LOGE("%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800103// printf("L11111%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian60136c32023-11-24 13:59:45 +0800104 if (strstr_n(notify_str, "start")) {
105 fota_cb(0, 0);
106 } else if (strstr_n(notify_str, "end[1]")) {
107 fota_cb(0, 100);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800108 fota_dowload_flag = 4;
LUOJian09598702023-12-14 13:58:42 +0800109// sem_post(&sem);
luojian487f2352024-08-16 17:51:48 +0800110 LOGE("download firmware success!\r\n");
LUOJian60136c32023-11-24 13:59:45 +0800111 } else if (strstr_n(notify_str, "end[0]")) {
112 fota_cb(1, 100);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800113 fota_dowload_flag = 5;
LUOJian09598702023-12-14 13:58:42 +0800114// sem_post(&sem);
luojian487f2352024-08-16 17:51:48 +0800115 LOGE("download firmware fail!\r\n");
LUOJian60136c32023-11-24 13:59:45 +0800116 }
117 ret = strstr_n(notify_str, "progress");
118 if (ret) {
119 memcpy(progress, &notify_str[ret + 8], len - ret - 9);
120 fota_cb(0, atoi(progress));
121 }
122 return 0;
123}
124
125static void otad_subscriber_remove_cb(struct ubus_context* ctx,
126 struct ubus_subscriber* obj, uint32_t id)
127{
128 UNUSEDPARAM(ctx);
129 UNUSEDPARAM(obj);
130 UNUSEDPARAM(id);
luojian487f2352024-08-16 17:51:48 +0800131 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800132}
133
134
135/*******************************************************************************
136* @brief write firmware package, the firmware package is written in segments.
137 and The result of the write is output by calling the callback function.
138 the firmware package size must less than 32MB
139 @param
140 fname: firmware package file
141 segment_size: the length of once write, recommending 3*1024*1024 bytes
142 @return
143 if success return 0, else return -1
144 *******************************************************************************/
145int mbtk_fota_fw_write(char* fname, int segment_size)
146{
LUOJian9a2d3ba2024-01-05 17:14:41 +0800147 fota_dowload_flag = 3;
luojian487f2352024-08-16 17:51:48 +0800148 LOGE("mbtk_fota_fw_write start3\n");
LUOJian09598702023-12-14 13:58:42 +0800149 int ret = -1;
LUOJian60136c32023-11-24 13:59:45 +0800150 static struct ubus_request req;
151 int _segment_size;
luojian487f2352024-08-16 17:51:48 +0800152 char cmd[128]={0};
153
154 if(!access("/sys/power/wake_lock", W_OK))
155 {
156 sprintf(cmd, "echo %s > /sys/power/wake_lock", "ota_lock");
157 system(cmd);
158 LOGE("/sys/power/wake_lock success\n");
159 }
160 else
161 {
162 LOGE("/sys/power/wake_lock can not write.\n");
163 }
164
LUOJian60136c32023-11-24 13:59:45 +0800165 blob_buf_init(&b, 0);
166 blobmsg_add_string(&b, "url", fname);
167 blobmsg_add_u32(&b, "type", 2);
168 blobmsg_add_u32(&b, "sync", 1);
169 _segment_size = segment_size;
170 if (_segment_size > 1024) {
171 blobmsg_add_u32(&b, "segment_size", _segment_size);
172 }
173 blobmsg_add_u32(&b, "sync", 1);
174 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
175 ubus_complete_request_async(fota_ubus_ctx, &req);
luojian487f2352024-08-16 17:51:48 +0800176
LUOJian09598702023-12-14 13:58:42 +0800177 while(1)
178 {
luojian487f2352024-08-16 17:51:48 +0800179 /* V2������ */
LUOJian09598702023-12-14 13:58:42 +0800180// sem_wait(&sem);
181// break;
LUOJian60136c32023-11-24 13:59:45 +0800182
LUOJian9a2d3ba2024-01-05 17:14:41 +0800183 if(fota_dowload_flag != 3)
LUOJian09598702023-12-14 13:58:42 +0800184 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800185 // printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
LUOJian09598702023-12-14 13:58:42 +0800186 break;
187 }
luojian487f2352024-08-16 17:51:48 +0800188 sleep(1);
LUOJian09598702023-12-14 13:58:42 +0800189 }
luojian487f2352024-08-16 17:51:48 +0800190
191 if(!access("/sys/power/wake_unlock", W_OK))
192 {
193 char cmd[128]={0};
194 sprintf(cmd, "echo %s > /sys/power/wake_unlock", "ota_lock");
195 system(cmd);
196 LOGE("/sys/power/wake_unlock success\n");
197 }
198 else
199 {
200 LOGE("/sys/power/wake_unlock can not write.\n");
201 }
202 LOGE("%s, fota_dowload_flag = :%d", __FUNCTION__, fota_dowload_flag);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800203 if(fota_dowload_flag == 4)
LUOJian09598702023-12-14 13:58:42 +0800204 {
205 ret = 0;
206 }
207 return ret;
LUOJian60136c32023-11-24 13:59:45 +0800208}
209
LUOJian60136c32023-11-24 13:59:45 +0800210/*******************************************************************************
211* @brief download firmware by url, and write firmware package, the firmware
212 package is written in segments. The result of the write is output by
213 calling the callback function. the firmware package size must less than
214 32MB
215 @param
216 url: [IN] the address of download firmware package file, the url
217 support http or https protocol.
218 segment_size: [IN] the length of once write, recommending 3*1024*1024 bytes
219 conn_timeout: [IN] timeout to connect to the server, if set 0 that means
220 switch to the default build-in connection timeout(300s)
221 download_timeout: [IN] timeout for download the firmware file. if set 0 that means
222 it never time out
223 @return
224 if success return 0, else return -1
225 *******************************************************************************/
226int mbtk_fota_fw_write_by_url(char* url, int segment_size,
227 int conn_timeout, int download_timeout)
228{
luojian487f2352024-08-16 17:51:48 +0800229 LOGE("mbtk_fota_fw_write_by_url start2\n");
230 int ret = -1;
LUOJian9a2d3ba2024-01-05 17:14:41 +0800231 fota_dowload_flag = 3;
LUOJian60136c32023-11-24 13:59:45 +0800232 static struct ubus_request req;
233 int _segment_size;
luojian487f2352024-08-16 17:51:48 +0800234 char cmd[128]={0};
235
236 if(!access("/sys/power/wake_lock", W_OK))
237 {
238 sprintf(cmd, "echo %s > /sys/power/wake_lock", "ota_lock");
239 system(cmd);
240 LOGE("/sys/power/wake_lock success\n");
241 }
242 else
243 {
244 LOGE("/sys/power/wake_lock can not write.\n");
245 }
246
LUOJian60136c32023-11-24 13:59:45 +0800247 blob_buf_init(&b, 0);
248 blobmsg_add_string(&b, "url", url);
249 blobmsg_add_string(&b, "username", "user name");
250 blobmsg_add_u32(&b, "type", 0);
251 blobmsg_add_u32(&b, "sync", 1);
252 _segment_size = segment_size;
253 if (_segment_size > 1024) {
254 blobmsg_add_u32(&b, "segment_size", _segment_size);
255 }
256 blobmsg_add_u32(&b, "sync", 1);
257 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
258 ubus_complete_request_async(fota_ubus_ctx, &req);
LUOJian09598702023-12-14 13:58:42 +0800259
260 while(1)
261 {
luojian487f2352024-08-16 17:51:48 +0800262 /* V2������ */
LUOJian09598702023-12-14 13:58:42 +0800263// sem_wait(&sem);
264// break;
265
LUOJian9a2d3ba2024-01-05 17:14:41 +0800266 if(fota_dowload_flag != 3)
LUOJian09598702023-12-14 13:58:42 +0800267 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800268 // printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
LUOJian09598702023-12-14 13:58:42 +0800269 break;
270 }
luojian487f2352024-08-16 17:51:48 +0800271 sleep(1);
LUOJian09598702023-12-14 13:58:42 +0800272 }
273
luojian487f2352024-08-16 17:51:48 +0800274 if(!access("/sys/power/wake_unlock", W_OK))
275 {
276 char cmd[128]={0};
277 sprintf(cmd, "echo %s > /sys/power/wake_unlock", "ota_lock");
278 system(cmd);
279 LOGE("/sys/power/wake_unlock success\n");
280 }
281 else
282 {
283 LOGE("/sys/power/wake_unlock can not write.\n");
284 }
285
286 LOGE("%s, fota_dowload_flag = :%d", __FUNCTION__, fota_dowload_flag);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800287 if(fota_dowload_flag == 4)
LUOJian09598702023-12-14 13:58:42 +0800288 {
289 ret = 0;
290 }
291 return ret;
292
LUOJian60136c32023-11-24 13:59:45 +0800293}
294/*******************************************************************************
295* @brief reboot system and clear env
296 @param
297 is_reboot: if set 1, after fota success, reboot system
298 @return
299 if success return 0, else return -1
300 *******************************************************************************/
301int mbtk_fota_done(int is_reboot)
302{
303 int ret;
304
305 ret = pthread_cancel(fota_status_pthread);
luojian487f2352024-08-16 17:51:48 +0800306 LOGE("kill pthread : %d \n", ret);
LUOJian60136c32023-11-24 13:59:45 +0800307 pthread_join(fota_status_pthread, NULL);
308 do {
309 ret = pthread_kill(fota_status_pthread, 0);
luojian487f2352024-08-16 17:51:48 +0800310 LOGE("kill pthread: %d \n", ret);
LUOJian60136c32023-11-24 13:59:45 +0800311 if (ret == ESRCH) {
luojian487f2352024-08-16 17:51:48 +0800312 LOGE("The specified thread does not exist or has terminated\n");
LUOJian60136c32023-11-24 13:59:45 +0800313 } else if (ret == EINVAL) {
luojian487f2352024-08-16 17:51:48 +0800314 LOGE("Useless signal\n");
LUOJian60136c32023-11-24 13:59:45 +0800315 } else {
luojian487f2352024-08-16 17:51:48 +0800316 LOGE("The thread exists\n");
LUOJian60136c32023-11-24 13:59:45 +0800317 }
318 usleep(100000);
319 } while (0 == ret);
320
321
322 ubus_free(fota_ubus_ctx);
323 uloop_done();
324
325 fota_cb = NULL;
326
327 if (is_reboot) {
328 system("sync");
329 system("reboot");
330 }
331 return 0;
LUOJian9a2d3ba2024-01-05 17:14:41 +0800332
333}
334
335int mbtk_fota_done1(int is_reboot)
336{
337 if (is_reboot) {
338 system("sync");
339 system("reboot");
340 }
341 return 0;
LUOJian60136c32023-11-24 13:59:45 +0800342}
343
344void* mbtk_fota_thread(void* argc)
345{
346 int ret, retries = 0;
347 UNUSEDPARAM(argc);
348
LUOJian09598702023-12-14 13:58:42 +0800349 printf("mbtk_fota_thread() start\n");
350 pthread_detach(pthread_self());
LUOJian60136c32023-11-24 13:59:45 +0800351 //register for ril indication
352 ret = ubus_register_subscriber(fota_ubus_ctx, &notification_event);
353 if (ret) {
luojian487f2352024-08-16 17:51:48 +0800354 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800355 pthread_exit(NULL);
356 }
357 notification_event.cb = otad_notify;
358 notification_event.remove_cb = otad_subscriber_remove_cb;
359
360 ubus_subscribe(fota_ubus_ctx, &notification_event, fota_request_id);
361 uloop_run();
362 ubus_unsubscribe(fota_ubus_ctx, &notification_event, fota_request_id);
363 pthread_exit(NULL);
364
365 return NULL;
366}
367
368
369int mbtk_fota_init(fota_callback cb)
370{
371 int id;
372 int retries = 0;
373
374 /*create ubus loop to listen to RIL event*/
375 uloop_init();
376 fota_ubus_ctx = ubus_connect(NULL);
377 if (!fota_ubus_ctx) {
luojian487f2352024-08-16 17:51:48 +0800378 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800379 uloop_done();
380 return 0;
381 }
382
383 ubus_add_uloop(fota_ubus_ctx);
384
385 do {
386 //register for ril request
387 retries = 0;
388 if (ubus_lookup_id(fota_ubus_ctx, "ota", &fota_request_id)) {
luojian487f2352024-08-16 17:51:48 +0800389 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800390 sleep(1);
391 } else {
392 break;
393 }
394 } while (retries++ < 20);
395 if (retries >= 20) {
luojian487f2352024-08-16 17:51:48 +0800396 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800397 goto fail1;
398 }
399 pthread_create(&fota_status_pthread, NULL, (void*)mbtk_fota_thread, NULL);
400 fota_cb = cb;
LUOJian60136c32023-11-24 13:59:45 +0800401 return 0;
LUOJian09598702023-12-14 13:58:42 +0800402fail1:
403 return 1;
LUOJian60136c32023-11-24 13:59:45 +0800404}
405
luojian17de8c52024-05-31 09:46:11 +0800406int mbtk_fota_get_asr_reboot_cnt_flag(void)
luojianb72371a2024-04-23 17:47:46 +0800407{
luojian49e53402024-06-05 15:37:57 +0800408 int type = 0;
409 char time_type[] ={0};
410 property_get("persist.mbtk.reboot_cnt", time_type, "0");
luojianb72371a2024-04-23 17:47:46 +0800411
luojian49e53402024-06-05 15:37:57 +0800412 type = atoi(time_type);
luojianb72371a2024-04-23 17:47:46 +0800413
luojian49e53402024-06-05 15:37:57 +0800414 return type;
luojianb72371a2024-04-23 17:47:46 +0800415}
416
417
LUOJian9a2d3ba2024-01-05 17:14:41 +0800418int mbtk_fota_status(void)
419{
420 return fota_dowload_flag;
421}
422
423
luojian487f2352024-08-16 17:51:48 +0800424
425
426
427