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, &notify_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, &notification_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, &notification_event, fota_request_id);
+    uloop_run();
+    ubus_unsubscribe(fota_ubus_ctx, &notification_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;
+}