blob: 424f64d3d5c1a249b59a4b1d3e6a4ca8f52b615c [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>
13
LUOJian60136c32023-11-24 13:59:45 +080014
15
16#ifdef DEBUG
17 #define fota_log(...) printf(__VA_ARGS__)
18#else
19 #define fota_log(...)
20#endif
21
22#define UNUSEDPARAM(param) (void)param;
23#define OTA_MAX_STRING_LEN 128
24
25static struct ubus_context *fota_ubus_ctx = NULL;
26static uint32_t fota_request_id;
27static struct ubus_subscriber notification_event;
28static pthread_t fota_status_pthread;
29static struct blob_buf b;
30static fota_callback fota_cb = NULL;
LUOJian09598702023-12-14 13:58:42 +080031sem_t sem;
LUOJian9a2d3ba2024-01-05 17:14:41 +080032volatile int fota_dowload_flag = -1;
33//3: upding
34//4: updata success
35//5: updata fail
LUOJian60136c32023-11-24 13:59:45 +080036
37enum {
38 ATTR_SMSGPS,
39 ATTR_SMSGPS_MAX,
40};
41
42static const struct blobmsg_policy ota_info_attr_policy[] = {
43 [ATTR_SMSGPS] ={.name = "notification", .type = BLOBMSG_TYPE_STRING,},
44};
45
46/**
47 * \brief strstr_n
48 *
49 * find string return number
50 *
51 * \param param
52 * \return return type
53 */
54static int strstr_n(const char *s1, const char *s2)
55{
56 int n;
57 int strlen = 0;
58
59 if(*s2) {
60 while(*s1) {
61 for(n = 0; *(s1+n) == *(s2 + n); n++) {
62 if(!*(s2 + n + 1)) {
63 strlen++;
64 return strlen;
65 }
66 }
67 s1++;
68 strlen++;
69 }
70 return 0;
71 }
72 else
73 return 0;
74}
75
76static int otad_notify(struct ubus_context* ctx, struct ubus_object* obj,
77 struct ubus_request_data* req, const char* method,
78 struct blob_attr* msg)
79{
80 UNUSEDPARAM(ctx);
81 UNUSEDPARAM(obj);
82 UNUSEDPARAM(req);
83 UNUSEDPARAM(method);
84 // User can get downloading process information from here
85 int ret, len;
86 char progress[4] = {0};
87 char *notify_str;
88
89 struct blob_attr *tb[ATTR_SMSGPS_MAX];
90 ret = blobmsg_parse(ota_info_attr_policy, ARRAY_SIZE(ota_info_attr_policy), tb,
91 blob_data(msg), blob_len(msg));
92
93 if (ret || !tb[ATTR_SMSGPS]) {
94 printf("invalid SMS\n");
95 return -1;
96 }
97
98 notify_str = blobmsg_get_string(tb[ATTR_SMSGPS]);
99 len = strlen(notify_str);
100 fota_log("%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800101// printf("L11111%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian60136c32023-11-24 13:59:45 +0800102 if (strstr_n(notify_str, "start")) {
103 fota_cb(0, 0);
104 } else if (strstr_n(notify_str, "end[1]")) {
105 fota_cb(0, 100);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800106 fota_dowload_flag = 4;
LUOJian09598702023-12-14 13:58:42 +0800107// sem_post(&sem);
LUOJian60136c32023-11-24 13:59:45 +0800108 printf("download firmware success!\r\n");
109 } else if (strstr_n(notify_str, "end[0]")) {
110 fota_cb(1, 100);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800111 fota_dowload_flag = 5;
LUOJian09598702023-12-14 13:58:42 +0800112// sem_post(&sem);
113 printf("download firmware fail!\r\n");
LUOJian60136c32023-11-24 13:59:45 +0800114 }
115 ret = strstr_n(notify_str, "progress");
116 if (ret) {
117 memcpy(progress, &notify_str[ret + 8], len - ret - 9);
118 fota_cb(0, atoi(progress));
119 }
120 return 0;
121}
122
123static void otad_subscriber_remove_cb(struct ubus_context* ctx,
124 struct ubus_subscriber* obj, uint32_t id)
125{
126 UNUSEDPARAM(ctx);
127 UNUSEDPARAM(obj);
128 UNUSEDPARAM(id);
129 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
130}
131
132
133/*******************************************************************************
134* @brief write firmware package, the firmware package is written in segments.
135 and The result of the write is output by calling the callback function.
136 the firmware package size must less than 32MB
137 @param
138 fname: firmware package file
139 segment_size: the length of once write, recommending 3*1024*1024 bytes
140 @return
141 if success return 0, else return -1
142 *******************************************************************************/
143int mbtk_fota_fw_write(char* fname, int segment_size)
144{
LUOJian9a2d3ba2024-01-05 17:14:41 +0800145 fota_dowload_flag = 3;
LUOJian09598702023-12-14 13:58:42 +0800146 printf("mbtk_fota_fw_write start2\n");
147 int L = 1;
148 int ret = -1;
LUOJian60136c32023-11-24 13:59:45 +0800149 static struct ubus_request req;
150 int _segment_size;
151 blob_buf_init(&b, 0);
152 blobmsg_add_string(&b, "url", fname);
153 blobmsg_add_u32(&b, "type", 2);
154 blobmsg_add_u32(&b, "sync", 1);
155 _segment_size = segment_size;
156 if (_segment_size > 1024) {
157 blobmsg_add_u32(&b, "segment_size", _segment_size);
158 }
159 blobmsg_add_u32(&b, "sync", 1);
160 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
161 ubus_complete_request_async(fota_ubus_ctx, &req);
LUOJian09598702023-12-14 13:58:42 +0800162#if 1
163 while(1)
164 {
165 if(L == 1)
166 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800167 // printf("%s, L:%d", __FUNCTION__,L);
LUOJian09598702023-12-14 13:58:42 +0800168 L++;
169 }
170 /* V2¨´¡Á¡Â */
171// sem_wait(&sem);
172// break;
LUOJian60136c32023-11-24 13:59:45 +0800173
LUOJian9a2d3ba2024-01-05 17:14:41 +0800174 if(fota_dowload_flag != 3)
LUOJian09598702023-12-14 13:58:42 +0800175 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800176 // printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
LUOJian09598702023-12-14 13:58:42 +0800177 break;
178 }
179 }
180#endif
LUOJian9a2d3ba2024-01-05 17:14:41 +0800181// printf("%s, L:%d, fota_dowload_flag = :%d", __FUNCTION__,L, fota_dowload_flag);
182// printf("mbtk_fota_fw_write end \n");
183 if(fota_dowload_flag == 4)
LUOJian09598702023-12-14 13:58:42 +0800184 {
185 ret = 0;
186 }
187 return ret;
LUOJian60136c32023-11-24 13:59:45 +0800188}
189
LUOJian60136c32023-11-24 13:59:45 +0800190/*******************************************************************************
191* @brief download firmware by url, and write firmware package, the firmware
192 package is written in segments. The result of the write is output by
193 calling the callback function. the firmware package size must less than
194 32MB
195 @param
196 url: [IN] the address of download firmware package file, the url
197 support http or https protocol.
198 segment_size: [IN] the length of once write, recommending 3*1024*1024 bytes
199 conn_timeout: [IN] timeout to connect to the server, if set 0 that means
200 switch to the default build-in connection timeout(300s)
201 download_timeout: [IN] timeout for download the firmware file. if set 0 that means
202 it never time out
203 @return
204 if success return 0, else return -1
205 *******************************************************************************/
206int mbtk_fota_fw_write_by_url(char* url, int segment_size,
207 int conn_timeout, int download_timeout)
208{
LUOJian09598702023-12-14 13:58:42 +0800209 printf("mbtk_fota_fw_write_by_url start1\n");
210 int ret = -1, L = 1;
LUOJian9a2d3ba2024-01-05 17:14:41 +0800211 fota_dowload_flag = 3;
LUOJian60136c32023-11-24 13:59:45 +0800212 static struct ubus_request req;
213 int _segment_size;
214 blob_buf_init(&b, 0);
215 blobmsg_add_string(&b, "url", url);
216 blobmsg_add_string(&b, "username", "user name");
217 blobmsg_add_u32(&b, "type", 0);
218 blobmsg_add_u32(&b, "sync", 1);
219 _segment_size = segment_size;
220 if (_segment_size > 1024) {
221 blobmsg_add_u32(&b, "segment_size", _segment_size);
222 }
223 blobmsg_add_u32(&b, "sync", 1);
224 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
225 ubus_complete_request_async(fota_ubus_ctx, &req);
LUOJian09598702023-12-14 13:58:42 +0800226
227 while(1)
228 {
229 if(L == 1)
230 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800231 // printf("%s, L:%d", __FUNCTION__,L);
LUOJian09598702023-12-14 13:58:42 +0800232 L++;
233 }
234 /* V2¨´¡Á¡Â */
235// sem_wait(&sem);
236// break;
237
LUOJian9a2d3ba2024-01-05 17:14:41 +0800238 if(fota_dowload_flag != 3)
LUOJian09598702023-12-14 13:58:42 +0800239 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800240 // printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
LUOJian09598702023-12-14 13:58:42 +0800241 break;
242 }
243 }
244
LUOJian9a2d3ba2024-01-05 17:14:41 +0800245 // printf("%s, L:%d, fota_dowload_flag = :%d", __FUNCTION__,L, fota_dowload_flag);
246 // printf("mbtk_fota_fw_write_by_url end \n");
247 if(fota_dowload_flag == 4)
LUOJian09598702023-12-14 13:58:42 +0800248 {
249 ret = 0;
250 }
251 return ret;
252
LUOJian60136c32023-11-24 13:59:45 +0800253}
254/*******************************************************************************
255* @brief reboot system and clear env
256 @param
257 is_reboot: if set 1, after fota success, reboot system
258 @return
259 if success return 0, else return -1
260 *******************************************************************************/
261int mbtk_fota_done(int is_reboot)
262{
263 int ret;
264
265 ret = pthread_cancel(fota_status_pthread);
266 fota_log("kill pthread : %d \n", ret);
267 pthread_join(fota_status_pthread, NULL);
268 do {
269 ret = pthread_kill(fota_status_pthread, 0);
270 fota_log("kill pthread: %d \n", ret);
271 if (ret == ESRCH) {
272 fota_log("The specified thread does not exist or has terminated\n");
273 } else if (ret == EINVAL) {
274 fota_log("Useless signal\n");
275 } else {
276 fota_log("The thread exists\n");
277 }
278 usleep(100000);
279 } while (0 == ret);
280
281
282 ubus_free(fota_ubus_ctx);
283 uloop_done();
284
285 fota_cb = NULL;
286
287 if (is_reboot) {
288 system("sync");
289 system("reboot");
290 }
291 return 0;
LUOJian9a2d3ba2024-01-05 17:14:41 +0800292
293}
294
295int mbtk_fota_done1(int is_reboot)
296{
297 if (is_reboot) {
298 system("sync");
299 system("reboot");
300 }
301 return 0;
LUOJian60136c32023-11-24 13:59:45 +0800302}
303
304void* mbtk_fota_thread(void* argc)
305{
306 int ret, retries = 0;
307 UNUSEDPARAM(argc);
308
LUOJian09598702023-12-14 13:58:42 +0800309 printf("mbtk_fota_thread() start\n");
310 pthread_detach(pthread_self());
LUOJian60136c32023-11-24 13:59:45 +0800311 //register for ril indication
312 ret = ubus_register_subscriber(fota_ubus_ctx, &notification_event);
313 if (ret) {
314 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
315 pthread_exit(NULL);
316 }
317 notification_event.cb = otad_notify;
318 notification_event.remove_cb = otad_subscriber_remove_cb;
319
320 ubus_subscribe(fota_ubus_ctx, &notification_event, fota_request_id);
321 uloop_run();
322 ubus_unsubscribe(fota_ubus_ctx, &notification_event, fota_request_id);
323 pthread_exit(NULL);
324
325 return NULL;
326}
327
328
329int mbtk_fota_init(fota_callback cb)
330{
331 int id;
332 int retries = 0;
333
334 /*create ubus loop to listen to RIL event*/
335 uloop_init();
336 fota_ubus_ctx = ubus_connect(NULL);
337 if (!fota_ubus_ctx) {
338 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
339 uloop_done();
340 return 0;
341 }
342
343 ubus_add_uloop(fota_ubus_ctx);
344
345 do {
346 //register for ril request
347 retries = 0;
348 if (ubus_lookup_id(fota_ubus_ctx, "ota", &fota_request_id)) {
349 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
350 sleep(1);
351 } else {
352 break;
353 }
354 } while (retries++ < 20);
355 if (retries >= 20) {
356 printf("%s,%d\n", __FUNCTION__, __LINE__);
357 goto fail1;
358 }
359 pthread_create(&fota_status_pthread, NULL, (void*)mbtk_fota_thread, NULL);
360 fota_cb = cb;
LUOJian60136c32023-11-24 13:59:45 +0800361 return 0;
LUOJian09598702023-12-14 13:58:42 +0800362fail1:
363 return 1;
LUOJian60136c32023-11-24 13:59:45 +0800364}
365
LUOJian9a2d3ba2024-01-05 17:14:41 +0800366int mbtk_fota_status(void)
367{
368 return fota_dowload_flag;
369}
370
371