Add toolchain and mbtk source
Change-Id: Ie12546301367ea59240bf23d5e184ad7e36e40b3
diff --git a/mbtk/ql_lib/src/ql_fota.c b/mbtk/ql_lib/src/ql_fota.c
new file mode 100755
index 0000000..5894272
--- /dev/null
+++ b/mbtk/ql_lib/src/ql_fota.c
@@ -0,0 +1,306 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <libubox/blobmsg_json.h>
+#include "libubus.h"
+#include "ql/ql_fota.h"
+
+// #define DEBUG 1
+
+#ifdef DEBUG
+ #define fota_log(...) printf(__VA_ARGS__)
+#else
+ #define fota_log(...)
+#endif
+
+#define UNUSEDPARAM(param) (void)param;
+#define OTA_MAX_STRING_LEN 128
+
+static struct ubus_context *fota_ubus_ctx = NULL;
+static uint32_t fota_request_id;
+static struct ubus_subscriber notification_event;
+static pthread_t fota_status_pthread;
+static struct blob_buf b;
+static fota_callback fota_cb = NULL;
+
+enum {
+ ATTR_SMSGPS,
+ ATTR_SMSGPS_MAX,
+};
+
+static const struct blobmsg_policy ota_info_attr_policy[] = {
+ [ATTR_SMSGPS] ={.name = "notification", .type = BLOBMSG_TYPE_STRING,},
+};
+
+/**
+ * \brief strstr_n
+ *
+ * find string return number
+ *
+ * \param param
+ * \return return type
+ */
+static int strstr_n(const char *s1, const char *s2)
+{
+ int n;
+ int strlen = 0;
+
+ if(*s2) {
+ while(*s1) {
+ for(n = 0; *(s1+n) == *(s2 + n); n++) {
+ if(!*(s2 + n + 1)) {
+ strlen++;
+ return strlen;
+ }
+ }
+ s1++;
+ strlen++;
+ }
+ return 0;
+ }
+ else
+ return 0;
+}
+
+static int otad_notify(struct ubus_context* ctx, struct ubus_object* obj,
+ struct ubus_request_data* req, const char* method,
+ struct blob_attr* msg)
+{
+ UNUSEDPARAM(ctx);
+ UNUSEDPARAM(obj);
+ UNUSEDPARAM(req);
+ UNUSEDPARAM(method);
+ // User can get downloading process information from here
+ int ret, len;
+ char progress[4] = {0};
+ char *notify_str;
+
+ struct blob_attr *tb[ATTR_SMSGPS_MAX];
+ ret = blobmsg_parse(ota_info_attr_policy, ARRAY_SIZE(ota_info_attr_policy), tb,
+ blob_data(msg), blob_len(msg));
+
+ if (ret || !tb[ATTR_SMSGPS]) {
+ printf("invalid SMS\n");
+ return -1;
+ }
+
+ notify_str = blobmsg_get_string(tb[ATTR_SMSGPS]);
+ len = strlen(notify_str);
+ fota_log("%s : %s\r\n", __FUNCTION__, notify_str);
+ if (strstr_n(notify_str, "start")) {
+ fota_cb(0, 0);
+ } else if (strstr_n(notify_str, "end[1]")) {
+ fota_cb(0, 100);
+ printf("download firmware success!\r\n");
+ } else if (strstr_n(notify_str, "end[0]")) {
+ fota_cb(1, 100);
+ }
+ ret = strstr_n(notify_str, "progress");
+ if (ret) {
+ memcpy(progress, ¬ify_str[ret + 8], len - ret - 9);
+ fota_cb(0, atoi(progress));
+ }
+ return 0;
+}
+
+static void otad_subscriber_remove_cb(struct ubus_context* ctx,
+ struct ubus_subscriber* obj, uint32_t id)
+{
+ UNUSEDPARAM(ctx);
+ UNUSEDPARAM(obj);
+ UNUSEDPARAM(id);
+ fota_log("%s,%d\n", __FUNCTION__, __LINE__);
+}
+
+
+/*******************************************************************************\
+* Function: main
+\*******************************************************************************/
+void* fota_main(void* argc)
+{
+ int ret, retries = 0;
+ UNUSEDPARAM(argc);
+
+ //register for ril indication
+ ret = ubus_register_subscriber(fota_ubus_ctx, ¬ification_event);
+ if (ret) {
+ fota_log("%s,%d\n", __FUNCTION__, __LINE__);
+ pthread_exit(NULL);
+ }
+ notification_event.cb = otad_notify;
+ notification_event.remove_cb = otad_subscriber_remove_cb;
+
+ ubus_subscribe(fota_ubus_ctx, ¬ification_event, fota_request_id);
+ uloop_run();
+ ubus_unsubscribe(fota_ubus_ctx, ¬ification_event, fota_request_id);
+ pthread_exit(NULL);
+
+ return NULL;
+}
+
+int ql_fota_init(fota_callback cb)
+{
+ int id;
+ int retries = 0;
+
+ /*create ubus loop to listen to RIL event*/
+ uloop_init();
+ fota_ubus_ctx = ubus_connect(NULL);
+ if (!fota_ubus_ctx) {
+ fota_log("%s,%d\n", __FUNCTION__, __LINE__);
+ uloop_done();
+ return 0;
+ }
+
+ ubus_add_uloop(fota_ubus_ctx);
+
+ do {
+ //register for ril request
+ retries = 0;
+ if (ubus_lookup_id(fota_ubus_ctx, "ota", &fota_request_id)) {
+ fota_log("%s,%d\n", __FUNCTION__, __LINE__);
+ sleep(1);
+ } else {
+ break;
+ }
+ } while (retries++ < 20);
+ if (retries >= 20) {
+ printf("%s,%d\n", __FUNCTION__, __LINE__);
+ goto fail1;
+ }
+ pthread_create(&fota_status_pthread, NULL, (void*)fota_main, NULL);
+ fota_cb = cb;
+fail1:
+ return 0;
+}
+
+static void sync_prog_cb(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+ char *str;
+ if (!msg)
+ return;
+
+ /*
+ 在这里处理返回的消息。
+ 本例子只是将返回的消息打印出来。
+ */
+ str = blobmsg_format_json_indent(msg, true, 0);
+ printf("%s\n", str);
+
+ if (strstr_n(str, "end[1]")) {
+ fota_cb(0, 100);
+ printf("download firmware success!\r\n");
+ } else if (strstr_n(str, "end[0]") || strstr_n(str, "failed")) {
+ fota_cb(1, 0);
+ }
+ free(str);
+}
+/*******************************************************************************
+* @brief write firmware package, the firmware package is written in segments.
+ and The result of the write is output by calling the callback function.
+ the firmware package size must less than 32MB
+ @param
+ fname: firmware package file
+ segment_size: the length of once write, recommending 3*1024*1024 bytes
+ @return
+ if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_fw_write(char* fname, int segment_size)
+{
+ static struct ubus_request req;
+ int _segment_size;
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "url", fname);
+ blobmsg_add_u32(&b, "type", 2);
+ blobmsg_add_u32(&b, "sync", 1);
+ _segment_size = segment_size;
+ if (_segment_size > 1024) {
+ blobmsg_add_u32(&b, "segment_size", _segment_size);
+ }
+ // blobmsg_add_u32(&b, "segment_size", segment_size);
+ /* 调用"ota"对象的"download"方法 */
+ ubus_invoke(fota_ubus_ctx, fota_request_id,
+ "download", b.head, sync_prog_cb, NULL, 30 * 1000);
+
+ return 0;
+}
+
+
+/*******************************************************************************
+* @brief download firmware by url, and write firmware package, the firmware
+ package is written in segments. The result of the write is output by
+ calling the callback function. the firmware package size must less than
+ 32MB
+ @param
+ url: [IN] the address of download firmware package file, the url
+ support http or https protocol.
+ segment_size: [IN] the length of once write, recommending 3*1024*1024 bytes
+ conn_timeout: [IN] timeout to connect to the server, if set 0 that means
+ switch to the default build-in connection timeout(300s)
+ download_timeout: [IN] timeout for download the firmware file. if set 0 that means
+ it never time out
+ @return
+ if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_fw_write_by_url(char* url, int segment_size,
+ int conn_timeout, int download_timeout)
+{
+ static struct ubus_request req;
+ int _segment_size;
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "url", url);
+ blobmsg_add_string(&b, "username", "user name");
+ blobmsg_add_u32(&b, "type", 0);
+ blobmsg_add_u32(&b, "sync", 1);
+ _segment_size = segment_size;
+ if (_segment_size > 1024) {
+ blobmsg_add_u32(&b, "segment_size", _segment_size);
+ }
+ blobmsg_add_u32(&b, "sync", 1);
+ ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
+ ubus_complete_request_async(fota_ubus_ctx, &req);
+ return 0;
+}
+/*******************************************************************************
+* @brief reboot system and clear env
+ @param
+ is_reboot: if set 1, after fota success, reboot system
+ @return
+ if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_done(int is_reboot)
+{
+ int ret;
+
+ ret = pthread_cancel(fota_status_pthread);
+ fota_log("kill pthread : %d \n", ret);
+ pthread_join(fota_status_pthread, NULL);
+ do {
+ ret = pthread_kill(fota_status_pthread, 0);
+ fota_log("kill pthread: %d \n", ret);
+ if (ret == ESRCH) {
+ fota_log("The specified thread does not exist or has terminated\n");
+ } else if (ret == EINVAL) {
+ fota_log("Useless signal\n");
+ } else {
+ fota_log("The thread exists\n");
+ }
+ usleep(100000);
+ } while (0 == ret);
+
+
+ ubus_free(fota_ubus_ctx);
+ uloop_done();
+
+ fota_cb = NULL;
+
+ if (is_reboot) {
+ system("reboot");
+ }
+ return 0;
+}