blob: a26e2a6e880f24b10c87eb3158eae48a786b6994 [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;
32volatile int fota_dowload_flag = 0;
33
LUOJian60136c32023-11-24 13:59:45 +080034
35enum {
36 ATTR_SMSGPS,
37 ATTR_SMSGPS_MAX,
38};
39
40static const struct blobmsg_policy ota_info_attr_policy[] = {
41 [ATTR_SMSGPS] ={.name = "notification", .type = BLOBMSG_TYPE_STRING,},
42};
43
44/**
45 * \brief strstr_n
46 *
47 * find string return number
48 *
49 * \param param
50 * \return return type
51 */
52static int strstr_n(const char *s1, const char *s2)
53{
54 int n;
55 int strlen = 0;
56
57 if(*s2) {
58 while(*s1) {
59 for(n = 0; *(s1+n) == *(s2 + n); n++) {
60 if(!*(s2 + n + 1)) {
61 strlen++;
62 return strlen;
63 }
64 }
65 s1++;
66 strlen++;
67 }
68 return 0;
69 }
70 else
71 return 0;
72}
73
74static int otad_notify(struct ubus_context* ctx, struct ubus_object* obj,
75 struct ubus_request_data* req, const char* method,
76 struct blob_attr* msg)
77{
78 UNUSEDPARAM(ctx);
79 UNUSEDPARAM(obj);
80 UNUSEDPARAM(req);
81 UNUSEDPARAM(method);
82 // User can get downloading process information from here
83 int ret, len;
84 char progress[4] = {0};
85 char *notify_str;
86
87 struct blob_attr *tb[ATTR_SMSGPS_MAX];
88 ret = blobmsg_parse(ota_info_attr_policy, ARRAY_SIZE(ota_info_attr_policy), tb,
89 blob_data(msg), blob_len(msg));
90
91 if (ret || !tb[ATTR_SMSGPS]) {
92 printf("invalid SMS\n");
93 return -1;
94 }
95
96 notify_str = blobmsg_get_string(tb[ATTR_SMSGPS]);
97 len = strlen(notify_str);
98 fota_log("%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian09598702023-12-14 13:58:42 +080099 printf("L11111%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian60136c32023-11-24 13:59:45 +0800100 if (strstr_n(notify_str, "start")) {
101 fota_cb(0, 0);
102 } else if (strstr_n(notify_str, "end[1]")) {
103 fota_cb(0, 100);
LUOJian09598702023-12-14 13:58:42 +0800104 fota_dowload_flag = 1;
105// sem_post(&sem);
LUOJian60136c32023-11-24 13:59:45 +0800106 printf("download firmware success!\r\n");
107 } else if (strstr_n(notify_str, "end[0]")) {
108 fota_cb(1, 100);
LUOJian09598702023-12-14 13:58:42 +0800109 fota_dowload_flag = 2;
110// sem_post(&sem);
111 printf("download firmware fail!\r\n");
LUOJian60136c32023-11-24 13:59:45 +0800112 }
113 ret = strstr_n(notify_str, "progress");
114 if (ret) {
115 memcpy(progress, &notify_str[ret + 8], len - ret - 9);
116 fota_cb(0, atoi(progress));
117 }
118 return 0;
119}
120
121static void otad_subscriber_remove_cb(struct ubus_context* ctx,
122 struct ubus_subscriber* obj, uint32_t id)
123{
124 UNUSEDPARAM(ctx);
125 UNUSEDPARAM(obj);
126 UNUSEDPARAM(id);
127 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
128}
129
130
131/*******************************************************************************
132* @brief write firmware package, the firmware package is written in segments.
133 and The result of the write is output by calling the callback function.
134 the firmware package size must less than 32MB
135 @param
136 fname: firmware package file
137 segment_size: the length of once write, recommending 3*1024*1024 bytes
138 @return
139 if success return 0, else return -1
140 *******************************************************************************/
141int mbtk_fota_fw_write(char* fname, int segment_size)
142{
LUOJian09598702023-12-14 13:58:42 +0800143 fota_dowload_flag = 0;
144 printf("mbtk_fota_fw_write start2\n");
145 int L = 1;
146 int ret = -1;
LUOJian60136c32023-11-24 13:59:45 +0800147 static struct ubus_request req;
148 int _segment_size;
149 blob_buf_init(&b, 0);
150 blobmsg_add_string(&b, "url", fname);
151 blobmsg_add_u32(&b, "type", 2);
152 blobmsg_add_u32(&b, "sync", 1);
153 _segment_size = segment_size;
154 if (_segment_size > 1024) {
155 blobmsg_add_u32(&b, "segment_size", _segment_size);
156 }
157 blobmsg_add_u32(&b, "sync", 1);
158 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
159 ubus_complete_request_async(fota_ubus_ctx, &req);
LUOJian09598702023-12-14 13:58:42 +0800160#if 1
161 while(1)
162 {
163 if(L == 1)
164 {
165 printf("%s, L:%d", __FUNCTION__,L);
166 L++;
167 }
168 /* V2¨´¡Á¡Â */
169// sem_wait(&sem);
170// break;
LUOJian60136c32023-11-24 13:59:45 +0800171
LUOJian09598702023-12-14 13:58:42 +0800172 if(fota_dowload_flag != 0)
173 {
174 printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
175 break;
176 }
177 }
178#endif
179 printf("%s, L:%d, fota_dowload_flag = :%d", __FUNCTION__,L, fota_dowload_flag);
180 printf("mbtk_fota_fw_write end \n");
181 if(fota_dowload_flag == 1)
182 {
183 ret = 0;
184 }
185 return ret;
LUOJian60136c32023-11-24 13:59:45 +0800186}
187
LUOJian60136c32023-11-24 13:59:45 +0800188/*******************************************************************************
189* @brief download firmware by url, and write firmware package, the firmware
190 package is written in segments. The result of the write is output by
191 calling the callback function. the firmware package size must less than
192 32MB
193 @param
194 url: [IN] the address of download firmware package file, the url
195 support http or https protocol.
196 segment_size: [IN] the length of once write, recommending 3*1024*1024 bytes
197 conn_timeout: [IN] timeout to connect to the server, if set 0 that means
198 switch to the default build-in connection timeout(300s)
199 download_timeout: [IN] timeout for download the firmware file. if set 0 that means
200 it never time out
201 @return
202 if success return 0, else return -1
203 *******************************************************************************/
204int mbtk_fota_fw_write_by_url(char* url, int segment_size,
205 int conn_timeout, int download_timeout)
206{
LUOJian09598702023-12-14 13:58:42 +0800207 printf("mbtk_fota_fw_write_by_url start1\n");
208 int ret = -1, L = 1;
209 fota_dowload_flag = 0;
LUOJian60136c32023-11-24 13:59:45 +0800210 static struct ubus_request req;
211 int _segment_size;
212 blob_buf_init(&b, 0);
213 blobmsg_add_string(&b, "url", url);
214 blobmsg_add_string(&b, "username", "user name");
215 blobmsg_add_u32(&b, "type", 0);
216 blobmsg_add_u32(&b, "sync", 1);
217 _segment_size = segment_size;
218 if (_segment_size > 1024) {
219 blobmsg_add_u32(&b, "segment_size", _segment_size);
220 }
221 blobmsg_add_u32(&b, "sync", 1);
222 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
223 ubus_complete_request_async(fota_ubus_ctx, &req);
LUOJian09598702023-12-14 13:58:42 +0800224
225 while(1)
226 {
227 if(L == 1)
228 {
229 printf("%s, L:%d", __FUNCTION__,L);
230 L++;
231 }
232 /* V2¨´¡Á¡Â */
233// sem_wait(&sem);
234// break;
235
236 if(fota_dowload_flag != 0)
237 {
238 printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
239 break;
240 }
241 }
242
243 printf("%s, L:%d, fota_dowload_flag = :%d", __FUNCTION__,L, fota_dowload_flag);
244 printf("mbtk_fota_fw_write_by_url end \n");
245 if(fota_dowload_flag == 1)
246 {
247 ret = 0;
248 }
249 return ret;
250
LUOJian60136c32023-11-24 13:59:45 +0800251}
252/*******************************************************************************
253* @brief reboot system and clear env
254 @param
255 is_reboot: if set 1, after fota success, reboot system
256 @return
257 if success return 0, else return -1
258 *******************************************************************************/
259int mbtk_fota_done(int is_reboot)
260{
261 int ret;
262
263 ret = pthread_cancel(fota_status_pthread);
264 fota_log("kill pthread : %d \n", ret);
265 pthread_join(fota_status_pthread, NULL);
266 do {
267 ret = pthread_kill(fota_status_pthread, 0);
268 fota_log("kill pthread: %d \n", ret);
269 if (ret == ESRCH) {
270 fota_log("The specified thread does not exist or has terminated\n");
271 } else if (ret == EINVAL) {
272 fota_log("Useless signal\n");
273 } else {
274 fota_log("The thread exists\n");
275 }
276 usleep(100000);
277 } while (0 == ret);
278
279
280 ubus_free(fota_ubus_ctx);
281 uloop_done();
282
283 fota_cb = NULL;
284
285 if (is_reboot) {
286 system("sync");
287 system("reboot");
288 }
289 return 0;
290}
291
292void* mbtk_fota_thread(void* argc)
293{
294 int ret, retries = 0;
295 UNUSEDPARAM(argc);
296
LUOJian09598702023-12-14 13:58:42 +0800297 printf("mbtk_fota_thread() start\n");
298 pthread_detach(pthread_self());
LUOJian60136c32023-11-24 13:59:45 +0800299 //register for ril indication
300 ret = ubus_register_subscriber(fota_ubus_ctx, &notification_event);
301 if (ret) {
302 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
303 pthread_exit(NULL);
304 }
305 notification_event.cb = otad_notify;
306 notification_event.remove_cb = otad_subscriber_remove_cb;
307
308 ubus_subscribe(fota_ubus_ctx, &notification_event, fota_request_id);
309 uloop_run();
310 ubus_unsubscribe(fota_ubus_ctx, &notification_event, fota_request_id);
311 pthread_exit(NULL);
312
313 return NULL;
314}
315
316
317int mbtk_fota_init(fota_callback cb)
318{
319 int id;
320 int retries = 0;
321
322 /*create ubus loop to listen to RIL event*/
323 uloop_init();
324 fota_ubus_ctx = ubus_connect(NULL);
325 if (!fota_ubus_ctx) {
326 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
327 uloop_done();
328 return 0;
329 }
330
331 ubus_add_uloop(fota_ubus_ctx);
332
333 do {
334 //register for ril request
335 retries = 0;
336 if (ubus_lookup_id(fota_ubus_ctx, "ota", &fota_request_id)) {
337 fota_log("%s,%d\n", __FUNCTION__, __LINE__);
338 sleep(1);
339 } else {
340 break;
341 }
342 } while (retries++ < 20);
343 if (retries >= 20) {
344 printf("%s,%d\n", __FUNCTION__, __LINE__);
345 goto fail1;
346 }
347 pthread_create(&fota_status_pthread, NULL, (void*)mbtk_fota_thread, NULL);
348 fota_cb = cb;
LUOJian60136c32023-11-24 13:59:45 +0800349 return 0;
LUOJian09598702023-12-14 13:58:42 +0800350fail1:
351 return 1;
LUOJian60136c32023-11-24 13:59:45 +0800352}
353