Change mbtk_source_v2
Change-Id: I0699762ab517b43060aad43fec0d87c2bfc1445d
diff --git a/mbtk/libmbtk_lib/common/ds_ASBuffer.cpp b/mbtk/libmbtk_lib/common/ds_ASBuffer.cpp
new file mode 100755
index 0000000..dc06fc1
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/ds_ASBuffer.cpp
@@ -0,0 +1,297 @@
+/*==============================================================================
+
+ ds_ASBuffer.cpp
+
+GENERAL DESCRIPTION
+ A buffer class with utility functions for parsing raw bytes.
+
+EXTERNALIZED FUNCTIONS
+
+INITIALIZATION AND SEQUENCING REQUIREMENTS
+ None
+
+ Copyright (c) 2014 by Qualcomm Technologies Incorporated. All Rights Reserved.
+==============================================================================*/
+
+/*==============================================================================
+ EDIT HISTORY FOR MODULE
+
+This section contains comments describing changes made to the module.
+Notice that changes are listed in reverse chronological order.
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+06/03/15 ml Remove memory allocation on default constructor
+05/20/15 ml Use memory from modem heap
+04/21/14 ml Created file/Initial version.
+==============================================================================*/
+#include "ds_ASBuffer.h"
+
+//#include "ds_appsrv_mem.h"
+#include <string.h>
+#include <mbtk_type.h>
+#include <stdlib.h>
+
+#include <cctype> // isspace
+
+
+// temp
+#include "ds_ASString.h"
+
+#define DEFAULT_BUFFER_SIZE 256
+
+// static const uint8 EMPTY_STRING[] = "";
+
+void memscpy(void* dest, size_t destLen, const void* src, size_t srcLen) {
+ if (srcLen <= destLen)
+ memcpy(dest, src, srcLen);
+}
+
+
+ASBuffer::ASBuffer()
+: buffer(NULL), buffer_size(0), buffer_capacity(DEFAULT_BUFFER_SIZE), error_status(false)
+{ }
+
+
+
+ASBuffer::ASBuffer(uint32 capacity)
+: buffer(NULL), buffer_size(0), buffer_capacity(capacity), error_status(false)
+{ }
+
+
+
+ASBuffer::ASBuffer(ASBuffer &buf)
+: buffer(NULL), buffer_size(0), buffer_capacity(buf.buffer_capacity), error_status(false)
+{
+ init();
+ append(buf);
+}
+
+
+
+ASBuffer::ASBuffer(const ASBuffer &buf)
+: buffer(NULL), buffer_size(0), buffer_capacity(buf.buffer_capacity), error_status(false)
+{
+ init();
+ append(buf);
+}
+
+
+
+ASBuffer::ASBuffer(const uint8* buf, uint32 buf_size)
+: buffer(NULL), buffer_size(0), buffer_capacity(buf_size), error_status(false)
+{
+ init();
+ append(buf, buf_size);
+}
+
+
+
+ASBuffer::~ASBuffer()
+{
+ if(NULL != buffer)
+ {
+ free(buffer);
+ buffer = NULL;
+ }
+}
+
+
+
+ASBuffer& ASBuffer::operator=(const ASBuffer &rhs)
+{
+ clear();
+ append(rhs);
+ return *this;
+}
+
+
+
+
+void ASBuffer::init()
+{
+ if(0 == buffer_capacity)
+ {
+ error_status = true;
+ }
+ else if(NULL == buffer)
+ {
+ buffer = (uint8*)malloc(sizeof(uint8) * (buffer_capacity+1));
+ error_status = (NULL == buffer);
+ }
+}
+
+
+
+// temp name
+#define DO_NOT_DOUBLE_IF_LARGER 2147483647
+bool ASBuffer::increment_buffer_capacity(const uint32 req_size)
+{
+ uint32 new_capacity = buffer_capacity;
+ uint8* tmp = NULL;
+
+ while(req_size > new_capacity)
+ {
+ // will cause overflow if doubled
+ if(DO_NOT_DOUBLE_IF_LARGER < new_capacity)
+ return false;
+
+ new_capacity *= 2;
+ }
+
+ tmp = (uint8*)malloc(sizeof(uint8) * new_capacity+1);
+ if(NULL == tmp)
+ return false;
+
+ memset(tmp, 0, new_capacity+1);
+ memscpy(tmp, new_capacity, buffer, buffer_size);
+ free(buffer);
+ buffer = NULL;
+
+ buffer = tmp;
+ buffer_capacity = new_capacity;
+
+ return true;
+}
+
+
+
+uint8* ASBuffer::non_const_content()
+{
+ return buffer;
+}
+
+
+const uint8* ASBuffer::content() const
+{
+ return buffer;
+}
+
+
+const char* ASBuffer::c_str() const
+{
+ if(NULL == buffer)
+ return "";
+ else
+ return (const char*)buffer;
+}
+
+
+
+uint32 ASBuffer::size() const
+{
+ return buffer_size;
+}
+
+
+
+bool ASBuffer::empty() const
+{
+ return (0 == buffer_size);
+}
+
+
+
+bool ASBuffer::error() const
+{
+ return error_status;
+}
+
+
+
+void ASBuffer::clear()
+{
+ if(NULL == buffer)
+ {
+ init();
+ }
+ else
+ {
+ memset(buffer, 0, buffer_capacity+1);
+ }
+ buffer_size = 0;
+}
+
+
+
+bool ASBuffer::append(const uint8* append_buffer, const uint32 append_size)
+{
+ if(NULL == append_buffer || 0 == append_size)
+ return true;
+
+ if(NULL == buffer)
+ init();
+
+ if(error_status) // do nothing if in error state
+ return false;
+
+ uint32 new_size = buffer_size + append_size;
+ if(new_size > buffer_capacity)
+ {
+ if(!increment_buffer_capacity(new_size))
+ {
+ error_status = true;
+ return false;
+ }
+ }
+
+ memscpy(
+ buffer + buffer_size,
+ buffer_capacity - buffer_size,
+ append_buffer,
+ append_size
+ );
+ buffer_size = new_size;
+
+ return true;
+}
+
+
+
+bool ASBuffer::append(const char* append_buffer)
+{
+ if(NULL == append_buffer)
+ return false;
+ else
+ return append((uint8*)append_buffer, strlen(append_buffer));
+}
+
+
+bool ASBuffer::append(const char append_buffer)
+{
+ char buffer[1];
+ buffer[0] = append_buffer;
+
+ return append((uint8*)buffer, 1);
+}
+
+
+bool ASBuffer::append(const char* append_buffer, const uint32 size)
+{
+ if(NULL == append_buffer)
+ return false;
+ else
+ return append((uint8*)append_buffer, size);
+}
+
+
+
+bool ASBuffer::append(const ASBuffer& append_buffer)
+{
+ if(append_buffer.empty())
+ return false;
+ else
+ return append(append_buffer.content(), append_buffer.size());
+}
+
+
+
+bool ASBuffer::append(const ASString& append_buffer)
+{
+ if(append_buffer.empty())
+ return false;
+ else
+ return append((uint8*)append_buffer.c_str(), append_buffer.size());
+}
+
+
diff --git a/mbtk/libmbtk_lib/common/ds_ASString.cpp b/mbtk/libmbtk_lib/common/ds_ASString.cpp
new file mode 100755
index 0000000..eaa1b82
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/ds_ASString.cpp
@@ -0,0 +1,396 @@
+/*==============================================================================
+
+ ds_ASString.cpp
+
+GENERAL DESCRIPTION
+ A string class with utility functions for parsing AS.
+
+EXTERNALIZED FUNCTIONS
+
+INITIALIZATION AND SEQUENCING REQUIREMENTS
+ None
+
+ Copyright (c) 2014 by Qualcomm Technologies Incorporated. All Rights Reserved.
+==============================================================================*/
+
+/*==============================================================================
+ EDIT HISTORY FOR MODULE
+
+This section contains comments describing changes made to the module.
+Notice that changes are listed in reverse chronological order.
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+05/20/15 ml Use memory from modem heap
+04/21/14 ml Created file/Initial version.
+==============================================================================*/
+#include "ds_ASString.h"
+
+//#include "ds_appsrv_mem.h"
+//#include "data_msg.h"
+#include "mbtk_type.h"
+#include <string.h>
+#include <stdlib.h>
+#include <cctype> // isspace, tolower
+
+// #define DS_ASSTRING_MAX_LEN 4294967295 // uint32 max
+#define DS_ASSTRING_MAX_LEN 400000
+
+static const char AS_ESCAPE_MARK = '&';
+static const char EMPTY_STRING[] = "";
+
+static const char* ESCAPE_CHARS[] = {"<", ">", "&", "'", """};
+static const char UNESCAPE_CHARS[] = {'<', '>', '&', '\'', '"'};
+static const uint32 NUM_ESCAPE_CHARS = 5;
+
+
+static bool has_string_at_start(const char* buf, const char* cmp);
+
+static void memscpy(void* dest, size_t destLen, const void* src, size_t srcLen) {
+ if (srcLen <= destLen)
+ memcpy(dest, src, srcLen);
+}
+
+
+ASString::ASString()
+: str(NULL) { }
+
+
+ASString::ASString(const char* src)
+: str(NULL)
+{
+ if(NULL == src)
+ {
+ str = NULL;
+ return;
+ }
+ copy_string(src, strlen(src));
+}
+
+
+ASString::ASString(const char* src, uint32 len)
+: str(NULL)
+{
+ copy_string(src, len);
+}
+
+
+// copy constructor
+ASString::ASString(ASString& src)
+: str(NULL)
+{
+ copy_string(src.c_str(), src.size());
+}
+
+
+ASString::ASString(const ASString& src)
+: str(NULL)
+{
+ copy_string(src.c_str(), src.size());
+}
+
+
+ASString::~ASString()
+{
+ if(NULL != str)
+ {
+ free(str);
+ }
+}
+
+// Assumes this->str with no memory allocated
+void ASString::copy_string(const char* src, uint32 len)
+{
+ if(NULL == src || 0 == len)
+ {
+ str = NULL;
+ return;
+ }
+ if(len > DS_ASSTRING_MAX_LEN)
+ return;
+
+ str = (char*)malloc(sizeof(char) * (len + 1));
+ if(NULL != str)
+ {
+ memscpy(str, len, src, len);
+ }
+}
+
+
+ASString& ASString::operator=(const ASString& rhs)
+{
+ if(&rhs != this)
+ {
+ if(NULL != str)
+ {
+ free(str);
+ str = NULL;
+ }
+
+ if(NULL == rhs.str)
+ str = NULL;
+ else
+ copy_string(rhs.str, rhs.size());
+ }
+ return *this;
+}
+
+
+ASString& ASString::operator=(const char* rhs)
+{
+ if(NULL != str)
+ {
+ free(str);
+ str = NULL;
+ }
+
+ if(NULL == rhs)
+ str = NULL;
+ else
+ copy_string(rhs, strlen(rhs));
+
+ return *this;
+}
+
+
+
+char ASString::operator[](const int index) const
+{
+ return str[index];
+}
+
+
+char& ASString::operator[](int index)
+{
+ return str[index];
+}
+
+
+const char* ASString::c_str() const
+{
+ if(NULL == str)
+ return EMPTY_STRING;
+ return str;
+}
+
+
+uint32 ASString::size() const
+{
+ return length();
+}
+
+
+uint32 ASString::length() const
+{
+ if(NULL == str)
+ return 0;
+ return (uint32)strlen(str);
+}
+
+
+bool ASString::empty() const
+{
+ return (0 == length());
+}
+
+void ASString::remove_trailing_spaces()
+{
+ uint32 end = length();
+
+ if(0 == end)
+ return;
+
+ while(0 != end)
+ {
+ if(!isspace(str[--end]))
+ {
+ end++;
+ break;
+ }
+ }
+
+ str[end] = '\0';
+}
+
+
+
+
+bool ASString::resolve_xml_escapes()
+{
+ bool replaced = false;
+ uint32 counter = 0;
+ uint32 len = length();
+ char* buf = str;
+ char* new_str = NULL;
+
+ if(0 == len)
+ return true;
+
+ new_str = (char*)malloc(sizeof(char) * (len + 1) );
+ if(NULL == new_str)
+ return true;
+
+ while('\0' != *buf && counter < len)
+ {
+ if(AS_ESCAPE_MARK == *buf)
+ {
+ replaced = false;
+ for(uint32 i=0; i<NUM_ESCAPE_CHARS; i++)
+ {
+ if(has_string_at_start(buf, ESCAPE_CHARS[i]))
+ {
+ new_str[counter++] = UNESCAPE_CHARS[i];
+ buf += strlen(ESCAPE_CHARS[i]);
+ replaced = true;
+ break;
+ }
+ }
+
+ if(!replaced)
+ {
+ free(new_str);
+ return false;
+ }
+ }
+ else
+ {
+ new_str[counter++] = *buf;
+ buf++;
+ }
+ }
+
+ free(str);
+ str = new_str;
+
+ return true;
+}
+
+
+
+void ASString::to_lower()
+{
+ uint32 len = length();
+ for(uint32 i = 0; i < len; ++i)
+ {
+ str[i] = tolower(str[i]);
+ }
+}
+
+
+
+bool ASString::limit_cmp(const char* cstr, const uint32 len) const
+{
+ return (0 == strncmp(str, cstr, len));
+}
+
+
+
+void ASString::append(const char* append_str)
+{
+ if(NULL == append_str)
+ return;
+
+ append(append_str, strlen(append_str));
+}
+
+
+
+void ASString::append(const char* append_str, const uint32 len)
+{
+ uint32 prev_size, new_size;
+
+ if(NULL == append_str)
+ return;
+
+ if(strlen(append_str) < len || 0 == len)
+ return;
+
+ prev_size = length();
+ new_size = prev_size + len + 1;
+
+ if(new_size < prev_size || new_size < len || DS_ASSTRING_MAX_LEN < new_size) // overflow?
+ {
+ printf("append - append size too long");
+ return;
+ }
+
+ char* tmp = (char*)malloc(sizeof(char) * new_size);
+ if(NULL == tmp)
+ {
+ printf("append - Failed to allocate memory for result string");
+ return;
+ }
+
+ if(NULL != str)
+ {
+ // copy the current string to the new string.
+ memscpy(tmp, new_size, str, prev_size);
+ free(str);
+ str = NULL;
+ }
+ // add the new string
+ memscpy(tmp+prev_size, new_size - prev_size, append_str, len);
+
+ str = tmp;
+}
+
+
+void ASString::append(const ASString& append_str)
+{
+ if(append_str.empty())
+ return;
+ append(append_str.c_str(), append_str.length());
+}
+
+
+
+
+
+bool operator== (const ASString& lhs, const ASString& rhs)
+{
+ return (0 == strcasecmp(lhs.c_str(), rhs.c_str()));
+}
+
+bool operator!= (const ASString& lhs, const ASString& rhs)
+{
+ return (0 != strcasecmp(lhs.c_str(), rhs.c_str()));
+}
+
+
+bool operator== (const ASString& lhs, const char* rhs)
+{
+ return (0 == strcasecmp(lhs.c_str(), rhs));
+}
+
+bool operator!= (const ASString& lhs, const char* rhs)
+{
+ return (0 != strcasecmp(lhs.c_str(), rhs));
+}
+
+
+/*
+res < 0 if lhs < rhs
+res == 0 if lhs == rhs
+res > 0 if lhs < rhs
+*/
+bool operator< (const ASString& lhs, const ASString& rhs)
+{
+ return (0 > strcasecmp(lhs.c_str(), rhs.c_str()));
+}
+
+bool operator> (const ASString& lhs, const ASString& rhs)
+{
+ return (0 < strcasecmp(lhs.c_str(), rhs.c_str()));
+}
+
+
+
+
+
+
+
+static bool has_string_at_start(const char* buf, const char* cmp)
+{
+ return (0 == strncasecmp(buf, cmp, strlen(cmp)));
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_adc.c b/mbtk/libmbtk_lib/common/mbtk_adc.c
new file mode 100755
index 0000000..55cce7c
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_adc.c
@@ -0,0 +1,102 @@
+/**
+ * \file mbtk_adc.c
+ * \brief A Documented file.
+ *
+ * Detailed description
+ * \Author: js.wang <js.wang@mobiletek.cn>
+ * \Version: 1.0.0
+ * \Date: 2022-04-22
+ */
+#include <fcntl.h>
+#include <stdint.h>
+#include <limits.h>
+#include <termios.h>
+#include <stdarg.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/types.h>
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+#include "mbtk_adc.h"
+
+int mbtk_adc_close(const char* adc_dev)
+{
+ int ret = 0;
+ int fd = 0;
+ char adc = '3';
+ //system("echo 3 > /sys/kernel/debug/adc");
+ if(adc_dev != NULL && !access(adc_dev, R_OK))
+ {
+ //LOGI("DEV:%s", ADC_DEVICE_803);
+ fd = open(adc_dev, O_RDWR|O_CREAT|O_TRUNC, 0644);
+ }
+ else
+ {
+ LOGE("No found ADC devices.");
+ return -1;
+ }
+
+ if(fd < 0) {
+ LOGE("[%s] file open error\n", __FUNCTION__);
+ return -2;
+ }
+ ret = write(fd, &adc, 1);
+ if (ret < 0) {
+ LOGE("%s: error writing to file!\n", __FUNCTION__);
+ close(fd);
+ return -2;
+ }
+ close(fd);
+ return 0;
+}
+
+int mbtk_adc_get(const char* adc_dev, mbtk_adc_enum channle)
+{
+ int ret = 0;
+ int fd = 0;
+ char adc_buf[24] = {0};
+ char *adc_value = NULL;
+ char adc =(channle == MBTK_ADC0 ? '0' : (channle == MBTK_ADC1 ? '1' : '2'));
+
+
+ if(adc_dev != NULL && !access(adc_dev, R_OK))
+ {
+ LOGI("[adc] DEV:%s", adc_dev);
+ fd = open(adc_dev, O_RDWR|O_CREAT|O_TRUNC, 0644);
+ }
+ else
+ {
+ LOGE("No found ADC devices : %s", adc_dev ? adc_dev : "NULL");
+ return -1;
+ }
+
+ if(fd < 0) {
+ LOGE("[%s] file open error\n", __FUNCTION__);
+ return -2;
+ }
+ ret = write(fd, &adc, 1);
+ if (ret < 0) {
+ LOGE("%s: error writing to file!\n", __FUNCTION__);
+ close(fd);
+ return -2;
+ }
+ ret = read(fd, adc_buf, 24);
+ if (ret < 0) {
+ LOGE("%s: error writing to file!\n", __FUNCTION__);
+ close(fd);
+ return -2;
+ }else{
+ //LOGI("%s %d adc:%s\n", __FUNCTION__, __LINE__, adc_buf);
+ adc_value = strstr(adc_buf, "channel");
+ }
+ close(fd);
+ if(adc_value)
+ {
+ //LOGI("%s adc: %s\n", __FUNCTION__, adc_value);
+ }
+ else
+ return -2;
+
+ return atoi(&adc_value[9]);
+}
diff --git a/mbtk/libmbtk_lib/common/mbtk_alarm.c b/mbtk/libmbtk_lib/common/mbtk_alarm.c
new file mode 100755
index 0000000..d62a7e7
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_alarm.c
@@ -0,0 +1,41 @@
+#include "mbtk_alarm.h"
+
+/*===========================================================================
+FUNCTION mbtk_wakealarm_set()
+
+DESCRIPTION:
+ Set sleep wake alarm.
+
+PARAMETERS:
+ time_sec [IN]: Sleep wake-up time in second.
+
+RETURN VALUE:
+ int : Return 0 if success, other for failures.
+
+===========================================================================*/
+int mbtk_wakealarm_set(unsigned long time_sec);
+{
+
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION mbtk_poweralarm_set()
+
+DESCRIPTION:
+ Set shutdown alarm clock.
+
+PARAMETERS:
+ time_sec [IN]: Shutdown wake-up time in second.
+
+RETURN VALUE:
+ int : Return 0 if success, other for failures.
+
+===========================================================================*/
+int mbtk_poweralarm_set(unsigned long time_sec)
+{
+
+ return 0;
+}
+
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_at.c b/mbtk/libmbtk_lib/common/mbtk_at.c
new file mode 100755
index 0000000..8721a52
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_at.c
@@ -0,0 +1,207 @@
+#include <termios.h>
+#include <pthread.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "mbtk_log.h"
+
+#define MBTK_AT_SOCK "/tmp/atcmd_at"
+#define TEMP_FAILURE_RETRY(exp) ({ \
+ typeof (exp) _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1 && errno == EINTR); \
+ _rc; })
+
+static char *at_rsp_complete_tag[] = {
+ "OK",
+ "ERROR",
+ "CONNECT",
+ "+CMS ERROR:",
+ "+CME ERROR:",
+ "NO ANSWER",
+ "NO DIALTONE",
+ NULL};
+static int at_fd = -1;
+
+static int openSocket(const char* sockname)
+{
+ int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ LOGE("Error create socket: %s\n", strerror(errno));
+ return -1;
+ }
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, sockname, sizeof(addr.sun_path));
+ while (TEMP_FAILURE_RETRY(connect(sock,(const struct sockaddr*)&addr, sizeof(addr))) != 0) {
+ LOGE("Error connect to socket %s: %s, try again", sockname, strerror(errno));
+ sleep(1);
+ }
+
+#if 0
+ int sk_flags = fcntl(sock, F_GETFL, 0);
+ fcntl(sock, F_SETFL, sk_flags | O_NONBLOCK);
+#endif
+
+ return sock;
+}
+
+
+static int at_complete(char *rsp)
+{
+#if 0
+ char *ptr = at_rsp_complete_tag;
+ while(ptr) {
+ LOGD("ptr = %s", ptr);
+ if(strstr(rsp, ptr)) {
+ LOGD("%s , %s", rsp, ptr);
+ return 1;
+ }
+ ptr++;
+ }
+#else
+ int i = 0;
+ while(at_rsp_complete_tag[i]) {
+ LOGD("ptr = %s", at_rsp_complete_tag[i]);
+ if(strstr(rsp, at_rsp_complete_tag[i])) {
+ LOGD("%s , %s", rsp, at_rsp_complete_tag[i]);
+ return 1;
+ }
+ i++;
+ }
+
+#endif
+ return 0;
+}
+
+static int at_rsp_read(char* rsp, int rsp_len)
+{
+ int len = 0;
+ int index = 0;
+ memset(rsp, 0x0, rsp_len);
+ while(1) {
+ if((len = read(at_fd, rsp + index, rsp_len - index)) > 0) {
+ if(at_complete(rsp)) {
+ LOGD("AT<%s", rsp);
+ return 0;
+ } else {
+ index += len;
+
+ if(index >= rsp_len) {
+ LOGE("Buffer too small.");
+ return -1;
+ }
+ }
+ } else {
+ printf("Read error:%d\n",errno);
+ return -1;
+ }
+ }
+}
+
+
+/*===========================================================================
+FUNCTION mbtk_at_init
+
+DESCRIPTION:
+ Initial MBTK AT.
+
+PARAMETERS:
+ None.
+
+RETURN VALUE:
+ int : Return 0 if success,other for failure.
+
+===========================================================================*/
+int mbtk_at_init()
+{
+ if(at_fd > 0) {
+ LOGW("MBTK AT has inited.");
+ return 0;
+ }
+
+ at_fd = openSocket(MBTK_AT_SOCK);
+ return at_fd > 0 ? 0 : -1;
+}
+
+
+/*===========================================================================
+FUNCTION mbtk_at_deinit
+
+DESCRIPTION:
+ Deinitial MBTK AT.
+
+PARAMETERS:
+ None.
+
+RETURN VALUE:
+ int : Return 0 if success,other for failure.
+
+===========================================================================*/
+int mbtk_at_deinit()
+{
+ if(at_fd < 0) {
+ LOGW("MBTK AT not inited.");
+ return 0;
+ }
+
+ close(at_fd);
+ at_fd = -1;
+ return 0;
+}
+
+/*===========================================================================
+FUNCTION mbtk_at_send
+
+DESCRIPTION:
+ Send AT command.
+
+PARAMETERS:
+ cmd [IN]: AT command.
+ rsp [OUT]: AT command response.
+ rsp_len[IN] : AT command response buffer size.
+
+RETURN VALUE:
+ int : Return 0 if success,other for failure.
+
+===========================================================================*/
+int mbtk_at_send(char* cmd, char* rsp, int rsp_len)
+{
+ if(cmd == NULL || strlen(cmd) == 0 || rsp == NULL || rsp_len <= 0) {
+ return -1;
+ }
+ char at_cmd[2048] = {0};
+ memcpy(at_cmd, cmd, strlen(cmd));
+ char *ptr = at_cmd + strlen(at_cmd) - 1;
+ while(ptr >= at_cmd && (*ptr == '\r' || *ptr == '\n'))
+ {
+ *ptr-- = '\0';
+ }
+ if(!strncasecmp(at_cmd, "at", 2))
+ {
+ LOGD("AT>%s", at_cmd);
+ *(++ptr) = '\r';
+ *(++ptr) = '\n';
+ if(write(at_fd, at_cmd, strlen(at_cmd)) != strlen(at_cmd)) {
+ LOGE("Write error:%d",errno);
+ return -1;
+ }
+
+ return at_rsp_read(rsp, rsp_len);
+ } else {
+ LOGE("AT command error:%s",at_cmd);
+ return -1;
+ }
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_bs_position.c b/mbtk/libmbtk_lib/common/mbtk_bs_position.c
new file mode 100755
index 0000000..0119ae5
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_bs_position.c
@@ -0,0 +1,317 @@
+/**
+ * \file mbtk_bs_position.c
+ * \brief A Documented file.
+ *
+ * Detailed description
+ * \Author: Sniper <js.wang@mobiletek.cn>
+ * \Version: 1.0.0
+ * \Date: 2022-03-17
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include "mbtk_type.h"
+#include <telephony/ril.h>
+#include <telephony/ril_ext.h>
+#include "rilutil.h"
+#include "mbtk_log.h"
+
+#define RIL_UBUS_REQ "ril_request"
+#define RIL_UBUS_ID "ril"
+#define IMSI_SIZE 15
+
+// #define DEBUG 1
+
+#ifdef DEBUG
+ #define bs_log(...) printf(__VA_ARGS__)
+#else
+ #define bs_log(...)
+#endif
+
+struct bs_ril_cellinfo {
+ int type;
+ int mcc;
+ int mnc;
+ int lac;
+ int cid;
+ int reg_state;
+};
+
+struct mbtk_bs_ubus_t
+{
+ struct ubus_context *ctx;
+
+ /* RIL */
+ struct ubus_subscriber ril_ind_event;
+ uint32_t ril_subscriber_id;
+ uint32_t ril_request_id;
+ pthread_t call_status_pthread;
+ struct bs_ril_cellinfo cellinfo;
+};
+struct mbtk_bs_ubus_t *mbtk_bs_ubus = NULL;
+static struct blob_buf b;
+
+static inline int radio_tech_2_act(int radio_tech)
+{
+ switch(radio_tech)
+ {
+ case RADIO_TECH_GPRS: return 0; /* ACT could have been either 1 or 0 !! */
+ case RADIO_TECH_UMTS: return 2;
+ case RADIO_TECH_EDGE: return 3;
+ case RADIO_TECH_HSDPA: return 4;
+ case RADIO_TECH_HSUPA: return 5;
+ case RADIO_TECH_HSPA: return 6;
+ case RADIO_TECH_LTE: return 7;
+ case RADIO_TECH_LTEP: return 7; /* temporary set it to 7, in future we may need to set to a number for 4G+ */
+ case RADIO_TECH_HSPAP: return 8;
+ case RADIO_TECH_UNKNOWN:
+ default: break;
+ }
+
+ return 0;
+}
+static void cellid_cb(void *response)
+{
+ rilutilstrings *resp = NULL;
+
+ resp = (rilutilstrings *) response;
+ bs_log("response num : %d\n", resp->num);
+
+ sscanf(resp->str[0], "%d", &mbtk_bs_ubus->cellinfo.reg_state);
+ sscanf(resp->str[1], "%x", &mbtk_bs_ubus->cellinfo.lac);
+ sscanf(resp->str[2], "%x", &mbtk_bs_ubus->cellinfo.cid);
+ sscanf(resp->str[3], "%d", &mbtk_bs_ubus->cellinfo.type); /* converted ACT value */
+ bs_log("cellinfo (%p): reg_state before=%d",
+ &mbtk_bs_ubus->cellinfo,
+ mbtk_bs_ubus->cellinfo.reg_state);
+ bs_log("lac:%x, cid:%x\n",
+ mbtk_bs_ubus->cellinfo.lac,
+ mbtk_bs_ubus->cellinfo.cid);
+ bs_log("reg_state:%d, lac:%d, cid:%d, type:%d\n",
+ mbtk_bs_ubus->cellinfo.reg_state, mbtk_bs_ubus->cellinfo.lac,
+ mbtk_bs_ubus->cellinfo.cid, mbtk_bs_ubus->cellinfo.type);
+ mbtk_bs_ubus->cellinfo.type = radio_tech_2_act(mbtk_bs_ubus->cellinfo.type);
+ // bs_log("mcc:%d, mnc:%d, type:%d\n",
+ // mbtk_bs_ubus->cellinfo.mcc, mbtk_bs_ubus->cellinfo.mnc, mbtk_bs_ubus->cellinfo.type);
+ bs_log("cellinfo (%p): reg_state=%d, lac=%d, cid=%d, type=%d, mcc=%d, mnc=%d\n",
+ &mbtk_bs_ubus->cellinfo,
+ mbtk_bs_ubus->cellinfo.reg_state, mbtk_bs_ubus->cellinfo.lac, mbtk_bs_ubus->cellinfo.cid,
+ mbtk_bs_ubus->cellinfo.type, mbtk_bs_ubus->cellinfo.mcc, mbtk_bs_ubus->cellinfo.mnc);
+}
+
+
+static void setid_cb(char *resp)
+{
+ char mcc[4] = { 0 }, mnc[4] = { 0};
+ char *imsi = NULL;
+
+ imsi = malloc(IMSI_SIZE + 1);
+ if (!imsi) {
+ printf("Memory allocation failed\n");
+ return;
+ }
+ memset(imsi, 0, IMSI_SIZE + 1);
+ /* update imsi and cellinfo mcc & mnc */
+ strncpy(imsi, resp, IMSI_SIZE);
+ bs_log("imsi: %s\n", imsi);
+ memcpy(mcc, imsi, 3);
+ memcpy(mnc, (char *)imsi + 3, 2);
+ mbtk_bs_ubus->cellinfo.mcc = atoi(mcc);
+ mbtk_bs_ubus->cellinfo.mnc = atoi(mnc);
+
+ bs_log("reg_stat, mcc:%d, mnc:%d, \n",
+ mbtk_bs_ubus->cellinfo.mcc, mbtk_bs_ubus->cellinfo.mnc);
+ free(imsi);
+}
+
+static void bs_complete_cb(struct ubus_request *req, int ret)
+{
+ bs_log("ubus_request = %08X\n", req);
+ free(req);
+}
+
+static void bs_requset_cb(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+ unsigned int requestid = 0;
+ unsigned int rilerrno;
+ void *response = NULL;
+ int responselen = 0;
+ int ret = 0;
+
+ ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &response, &responselen);
+ if(ret)
+ {
+ fprintf(stderr, "parse blob error\n");
+ goto done;
+ }
+
+ if(rilerrno)
+ {
+ fprintf(stderr, "unsolicited id %d, error code %d\n", requestid, rilerrno);
+ goto done;
+ }
+ bs_log("requestid : %d\n", requestid);
+ if(requestid == RIL_REQUEST_GET_IMSI)
+ {
+ setid_cb((char *)response);
+ }
+ else if(requestid == RIL_REQUEST_DATA_REGISTRATION_STATE)
+ {
+ cellid_cb(response);
+ }
+done:
+ if(response)
+ rilutil_freeResponseData(requestid, response, responselen);
+
+ return;
+}
+
+
+int bs_get_cell_info(struct mbtk_bs_ubus_t *bs)
+{
+ int ret_val;
+ struct ubus_request *req = NULL;
+
+ if(!bs) {
+ printf("ril module not running\n");
+ return 0;
+ }
+ blob_buf_init(&b, 0);
+
+ rilutil_makeRequestBlob(&b, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL, 0);
+
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+
+ if ((ret_val =
+ ubus_invoke_async(bs->ctx, bs->ril_request_id, RIL_UBUS_REQ, b.head, req)) != UBUS_STATUS_OK) {
+ printf("mubus_invoke_async failed\n");
+ free(req);
+ return -1;
+ } else {
+ req->data_cb = bs_requset_cb;
+ req->complete_cb = bs_complete_cb;
+ ubus_complete_request_async(bs->ctx, req);
+ }
+ return 0;
+}
+
+int bs_get_setid_info(struct mbtk_bs_ubus_t *bs)
+{
+ int ret_val;
+ struct ubus_request *req = NULL;
+
+ if(!bs) {
+ printf("ril module not running\n");
+ return 0;
+ }
+ blob_buf_init(&b, 0);
+
+ rilutil_makeRequestBlob(&b, RIL_REQUEST_GET_IMSI, NULL, 0);
+
+ req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
+
+ if ((ret_val =
+ ubus_invoke_async(bs->ctx, bs->ril_request_id, RIL_UBUS_REQ, b.head, req)) != UBUS_STATUS_OK) {
+ printf("mubus_invoke_async failed\n");
+ free(req);
+ return -1;
+ } else {
+ req->data_cb = bs_requset_cb;
+ req->complete_cb = bs_complete_cb;
+ ubus_complete_request_async(bs->ctx, req);
+ }
+ return 0;
+}
+
+static void bs_register_ril(void* hdl)
+{
+ pthread_detach(pthread_self());
+ uloop_run();
+ bs_log("%s uloop_run!\n", __FUNCTION__);
+ pthread_exit(NULL);
+}
+
+struct mbtk_bs_ubus_t *bs_ril_init(struct mbtk_bs_ubus_t *bs)
+{
+ int ret;
+
+ mbtk_bs_ubus = malloc(sizeof(struct mbtk_bs_ubus_t));
+ if (!mbtk_bs_ubus) {
+ printf("memory allocation failed\n");
+ return NULL;
+ }
+
+ memset(mbtk_bs_ubus, 0, sizeof(*mbtk_bs_ubus));
+ uloop_init();
+ mbtk_bs_ubus->ctx = ubus_connect(NULL);
+ if(!mbtk_bs_ubus->ctx)
+ {
+ LOGE("Failed to connect to ubus");
+ goto out_error;
+ }
+
+ ubus_add_uloop(mbtk_bs_ubus->ctx);
+ if (ubus_lookup_id(mbtk_bs_ubus->ctx, RIL_UBUS_ID, &mbtk_bs_ubus->ril_request_id)) {
+ fprintf(stderr, "%s, Failed to look up test object\n", __FUNCTION__);
+ goto out_error;
+ }
+
+ pthread_create(&mbtk_bs_ubus->call_status_pthread, NULL, (void *)bs_register_ril, NULL);
+
+ return mbtk_bs_ubus;
+
+out_error:
+ free(mbtk_bs_ubus);
+ return NULL;
+}
+
+int bs_ril_exit(struct mbtk_bs_ubus_t *bs)
+{
+ int ret;
+
+ if(!bs) {
+ printf("ril module not running\n");
+ return 0;
+ }
+
+ ret = pthread_cancel(bs->call_status_pthread);
+ pthread_join(bs->call_status_pthread, NULL);
+ do{
+ ret = pthread_kill(bs->call_status_pthread, 0);
+ bs_log("kill pthread: %d \n", ret);
+ if(ret == ESRCH)
+ bs_log("The specified thread does not exist or has terminated\n");
+ else if(ret == EINVAL)
+ printf("Useless signal\n");
+ else
+ printf("The thread exists\n");
+ usleep(100000);
+ }while(0 == ret);
+
+ free(bs);
+ return 0;
+}
+int mbtk_bs_position(void)
+{
+ struct mbtk_bs_ubus_t *bs_hdl;
+ bs_hdl = bs_ril_init(NULL);
+ bs_get_setid_info(bs_hdl);
+ bs_get_cell_info(bs_hdl);
+
+ sleep(1);
+ bs_ril_exit(bs_hdl);
+
+ return 0;
+}
diff --git a/mbtk/libmbtk_lib/common/mbtk_debug.c b/mbtk/libmbtk_lib/common/mbtk_debug.c
new file mode 100755
index 0000000..e9280c9
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_debug.c
@@ -0,0 +1,382 @@
+/*
+* mbtk_debug.c
+*
+* Generate application exception information.
+*
+*/
+/******************************************************************************
+
+ EDIT HISTORY FOR FILE
+
+ WHEN WHO WHAT,WHERE,WHY
+-------- -------- -------------------------------------------------------
+2024/6/5 LiuBin Initial version
+
+******************************************************************************/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <ucontext.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdarg.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+
+/* 纯C环境下,不定义宏NO_CPP_DEMANGLE */
+#if (!defined(__cplusplus)) && (!defined(NO_CPP_DEMANGLE))
+#define NO_CPP_DEMANGLE
+#endif
+
+#ifndef NO_CPP_DEMANGLE
+#include <cxxabi.h>
+#ifdef __cplusplus
+using __cxxabiv1::__cxa_demangle;
+#endif
+#endif
+
+#if (defined __x86_64__)
+#define REGFORMAT "%016lx"
+#elif (defined __i386__)
+#define REGFORMAT "%08x"
+#elif (defined __arm__)
+#define REGFORMAT "%lx"
+#endif
+
+#define MBTK_PROC_DUMP_DIR "persist.mbtk.dump_dir"
+#define MBTK_PROC_DUMP_FILE_DEF "/etc/mbtk/mbtk_dump.log"
+
+
+static char proc_name[100];
+static char proc_dump_name[100];
+static int proc_dump_fd = -1;
+
+#ifdef HAS_ULSLIB
+#include <uls/logger.h>
+#define sigsegv_outp(x) sigsegv_outp(, gx)
+#else
+//#define sigsegv_outp(x, ...) fprintf(stderr, x"\n", ##__VA_ARGS__)
+void sigsegv_outp(const char* format, ...)
+{
+ if(proc_dump_fd > 0) {
+ char buf[1024] = {0};
+ va_list ap;
+ int length = 0;
+
+ va_start(ap, format);
+ length = vsnprintf(buf, sizeof(buf), format, ap);
+ if (length < 0 || 0 == length) {
+ return;
+ }
+
+ char *tmp = buf + length - 1;
+ while(tmp >= buf && (*tmp == '\r' || *tmp == '\n')) {
+ *tmp-- = '\0';
+ }
+ tmp++;
+ *tmp = '\n';
+
+ write(proc_dump_fd, buf, strlen(buf));
+
+ va_end(ap);
+ }
+}
+#endif
+
+static void print_reg(ucontext_t *uc)
+{
+#if (defined __x86_64__) || (defined __i386__)
+ int i;
+ for (i = 0; i < NGREG; i++)
+ {
+ sigsegv_outp("reg[%02d]: 0x"REGFORMAT, i, uc->uc_mcontext.gregs[i]);
+ }
+#elif (defined __arm__)
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 0, uc->uc_mcontext.arm_r0);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 1, uc->uc_mcontext.arm_r1);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 2, uc->uc_mcontext.arm_r2);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 3, uc->uc_mcontext.arm_r3);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 4, uc->uc_mcontext.arm_r4);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 5, uc->uc_mcontext.arm_r5);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 6, uc->uc_mcontext.arm_r6);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 7, uc->uc_mcontext.arm_r7);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 8, uc->uc_mcontext.arm_r8);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 9, uc->uc_mcontext.arm_r9);
+ sigsegv_outp("reg[%02d] = 0x"REGFORMAT, 10, uc->uc_mcontext.arm_r10);
+ sigsegv_outp("FP = 0x"REGFORMAT, uc->uc_mcontext.arm_fp);
+ sigsegv_outp("IP = 0x"REGFORMAT, uc->uc_mcontext.arm_ip);
+ sigsegv_outp("SP = 0x"REGFORMAT, uc->uc_mcontext.arm_sp);
+ sigsegv_outp("LR = 0x"REGFORMAT, uc->uc_mcontext.arm_lr);
+ sigsegv_outp("PC = 0x"REGFORMAT, uc->uc_mcontext.arm_pc);
+ sigsegv_outp("CPSR = 0x"REGFORMAT, uc->uc_mcontext.arm_cpsr);
+ sigsegv_outp("Fault Address = 0x"REGFORMAT, uc->uc_mcontext.fault_address);
+ sigsegv_outp("Trap no = 0x"REGFORMAT, uc->uc_mcontext.trap_no);
+ sigsegv_outp("Err Code = 0x"REGFORMAT, uc->uc_mcontext.error_code);
+ sigsegv_outp("Old Mask = 0x"REGFORMAT, uc->uc_mcontext.oldmask);
+#endif
+}
+
+static void print_call_link(ucontext_t *uc)
+{
+ int i = 0;
+ void **frame_pointer = (void **)NULL;
+ void *return_address = NULL;
+ Dl_info dl_info = { 0 };
+
+#if (defined __i386__)
+ frame_pointer = (void **)uc->uc_mcontext.gregs[REG_EBP];
+ return_address = (void *)uc->uc_mcontext.gregs[REG_EIP];
+#elif (defined __x86_64__)
+ frame_pointer = (void **)uc->uc_mcontext.gregs[REG_RBP];
+ return_address = (void *)uc->uc_mcontext.gregs[REG_RIP];
+#elif (defined __arm__)
+ /* sigcontext_t on ARM:
+ unsigned long trap_no;
+ unsigned long error_code;
+ unsigned long oldmask;
+ unsigned long arm_r0;
+ ...
+ unsigned long arm_r10;
+ unsigned long arm_fp;
+ unsigned long arm_ip;
+ unsigned long arm_sp;
+ unsigned long arm_lr;
+ unsigned long arm_pc;
+ unsigned long arm_cpsr;
+ unsigned long fault_address;
+ */
+ frame_pointer = (void **)uc->uc_mcontext.arm_fp;
+ return_address = (void *)uc->uc_mcontext.arm_pc;
+#endif
+
+ sigsegv_outp("\nStack trace:");
+ while (frame_pointer && return_address)
+ {
+ if (!dladdr(return_address, &dl_info)) break;
+ const char *sname = dl_info.dli_sname;
+#ifndef NO_CPP_DEMANGLE
+ int status;
+ char *tmp = __cxa_demangle(sname, NULL, 0, &status);
+ if (status == 0 && tmp)
+ {
+ sname = tmp;
+ }
+#endif
+ /* No: return address <sym-name + offset> (filename) */
+ sigsegv_outp("%02d: %p <%s + %lu> (%s)", ++i, return_address, sname,
+ (unsigned long)return_address - (unsigned long)dl_info.dli_saddr,
+ dl_info.dli_fname);
+#ifndef NO_CPP_DEMANGLE
+ if (tmp) free(tmp);
+#endif
+ if (dl_info.dli_sname && !strcmp(dl_info.dli_sname, "main"))
+ {
+ break;
+ }
+
+#if (defined __x86_64__) || (defined __i386__)
+ return_address = frame_pointer[1];
+ frame_pointer = frame_pointer[0];
+#elif (defined __arm__)
+ return_address = frame_pointer[-1];
+ frame_pointer = (void **)frame_pointer[-3];
+#endif
+ }
+ sigsegv_outp("Stack trace end.");
+}
+
+static void proc_maps_print() {
+ char file[64] = {0x00};
+ sprintf(file,"/proc/%d/maps", getpid());
+ FILE *fptr = fopen(file, "r");
+ char line[1024];
+ if(fptr)
+ {
+ memset(line, 0, sizeof(line));
+ while(fgets(line, sizeof(line), fptr)) {
+ // printf("Line : %s", line);
+ if(strstr(line, "libmbtk_") || strstr(line, "liblynq_") || strstr(line, "libql_")) {
+ sigsegv_outp("%s", line);
+ }
+ memset(line, 0, sizeof(line));
+ }
+
+ fclose(fptr);
+ }
+}
+
+static void sigsegv_handler(int signo, siginfo_t *info, void *context)
+{
+ printf("sigsegv_handler - %d\n", signo);
+ if (context)
+ {
+ struct timeval log_time;
+ char tmp[50] = {0};
+ gettimeofday(&log_time, NULL);
+ struct tm* tm_t = localtime(&(log_time.tv_sec));
+ strftime(tmp, 50, "%F %T", tm_t);
+ snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), ".%d", (int)(log_time.tv_usec / 1000));
+ sigsegv_outp("----------------------------%s----------------------------", tmp);
+
+ proc_maps_print();
+
+ ucontext_t *uc = (ucontext_t *)context;
+ char proc[100] = {0};
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+ if(fd > 0)
+ {
+ if(read(fd, proc, sizeof(proc)) > 0) {
+ sigsegv_outp("Segmentation Fault:%s", proc);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+ close(fd);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+
+ sigsegv_outp("info.si_signo = %d", signo);
+ sigsegv_outp("info.si_errno = %d", info->si_errno);
+ sigsegv_outp("info.si_code = %d (%s)", info->si_code,
+ (info->si_code == SEGV_MAPERR) ? "SEGV_MAPERR" : "SEGV_ACCERR");
+ sigsegv_outp("info.si_addr = 0x%x(%p)\n", info->si_addr, info->si_addr);
+
+ print_reg(uc);
+ print_call_link(uc);
+
+ signal(signo, SIG_DFL);
+ raise(signo);
+
+ printf("Segmentation Fault, refer to the log file:%s\n", proc_dump_name);
+ }
+
+ exit(0);
+}
+
+#if 1
+#define BACKTRACE_SIZE 32
+void sigsegv_handler_with_thread(int signo) {
+ struct timeval log_time;
+ char tmp[50] = {0};
+ gettimeofday(&log_time, NULL);
+ struct tm* tm_t = localtime(&(log_time.tv_sec));
+ strftime(tmp, 50, "%F %T", tm_t);
+ snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), ".%d", (int)(log_time.tv_usec / 1000));
+ sigsegv_outp("----------------------------%s----------------------------", tmp);
+
+ proc_maps_print();
+
+ char proc[100] = {0};
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+ if(fd > 0)
+ {
+ if(read(fd, proc, sizeof(proc)) > 0) {
+ sigsegv_outp("Segmentation Fault:%s", proc);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+ close(fd);
+ } else {
+ sigsegv_outp("Segmentation Fault:%s", "Unknown");
+ }
+
+ sigsegv_outp("info.si_signo = %d", signo);
+
+ int j, nptrs;
+ void *buffer[BACKTRACE_SIZE];
+ char **strings;
+ nptrs = backtrace(buffer, BACKTRACE_SIZE);
+ //printf("backtrace() returned %d addresses\n", nptrs);
+ strings = backtrace_symbols(buffer, nptrs);
+ if(strings == NULL){
+ //perror("backtrace_symbols");
+ exit(EXIT_FAILURE);
+ }
+
+ sigsegv_outp("\nStack trace:");
+ if(nptrs > 0) {
+ for (j = 0; j < nptrs; j++) {
+ sigsegv_outp("%02d: %s", j, strings[j]);
+ }
+ }
+ free(strings);
+ sigsegv_outp("Stack trace end.");
+
+ signal(signo, SIG_DFL);
+ raise(signo);
+
+ printf("Segmentation Fault, refer to the log file:%s\n", proc_dump_name);
+ exit(0);
+}
+#endif
+
+#define SETSIG(sa, sig, fun, flags) \
+ do { \
+ sa.sa_sigaction = fun; \
+ sa.sa_flags = flags; \
+ sigemptyset(&sa.sa_mask); \
+ sigaction(sig, &sa, NULL); \
+ } while(0)
+
+
+// arm-openwrt-linux-addr2line -e out/bin/mbtk_gnssd 0x12ca8
+void mbtk_debug_open(const char *log_file, bool thread_support)
+{
+ struct sigaction sa;
+
+#if 1
+ if(thread_support) {
+ SETSIG(sa, SIGSEGV, sigsegv_handler_with_thread, 0);
+ SETSIG(sa, SIGABRT, sigsegv_handler_with_thread, 0);
+ } else {
+ SETSIG(sa, SIGSEGV, sigsegv_handler, SA_SIGINFO);
+ SETSIG(sa, SIGABRT, sigsegv_handler, SA_SIGINFO);
+ }
+#else
+ SETSIG(sa, SIGSEGV, sigsegv_handler, SA_SIGINFO);
+#endif
+
+ memset(proc_name, 0, sizeof(proc_name));
+ memset(proc_dump_name, 0, sizeof(proc_dump_name));
+ int fd = open("/proc/self/cmdline", O_RDONLY);
+ if(fd > 0)
+ {
+ if(read(fd, proc_name, sizeof(proc_name)) <= 0) {
+ LOGE("Get PROC name fail.");
+ }
+ close(fd);
+ }
+
+ // Redirect stderr to log_file.
+ if(log_file) {
+ memcpy(proc_dump_name, log_file, strlen(log_file));
+ } else {
+ property_get(MBTK_PROC_DUMP_DIR, proc_dump_name, "");
+ if(strlen(proc_dump_name) > 0) {
+ snprintf(proc_dump_name + strlen(proc_dump_name),sizeof(proc_dump_name) - strlen(proc_dump_name), "/%s", proc_name);
+ } else {
+ memcpy(proc_dump_name, MBTK_PROC_DUMP_FILE_DEF, strlen(MBTK_PROC_DUMP_FILE_DEF));
+ }
+ }
+
+#if 0
+ if(freopen(proc_dump_name, "a", stderr) == NULL) {
+ LOGE("reopen stderr to %s fail.[%d]", proc_dump_name, errno);
+ }
+#else
+ proc_dump_fd = open(proc_dump_name, O_WRONLY | O_CREAT | O_APPEND, 0666);
+ if(proc_dump_fd < 0) {
+ LOGE("Open(%s) fail:%d.", proc_dump_name, errno);
+ }
+#endif
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_device_info.c b/mbtk/libmbtk_lib/common/mbtk_device_info.c
new file mode 100755
index 0000000..31d9523
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_device_info.c
@@ -0,0 +1,262 @@
+/*
+* mbtk_device_info.c
+*
+* MBTK device partition information utils.
+*
+*/
+/******************************************************************************
+
+ EDIT HISTORY FOR FILE
+
+ WHEN WHO WHAT,WHERE,WHY
+-------- -------- -------------------------------------------------------
+2024/2/27 LiuBin Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <mtd/mtd-user.h>
+
+#include "mbtk_type.h"
+#include "mbtk_device.h"
+#include "mbtk_log.h"
+#include "mbtk_str.h"
+#include "mbtk_mtd.h"
+
+/*
+* MBTK_DEVICE_INFO_ITEM_BASIC - mbtk_device_info_basic_t
+* MBTK_DEVICE_INFO_ITEM_FOTA - mbtk_device_info_fota_t
+* MBTK_DEVICE_INFO_ITEM_MODEM - mbtk_device_info_modem_t
+* MBTK_DEVICE_INFO_ITEM_LOG - mbtk_device_info_log_t
+*/
+int mbtk_dev_info_read(mbtk_device_info_item_enum item_type, void *item_ptr, int item_size)
+{
+ int fd, len, i;
+ mbtk_device_info_header_t info_header;
+ memset(&info_header, 0, sizeof(mbtk_device_info_header_t));
+
+ switch(item_type) {
+ case MBTK_DEVICE_INFO_ITEM_BASIC:
+ {
+ if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_basic_t)) {
+ LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+ return -1;
+ }
+ break;
+ }
+ case MBTK_DEVICE_INFO_ITEM_FOTA:
+ {
+ if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_fota_t)) {
+ LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+ return -1;
+ }
+ break;
+ }
+ case MBTK_DEVICE_INFO_ITEM_MODEM:
+ {
+ if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_modem_t)) {
+ LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+ return -1;
+ }
+ break;
+ }
+ case MBTK_DEVICE_INFO_ITEM_LOG:
+ {
+ if(item_ptr == NULL || item_size != sizeof(mbtk_device_info_log_t)) {
+ LOGE("ARG error:item-%d, item_size-%d", item_type, item_size);
+ return -1;
+ }
+ break;
+ }
+ default:
+ {
+ LOGE("Item type[%d] error.", item_type);
+ return -1;
+ }
+ }
+
+ mbtk_partition_info_t *partition_info = mbtk_partition_get();
+ if(partition_info == NULL) {
+ LOGE("mbtk_partition_get() fail.");
+ return -1;
+ }
+
+ i = 0;
+ char dev[32] = {0};
+ while(i < MBTK_PARTITION_NUM_MAX) {
+ if(partition_info[i].used && strcmp(partition_info[i].name, MBTK_DEVICE_INFO_PARTITION_NAME) == 0) {
+ snprintf(dev, 32, "/dev/%s", partition_info[i].dev);
+ LOGD("%s -> %s", partition_info[i].name, dev);
+ break;
+ }
+ i++;
+ }
+ if(strlen(dev) == 0) {
+ LOGE("DEV is null.");
+ return -1;
+ }
+
+ fd = open(dev, O_RDONLY);
+ if (fd < 0) {
+ LOGE("Fatal error: can't open device_info %s\n", dev);
+ return -1;
+ }
+
+ len = read(fd, &info_header, sizeof(mbtk_device_info_header_t));
+ if (len != sizeof(mbtk_device_info_header_t)) {
+ LOGE("Fatal error: read %d bytes(expect %d)\n", len, sizeof(mbtk_device_info_header_t));
+ close(fd);
+ goto fail;
+ }
+
+ if(info_header.tag != MBTK_DEVICE_INFO_PARTITION_TAG) {
+ LOGE("TAG error : %08x", info_header.tag);
+ goto fail;
+ }
+
+ if(info_header.version != MBTK_DEVICE_INFO_CURR_VERSION) {
+ LOGE("Version error : %d", info_header.version);
+ goto fail;
+ }
+
+ LOGD("Item count:%d", info_header.item_count);
+
+ if(info_header.item_header[item_type].addr == 0) {
+ LOGE("No found item : %d", item_type);
+ goto fail;
+ }
+
+ lseek(fd, info_header.item_header[item_type].addr, SEEK_SET);
+ if (read(fd, item_ptr, item_size) != item_size) {
+ LOGE("Read fail:%d", errno);
+ goto fail;
+ }
+
+ close(fd);
+ return 0;
+
+fail:
+ close(fd);
+ return -1;
+}
+
+int mbtk_dev_info_write(mbtk_device_info_item_enum item_type, void *item_ptr, int item_size)
+{
+ if(item_ptr == NULL) {
+ LOGE("ARG error.");
+ return -1;
+ }
+
+ switch(item_type) {
+ case MBTK_DEVICE_INFO_ITEM_BASIC:
+ {
+ if(item_size != sizeof(mbtk_device_info_basic_t)) {
+ LOGE("item_size != sizeof(mbtk_device_info_basic_t)\n\r");
+ return -1;
+ }
+ break;
+ }
+ case MBTK_DEVICE_INFO_ITEM_FOTA:
+ {
+ if(item_size != sizeof(mbtk_device_info_fota_t)) {
+ LOGE("item_size != sizeof(mbtk_device_info_fota_t)\n\r");
+ return -1;
+ }
+ break;
+ }
+ case MBTK_DEVICE_INFO_ITEM_MODEM:
+ {
+ if(item_size != sizeof(mbtk_device_info_modem_t)) {
+ LOGE("item_size != sizeof(mbtk_device_info_modem_t)\n\r");
+ return -1;
+ }
+ break;
+ }
+ case MBTK_DEVICE_INFO_ITEM_LOG:
+ {
+ if(item_size != sizeof(mbtk_device_info_log_t)) {
+ LOGE("item_size != sizeof(mbtk_device_info_log_t)\n\r");
+ return -1;
+ }
+ break;
+ }
+ default:
+ {
+ LOGE("Item type[%d] error.\n\r", item_type);
+ return -1;
+ }
+ }
+
+ mbtk_partition_info_t info;
+ memset(&info, 0x0, sizeof(mbtk_partition_info_t));
+ if(mbtk_partition_get_by_name("device_info", &info)) {
+ LOGE("mbtk_partition_get_by_name() fail.");
+ return -1;
+ }
+
+ LOGD("device_info name : %s, dev : %s, addr : %08x, size : %08x, erase_size : %08x", info.name,
+ info.dev, info.partition_start, info.partition_size, info.erase_size);
+
+ if(info.erase_size <= 0 || info.partition_size <= 0) {
+ LOGE("partition info error.");
+ return -1;
+ }
+
+ int fd = open(info.dev, O_RDWR);
+ if (fd < 0) {
+ LOGE("Fatal error: can't open device_info %s\n", info.dev);
+ return -1;
+ }
+
+ char *mtd_buff = (char*)malloc(info.erase_size);
+ if(mtd_buff == NULL) {
+ LOGE("malloc() failed\n");
+ return -1;
+ }
+ memset(mtd_buff, 0xFF, info.erase_size);
+ int len = read(fd, mtd_buff, info.erase_size);
+ if (len != info.erase_size) {
+ LOGE("Fatal error: read %d[%d] bytes(expect %d)\n", len, errno, info.erase_size);
+ goto fail;
+ }
+
+ struct erase_info_user mtdEraseInfo;
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ {
+ LOGE("seek failed\n");
+ return -1;
+ }
+
+ mtdEraseInfo.length = info.partition_size;
+ mtdEraseInfo.start = 0;
+ ioctl(fd, MEMUNLOCK, &mtdEraseInfo);
+ ioctl(fd, MEMERASE, &mtdEraseInfo);
+
+ mbtk_device_info_header_t *info_header = (mbtk_device_info_header_t*)mtd_buff;
+ memcpy(mtd_buff + info_header->item_header[item_type].addr, item_ptr, item_size);
+
+ lseek(fd, 0, SEEK_SET);
+ if (write(fd, mtd_buff, info.erase_size) != info.erase_size) {
+ LOGE("Write fail:%d", errno);
+ goto fail;
+ }
+
+ if(mtd_buff) {
+ free(mtd_buff);
+ }
+
+ close(fd);
+ return 0;
+
+fail:
+ close(fd);
+ return -1;
+}
+
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_file.c b/mbtk/libmbtk_lib/common/mbtk_file.c
new file mode 100755
index 0000000..44f3954
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_file.c
@@ -0,0 +1,128 @@
+#include "mbtk_file.h"
+
+/**
+* Return TRUE if file exist,FLASE or not.
+*/
+bool file_exist(const char *path)
+{
+ return (access(path, F_OK) == 0) ? true : false;
+}
+
+/*
+ * Return file descriptor if open file success, return -1 or not.
+ *
+ * flag : File open flag.
+ * O_RDONLY 以只读方式打开文件
+ * O_WRONLY 以只写方式打开文件
+ * O_RDWR 以可读写方式打开文件
+ * 上述三种旗标是互斥
+ *
+ * O_CREAT 若欲打开的文件不存在则自动建立该文件。
+ * O_EXCL 如果 O_CREAT 也被设置,此指令会去检查文件是否存在。文件若不存在则
+ * 建立该文件,否则将导致打开文件错误。此外,若 O_CREAT 与 O_EXCL 同时设置,
+ * 并且欲打开的文件为符号连接,则会打开文件失败。
+ * O_NOCTTY 如果欲打开的文件为终端机设备时,则不会将该终端机当成进程控制终端机。
+ * O_TRUNC 若文件存在并且以可写的方式打开时,此旗标会令文件长度清为 0,而原来存于该文件的资料也会消失。
+ * O_APPEND 当读写文件时会从文件尾开始移动,也就是所写入的数据会以附加的方式加入到文件后面。
+ * O_NONBLOCK 以不可阻断的方式打开文件,也就是无论有无数据读取或等待,都会立即返回进程之中。
+ * O_NDELAY 同 O_NONBLOCK。
+ * O_SYNC 以同步的方式打开文件。
+ * O_NOFOLLOW 如果参数 pathname 所指的文件为一符号连接,则会令打开文件失败。
+ * O_DIRECTORY 如果参数 pathname 所指的文件并非为一目录,则会令打开文件失败
+ */
+int file_open(const char *path, int flag)
+{
+ // Only for create file : rwxrw-rx-
+ int result = open(path, flag, 0766);
+ if(result == -1) {
+ LOGE("Open file[%s] fail:%d", path, errno);
+ }
+ return result;
+}
+
+/*
+* Return file size,or -1 if get file size fail.
+*/
+int file_length(int fd)
+{
+ int cur= lseek(fd, 0, SEEK_CUR);
+ if(cur < 0)
+ {
+ LOGE("lseek(SEEK_CUR) error: %d", errno);
+ return -1;
+ }
+ int len = lseek(fd, 0, SEEK_END);
+ if (len < 0)
+ {
+ LOGE("lseek(SEEK_END) error: %d", errno);
+ return -1;
+ }
+
+ // Reset position
+ if(cur != len) {
+ if(lseek(fd, cur, SEEK_SET))
+ {
+ LOGE("lseek(SEEK_SET) error: %d", errno);
+ return -1;
+ }
+ }
+ return len;
+}
+
+// Read data of specified length.
+int file_read(int fd, void *buf, int nbyte)
+{
+ int count = 0;
+ int len = 0;
+ while (true)
+ {
+ len = read(fd, buf + count, nbyte - count);
+ if (len > 0)
+ {
+ count += len;
+ }
+ else
+ {
+ break;
+ }
+
+ if (count == nbyte)
+ break;
+ }
+
+ return count;
+}
+
+// Write data of specified length.
+int file_write(int fd, void *buf, int nbyte)
+{
+ int count = 0;
+ int len = 0;
+ while (true)
+ {
+ len = write(fd, buf + count, nbyte - count);
+ if (len > 0)
+ {
+ count += len;
+ }
+ else
+ {
+ LOGE("write() fail,ret = %d,errno = %d", len, errno);
+ break;
+ }
+
+ if (count == nbyte)
+ break;
+ }
+
+ return count;
+}
+
+int file_close(int fd)
+{
+ int result = close(fd);
+ if(result == -1) {
+ LOGE("Close file fail:%d", errno);
+ }
+ return result;
+}
diff --git a/mbtk/libmbtk_lib/common/mbtk_gpio.c b/mbtk/libmbtk_lib/common/mbtk_gpio.c
new file mode 100755
index 0000000..0116f60
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_gpio.c
@@ -0,0 +1,212 @@
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+#include "mbtk_gpio.h"
+
+
+static int gpio_export(int gpio)
+{
+ int fd = -1;
+ char buffer[50];
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer,"/sys/class/gpio/gpio%d/direction", gpio);
+ if(access(buffer , F_OK) == 0)
+ {
+ LOGD("%d has export.", gpio);
+ return 0;
+ }
+
+ fd = open("/sys/class/gpio/export", O_WRONLY);
+ if(fd < 0)
+ {
+ LOGE("Open gpio export file fail.");
+ return -1;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer , "%d", gpio);
+ if(write(fd, buffer, strlen(buffer)) <= 0)
+ {
+ LOGE("Gpio[%d] export fail.", gpio);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 0;
+}
+
+static int gpio_unexport(int gpio)
+{
+ int fd = -1;
+ char buffer[50];
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer,"/sys/class/gpio/gpio%d/direction", gpio);
+ if(access(buffer , F_OK))
+ {
+ LOGD("%d not export.", gpio);
+ return 0;
+ }
+
+ fd = open("/sys/class/gpio/unexport", O_WRONLY);
+ if(fd < 0)
+ {
+ LOGE("Open gpio unexport file fail.");
+ return -1;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer , "%d", gpio);
+ if(write(fd, buffer, strlen(buffer)) <= 0)
+ {
+ LOGE("Gpio[%d] unexport fail.", gpio);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return 0;
+}
+
+mbtk_gpio_direct_t mbtk_gpio_direct_get(int gpio)
+{
+ char buffer[50];
+ int fd = -1;
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer, "/sys/class/gpio/gpio%d/direction", gpio);
+ fd = open(buffer, O_RDONLY);
+ if(fd < 0)
+ {
+ LOGE("Open gpio[%d] direct fail.", gpio);
+ return MBTK_GPIO_DIRECT_UNKNOWN;
+ }
+
+ memset(buffer, 0x0, sizeof(buffer));
+ if(read(fd, buffer, sizeof(buffer)) <= 0)
+ {
+ LOGE("Get gpio[%d] direct fail.", gpio);
+ close(fd);
+ return MBTK_GPIO_DIRECT_UNKNOWN;
+ }
+ close(fd);
+
+ if(strcmp(buffer, "out") == 0) {
+ return MBTK_GPIO_DIRECT_OUT;
+ } else if(strcmp(buffer, "in") == 0) {
+ return MBTK_GPIO_DIRECT_IN;
+ } else {
+ LOGE("direct : %s", buffer);
+ return MBTK_GPIO_DIRECT_UNKNOWN;
+ }
+}
+
+int mbtk_gpio_direct_set(int gpio, mbtk_gpio_direct_t dir)
+{
+ char buffer[50];
+ int fd = -1;
+ int ret = 0;
+
+ if(gpio_export(gpio)) {
+ return -1;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer, "/sys/class/gpio/gpio%d/direction", gpio);
+ fd = open(buffer, O_WRONLY);
+ if(fd < 0)
+ {
+ LOGE("Open gpio[%d] direct fail.", gpio);
+ return -1;
+ }
+
+ if(MBTK_GPIO_DIRECT_OUT == dir) {
+ if(write(fd, "out", 3) != 3) {
+ ret = -1;
+ LOGE("Write out fail:%d", errno);
+ }
+ } else if(MBTK_GPIO_DIRECT_IN == dir) {
+ if(write(fd, "in", 2) != 2) {
+ ret = -1;
+ LOGE("Write in fail:%d", errno);
+ }
+ } else {
+ LOGE("Unknown direct : %d", dir);
+ ret = -1;
+ }
+
+ close(fd);
+ return ret;
+}
+
+int mbtk_gpio_value_get(int gpio)
+{
+ char buffer[50];
+ int fd =-1;
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer, "/sys/class/gpio/gpio%d/value", gpio);
+ fd = open(buffer, O_RDONLY);
+ if(fd == -1)
+ {
+ LOGE("Open gpio[%d] fail.", gpio);
+ return -1;
+ }
+
+ if(read(fd, buffer, sizeof(buffer)) <= 0)
+ {
+ LOGE("Get gpio[%d] value fail", gpio);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return atoi(buffer);
+}
+
+int mbtk_gpio_value_set(int gpio, mbtk_gpio_direct_t dir, int value)
+{
+ char buffer[50];
+ int fd = -1;
+ int ret =-1;
+
+ if(gpio_export(gpio)) {
+ return -1;
+ }
+
+ if(mbtk_gpio_direct_set(gpio, dir)) {
+ return -1;
+ }
+
+ memset(buffer, 0, sizeof(buffer));
+ sprintf(buffer, "/sys/class/gpio/gpio%d/value", gpio);
+ fd = open(buffer, O_WRONLY);
+ if(fd == -1)
+ {
+ LOGE("Open gpio[%d] value fail.", gpio);
+ return -1;
+ }
+ if(value == 0) {
+ ret = write(fd, "0", 1);
+ } else {
+ ret = write(fd, "1", 1);
+ }
+
+ close(fd);
+ if(ret != 1)
+ {
+ LOGE("Set gpio[%d] value fail.", gpio);
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_list.c b/mbtk/libmbtk_lib/common/mbtk_list.c
new file mode 100755
index 0000000..d31cedf
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_list.c
@@ -0,0 +1,332 @@
+/*
+ * mbtk_list.c
+ *
+ * Created on: Aug 18, 2020
+ * Author: lb
+ */
+#include <string.h>
+#include <stdlib.h>
+#include "mbtk_list.h"
+
+list_node_t* list_create(list_free_func free_func)
+{
+ list_node_t *list = (list_node_t*) malloc(sizeof(list_node_t));
+ if (list) {
+ memset(list, 0x0, sizeof(list_node_t));
+ list->size = 0;
+ list->cur_index = 0;
+ list->cur_array_data = NULL;
+ list->sort_func = NULL;
+ list->free_func = free_func;
+ return list;
+ }
+
+ return NULL;
+}
+
+uint32 list_size(list_node_t *list)
+{
+ if (list) {
+ return list->size;
+ } else {
+ return 0;
+ }
+}
+
+static list_treenode_t* list_treeadd(list_node_t *list, list_treenode_t *node,
+ list_arraynode_t *data)
+{
+ if (node && node->data) {
+ int result = list->sort_func(data->data, node->data->data);
+ if (result == 0) { // Same node
+ node->count++;
+ // printf("Same[%d]:%s\n", node->count, data->data);
+
+ // Add the same node to last.
+ list_arraynode_t *array_node = node->data;
+ while (array_node->next) {
+ array_node = array_node->next;
+ }
+ array_node->next = data;
+ array_node->next->next = NULL;
+
+ } else if (result < 0) {
+ node->left = list_treeadd(list, node->left, data);
+ } else {
+ node->right = list_treeadd(list, node->right, data);
+ }
+ } else {
+ if (!node) {
+ node = (list_treenode_t*) malloc(sizeof(list_treenode_t));
+ }
+ node->left = NULL;
+ node->right = NULL;
+ node->data = data;
+ node->count = 1;
+ }
+
+ return node;
+}
+
+void list_add(list_node_t *list, void *data)
+{
+ if (list && data) {
+ list_arraynode_t *node = &(list->array_data);
+ while (node->next) {
+ node = node->next;
+ }
+
+ node->next = (list_arraynode_t*) malloc(sizeof(list_arraynode_t));
+ if(node->next) {
+ node->next->data = data;
+ node->next->next = NULL;
+ list->size++;
+ }
+ }
+}
+
+void list_add_unique(list_node_t *list, void *data, uint32 len)
+{
+ if (list && data && len > 0) {
+ list_arraynode_t *node = &(list->array_data);
+ while (node->next) {
+ if (!memcmp(node->next->data, data, len)) {
+ return;
+ }
+ node = node->next;
+ }
+
+ node->next = (list_arraynode_t*) malloc(sizeof(list_arraynode_t));
+ node->next->data = data;
+ node->next->next = NULL;
+
+ list->size++;
+ }
+}
+
+void* list_remove(list_node_t *list, void *data)
+{
+ if (list) {
+ list_arraynode_t *node = list->array_data.next;
+ if (node) {
+ if (data == node->data) { // Find node
+ list_arraynode_t *result = node;
+ void *reault_data = result->data;
+ list->array_data.next = node->next;
+ free(result);
+ list->size--;
+ return reault_data;
+ }
+ } else {
+ return NULL;
+ }
+
+ while (node->next) {
+ if (data == node->next->data) { // Find node
+ list_arraynode_t *result = node->next;
+ void *reault_data = result->data;
+ node->next = node->next->next;
+ free(result);
+ list->size--;
+ return reault_data;
+ }
+ node = node->next;
+ }
+ }
+
+ return NULL;
+}
+
+void* list_remove_by_content(list_node_t *list, void *data, uint32 data_len)
+{
+ if (list) {
+ list_arraynode_t *node = list->array_data.next;
+ if (node) {
+ if (!memcmp(data, node->data, data_len)) { // Find node
+ list_arraynode_t *result = node;
+ void *reault_data = result->data;
+ list->array_data.next = node->next;
+ free(result);
+ list->size--;
+ return reault_data;
+ }
+ } else {
+ return NULL;
+ }
+
+ while (node->next) {
+ if (!memcmp(data, node->next->data, data_len)) { // Find node
+ list_arraynode_t *result = node->next;
+ void *reault_data = result->data;
+ node->next = node->next->next;
+ free(result);
+ list->size--;
+ return reault_data;
+ }
+ node = node->next;
+ }
+ }
+
+ return NULL;
+}
+
+void list_first(list_node_t *list)
+{
+ if (list) {
+ list->cur_index = 0;
+ list->cur_array_data = list->array_data.next;
+ }
+}
+
+void* list_next(list_node_t *list)
+{
+ if (list) {
+ list_arraynode_t *node = list->cur_array_data;
+ if (node) {
+ list->cur_array_data = list->cur_array_data->next;
+ list->cur_index++;
+
+ return node->data;
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+void* list_get(list_node_t *list, uint32 index)
+{
+ if (list) {
+ if (index >= list->size) {
+ return NULL;
+ }
+
+ list_arraynode_t *node = list->array_data.next;
+ if (node) {
+ uint32 i = 0;
+ while (node) {
+ if (i == index) {
+ return node->data;
+ }
+ node = node->next;
+ i++;
+ }
+ }
+
+ return NULL;
+ } else {
+ return NULL;
+ }
+}
+
+static void list_treenext(list_node_t *list, list_treenode_t *tree_node)
+{
+ if (list && tree_node) {
+ list_treenode_t *left = tree_node->left;
+ list_treenode_t *right = tree_node->right;
+ list_treenext(list, left);
+
+ list_arraynode_t *array_node = tree_node->data;
+ while (array_node) {
+ list->cur_array_data->next = array_node;
+ list->cur_array_data = array_node;
+ array_node = array_node->next;
+ }
+ list_treenext(list, right);
+ }
+}
+
+static void list_treefree(list_node_t *list, list_treenode_t *tree_node)
+{
+ if (list && tree_node) {
+ list_treefree(list, tree_node->left);
+ list_treefree(list, tree_node->right);
+
+ if (&(list->tree_data) != tree_node) {
+ free(tree_node);
+ tree_node = NULL;
+ }
+ }
+}
+
+void list_sort(list_node_t *list, list_sort_func sort_func)
+{
+ if (list && sort_func) {
+ list->sort_func = sort_func;
+ list_arraynode_t *node = list->array_data.next; // First node
+ if (node) {
+ uint32 i = 0;
+ list_arraynode_t **temp = (list_arraynode_t **) malloc(
+ sizeof(list_arraynode_t*) * list->size);
+ list_arraynode_t *temp_node = node;
+ while (node) {
+ temp[i] = node;
+ temp_node = node;
+ node = node->next;
+ temp_node->next = NULL;
+ i++;
+ }
+
+ for (i = 0; i < list->size; i++) {
+ list_treeadd(list, &(list->tree_data), temp[i]);
+ }
+
+ /*while (node) {
+ list_treeadd(list, &(list->tree_data), node);
+ node = node->next;
+ }*/
+
+ // Sort complete.
+ list->cur_array_data = &(list->array_data);
+ list_treenext(list, &(list->tree_data));
+
+ list_treefree(list, &(list->tree_data));
+ free(temp);
+ }
+ }
+}
+
+void list_free(list_node_t *list)
+{
+ if (list) {
+ list_arraynode_t *node = &(list->array_data); // Head node
+ list_arraynode_t *node_temp = NULL;
+ while (node->next) {
+ node_temp = node->next;
+ node->next = node->next->next;
+
+ if (list->free_func) {
+ list->free_func(node_temp->data);
+ } else {
+ free(node_temp->data);
+ }
+ free(node_temp);
+ }
+ free(list);
+ }
+}
+
+void list_clear(list_node_t *list)
+{
+ if (list) {
+ list_arraynode_t *node = &(list->array_data); // Head node
+ list_arraynode_t *node_temp = NULL;
+ while (node->next) {
+ node_temp = node->next;
+ node->next = node->next->next;
+
+ if (list->free_func) {
+ list->free_func(node_temp->data);
+ }
+ free(node_temp);
+ }
+ list_free_func free_func = list->free_func;
+ memset(list, 0x0, sizeof(list_node_t));
+ list->size = 0;
+ list->cur_index = 0;
+ list->cur_array_data = NULL;
+ list->sort_func = NULL;
+ list->free_func = free_func;
+ }
+}
diff --git a/mbtk/libmbtk_lib/common/mbtk_log.c b/mbtk/libmbtk_lib/common/mbtk_log.c
new file mode 100755
index 0000000..11ec8fd
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_log.c
@@ -0,0 +1,203 @@
+#include <stdio.h>
+//#include <include/log.h>
+#include <sys/un.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <time.h>
+#include <string.h>
+#include <sys/time.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <include/logd.h>
+#include <ctype.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+#include "mbtk_str.h"
+
+typedef enum {
+ LOG_ID_MAIN = 0,
+ LOG_ID_RADIO = 1,
+ LOG_ID_EVENTS = 2,
+ LOG_ID_SYSTEM = 3,
+ LOG_ID_KMSG = 4,
+ LOG_ID_MAX
+} log_id_t;
+
+#define LOG_VERBOSE 8
+
+static int tlog_fd = -1;
+// Default for radio log.
+static int syslog_radio_enable = 2;
+static FILE* logfile = NULL;
+static int signal_fd = -1;
+
+static bool log_level_printed = FALSE;
+
+/**
+ * @brief mbtk_log_init
+ *
+ * @details 设置Log输出方式
+ * @param
+ * path:
+ * 不填参数(NULL) stdout : 命令行输
+ * "syslog":输出到syslog
+ * "radio":CatStudio
+ * 文件路径:输出到自定义文件路径
+ * tag : 自定义tag
+ *
+ * example:
+ * mbtk_log_init(NULL, "MBTK_RIL");
+ * mbtk_log_init("syslog", "MBTK_RIL");
+ * mbtk_log_init("radio", "MBTK_RIL");
+ * mbtk_log_init("/tmp/log/test.log", "MBTK_RIL");
+ */
+void mbtk_log_init(char* path, char* tag)
+{
+ if (str_empty(path)) {
+ tlog_fd = STDOUT_FILENO;
+ } else if (0 == memcmp(path, "syslog", 6)) {
+ openlog(tag, LOG_PID, LOG_USER);
+ syslog_radio_enable = 1;
+ } else if (0 == memcmp(path, "radio", 5)) {
+ if (tag && strlen(tag) > 0) {
+ set_service_log_tag(tag);
+ } else {
+ set_service_log_tag("MBTK");
+ }
+ syslog_radio_enable = 2;
+ } else if (path) {
+ tlog_fd = open(path, O_CREAT | O_WRONLY | O_APPEND, 0600);
+ if (tlog_fd < 0) {
+ fprintf(stderr, "failed to open %s: %s\n", path, strerror(errno));
+ exit(-1);
+ }
+ }
+}
+
+/* Control the log output */
+void mbtk_log(int level, const char* format, ...)
+{
+ char buf[1024] = {0};
+ va_list ap;
+ struct timeval log_time;
+ int length = 0;
+
+ va_start(ap, format);
+ length = vsnprintf(buf, sizeof(buf), format, ap);
+ if (length < 0 || 0 == length) {
+ return;
+ }
+
+ if (1 == syslog_radio_enable) {
+ syslog(level, "%s", buf);
+ } else if (2 == syslog_radio_enable) {
+ __android_log_printf(LOG_ID_RADIO, level, "%s", buf);
+
+ if(!log_level_printed) {
+ __android_log_printf(LOG_ID_RADIO, LOG_ERR_LEVEL, "sloglevel = %d", get_service_log_level());
+ log_level_printed = TRUE;
+ }
+ } else if (-1 != tlog_fd) {
+ char tmp[50] = {0};
+ gettimeofday(&log_time, NULL);
+ struct tm* tm_t = localtime(&(log_time.tv_sec));
+ strftime(tmp, 50, "%F %T", tm_t);
+ snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), " %d<%d>:", (int)(log_time.tv_usec / 1000), level);
+ write(tlog_fd, tmp, strlen(tmp));
+ write(tlog_fd, buf, length);
+ if (buf[length - 1] != '\n') {
+ write(tlog_fd, "\n", 1);
+ }
+ if (tlog_fd > 2) {
+ fsync(tlog_fd);
+ }
+ }
+
+ va_end(ap);
+}
+
+void log_hex(const char* tag, const void* data, int data_len)
+{
+ char buffer[60];
+ char str[17];
+ int size = 0;
+ uint8* ptr = (uint8*)data;
+ int i, j;
+ memset(buffer, 0x0, 60);
+ memset(str, 0x0, 17);
+ LOGI("%s,Length-%d:", tag, data_len);
+ LOGI(" 0 1 2 3 4 5 6 7 8 9 a b c d e f");
+ size += snprintf(buffer, 60, "%04x| ", 0);
+ for (i = 0; i < data_len; i++) {
+ size += snprintf(buffer + size, 60 - size, "%02x ", ptr[i]);
+ if (isprint(ptr[i])) {
+ str[i % 16] = ptr[i];
+ } else {
+ str[i % 16] = '.';
+ }
+ if ((i + 1) % 16 == 0 || i == data_len - 1) {
+ for (j = size; j < 54; j++) {
+ buffer[j] = ' ';
+ }
+ LOGI("%s| %s", buffer, str);
+
+ memset(buffer, 0x0, 60);
+ memset(str, 0x0, 17);
+ size = 0;
+ size += snprintf(buffer, 60, "%04x| ", (i + 1) / 16);
+ }
+ }
+}
+
+#define _MOPEN_RILD_SOCKET "/tmp/logd_socket"
+
+int mbtk_signal_log(char *data)
+{
+ char buff[256];
+ int size = 0;
+ int ret = 0;
+ int i = 0;
+ static struct sockaddr_un srv_addr;
+
+ if(signal_fd < 0) {
+ if (access(_MOPEN_RILD_SOCKET, F_OK) == -1) {
+ LOGW("Service not running...");
+ return -1;
+ }
+
+ signal_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (signal_fd < 0) {
+ LOGE("cannot creat socket");
+ return -1;
+ }
+
+ srv_addr.sun_family = AF_UNIX;
+ strcpy(srv_addr.sun_path, _MOPEN_RILD_SOCKET);
+ ret = connect(signal_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
+ if (ret < 0) {
+ LOGE("cannot connect server, ret=%d, errno=%d", ret, errno);
+ close(signal_fd);
+ signal_fd = -1;
+ return -1;
+ }
+ }
+
+ memset(buff, 0, sizeof(buff));
+ snprintf(buff, sizeof(buff), "%s\n", data);
+ size = write(signal_fd, buff, sizeof(buff));
+ if (size < 0 || size == 0) {
+ LOGE("cannot write , ret=%d, errno=%d\n", ret, errno);
+ return 1;
+ }
+
+ // close(signal_fd);
+
+ return 0;
+}
diff --git a/mbtk/libmbtk_lib/common/mbtk_map.c b/mbtk/libmbtk_lib/common/mbtk_map.c
new file mode 100755
index 0000000..061a538
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_map.c
@@ -0,0 +1,242 @@
+/*
+ * mbtk_map.c
+ *
+ * Created on: Aug 18, 2020
+ * Author: lb
+ */
+#include <stdlib.h>
+#include <string.h>
+#include "mbtk_map.h"
+
+map_node_t* map_create(uint32 capacity, map_free_func free_func)
+{
+ if (capacity > 0) {
+ map_node_t *map = (map_node_t*) malloc(sizeof(map_node_t));
+ if (map) {
+ memset(map, 0x0, sizeof(map_node_t));
+ map->size = 0;
+ map->cur_index = 0;
+ map->cur_data = NULL;
+ map->capacity = (uint32) (capacity * 0.75f); // Default 0.75
+ if(map->capacity < 1) {
+ free(map);
+ return NULL;
+ }
+ map->free_func = free_func;
+ map->map_array = (map_data_t**) malloc(
+ sizeof(map_data_t*) * map->capacity);
+ uint32 i = 0;
+ while (i < map->capacity) {
+ map->map_array[i] = NULL;
+ i++;
+ }
+ return map;
+ }
+ }
+
+ return NULL;
+}
+
+uint32 map_size(map_node_t* map)
+{
+ if (map) {
+ return map->size;
+ }
+
+ return 0;
+}
+
+uint32 map_hash(const char* key, uint32 capacity)
+{
+ uint32 hash = 0;
+ const uint8 *ptr = (const uint8*) key;
+ while (*ptr) {
+ hash = 31 * hash + *ptr;
+ ptr++;
+ }
+
+ return hash % capacity;
+}
+
+void map_put(map_node_t* map, const char* key, void* value)
+{
+ if (map && key && strlen(key) > 0 && value) {
+ uint32 index = map_hash(key, map->capacity);
+
+ map_data_t *ptr = map->map_array[index];
+ if (!ptr) { // Add to first position.
+ ptr = (map_data_t*) malloc(sizeof(map_data_t));
+ ptr->key = strdup(key);
+ ptr->value = value;
+ ptr->next = NULL;
+
+ map->size++;
+ map->map_array[index] = ptr;
+ } else { // This position has one item at least.
+ if (!memcmp(ptr->key, key, strlen(key))) { // Has this item,will change.
+ if (map->free_func) {
+ map->free_func(ptr->value);
+ }
+
+ ptr->value = value;
+ } else {
+ while (ptr->next) {
+ if (!memcmp(ptr->next->key, key, strlen(key))) // Has this item,will change.
+ break;
+ ptr = ptr->next;
+ }
+
+ if (!ptr->next) { // Add new item.
+ ptr->next = (map_data_t*) malloc(sizeof(map_data_t));
+
+ ptr->next->key = strdup(key);
+ ptr->next->value = value;
+ ptr->next->next = NULL;
+ map->size++;
+ } else { // Change item.
+ if (map->free_func) {
+ map->free_func(ptr->next->value);
+ }
+
+ ptr->next->value = value;
+ }
+ }
+ }
+ }
+}
+
+void* map_get(map_node_t* map, char* key)
+{
+ if (map && key && strlen(key) > 0) {
+ uint32 index = map_hash(key, map->capacity);
+ map_data_t *ptr = map->map_array[index];
+ while (ptr) {
+ if (ptr->key && !memcmp(ptr->key, key, strlen(key))) {
+ return ptr->value;
+ }
+ ptr = ptr->next;
+ }
+ }
+ return NULL;
+}
+
+void* map_remove(map_node_t* map, char* key)
+{
+ if (map && key && strlen(key) > 0) {
+ uint32 index = map_hash(key, map->capacity);
+ map_data_t *ptr = map->map_array[index];
+ if (!ptr) { // No items.
+ return NULL;
+ }
+
+ if (!memcmp(ptr->key, key, strlen(key))) { // Is first item
+ map_data_t *temp = ptr;
+ void *result = temp->value;
+ map->map_array[index] = ptr->next;
+ free(temp);
+ map->size--;
+
+ return result;
+ } else {
+ while (ptr->next) {
+ if (!memcmp(ptr->next->key, key, strlen(key))) {
+ map_data_t *temp = ptr->next;
+ void *result = temp->value;
+ ptr->next = temp->next;
+ free(temp);
+ map->size--;
+
+ return result;
+ }
+ ptr = ptr->next;
+ }
+ }
+ }
+ return NULL;
+}
+
+void map_first(map_node_t *map)
+{
+ if (map) {
+ map->cur_index = 0;
+ map->cur_data = map->map_array[0];
+ }
+}
+
+void* map_next(map_node_t *map)
+{
+ if (map) {
+ while (1) {
+ if (map->cur_data) {
+ void *result = map->cur_data;
+ map->cur_data = map->cur_data->next;
+ return result;
+ } else {
+ map->cur_index++;
+ if (map->cur_index < map->capacity) {
+ map->cur_data = map->map_array[map->cur_index];
+ } else { // Finish
+ return NULL;
+ }
+ }
+ }
+ } else {
+ return NULL;
+ }
+}
+
+void map_clear(map_node_t* map)
+{
+ if (map) {
+ uint32 i = 0;
+ map_data_t *ptr = NULL;
+ while (i < map->capacity) {
+ ptr = map->map_array[i];
+ while (ptr) {
+ map->map_array[i] = ptr->next;
+
+ free(ptr->key);
+ if (map->free_func) {
+ map->free_func(ptr->value);
+ }
+ free(ptr);
+
+ ptr = map->map_array[i];
+ }
+ i++;
+ }
+
+ map->size = 0;
+ map->cur_index = 0;
+ map->cur_data = NULL;
+ memset(map->map_array, 0x0,
+ sizeof(sizeof(map_data_t*) * map->capacity));
+ }
+}
+
+void map_free(map_node_t* map)
+{
+ if (map) {
+ uint32 i = 0;
+ map_data_t *ptr = NULL;
+ while (i < map->capacity) {
+ ptr = map->map_array[i];
+ while (ptr) {
+ map->map_array[i] = ptr->next;
+
+ free(ptr->key);
+ if (map->free_func) {
+ map->free_func(ptr->value);
+ }
+ free(ptr);
+
+ ptr = map->map_array[i];
+ }
+ i++;
+ }
+
+ free(map->map_array);
+ free(map);
+ }
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_mtd.c b/mbtk/libmbtk_lib/common/mbtk_mtd.c
new file mode 100755
index 0000000..b17b27f
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_mtd.c
@@ -0,0 +1,163 @@
+/*
+* mbtk_mtd.c
+*
+* MBTK mtd partition utils API.
+*
+*/
+/******************************************************************************
+
+ EDIT HISTORY FOR FILE
+
+ WHEN WHO WHAT,WHERE,WHY
+-------- -------- -------------------------------------------------------
+2024/2/26 LiuBin Initial version
+
+******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "mbtk_mtd.h"
+#include "mbtk_log.h"
+#include "mbtk_str.h"
+
+static mbtk_partition_info_t partition_list[MBTK_PARTITION_NUM_MAX];
+static bool partition_inited = FALSE;
+
+mbtk_partition_info_t* mbtk_partition_get()
+{
+ if(partition_inited) {
+ return partition_list;
+ }
+
+ memset(partition_list, 0x0, sizeof(partition_list));
+ FILE *fp = fopen("/proc/mtd", "r");
+ if(fp == NULL) {
+ LOGE("fopen(/proc/mtd) fail:%d", errno);
+ return NULL;
+ }
+
+ char buff[64];
+ int index = 0;
+ char size_str[16];
+ char name[32];
+ char erase_size_str[16];
+ char name_temp[32];
+ memset(buff, 0x0, 64);
+ memset(name_temp, 0x0, 32);
+ while(fgets(buff, 64, fp)) {
+ if(str_startwith(buff, "mtd")) {
+ memset(size_str, 0x0, 16);
+ memset(erase_size_str, 0x0, sizeof(erase_size_str));
+ memset(name, 0x0, 32);
+ if(4 == sscanf(buff, "%s %s %s %s", partition_list[index].dev, size_str, erase_size_str, name)) {
+ if(name[0] == '\"' && name[strlen(name) - 1] == '\"') {
+ memcpy(partition_list[index].name, name + 1, strlen(name) - 2); // No copy ""
+ } else {
+ LOGE("partition(%s) name error.", buff);
+ return NULL;
+ }
+
+ if(partition_list[index].dev[strlen(partition_list[index].dev) - 1] == ':') {
+ partition_list[index].dev[strlen(partition_list[index].dev) - 1] = '\0';
+ }
+
+ partition_list[index].partition_size = (uint32)strtoul(size_str, NULL, 16);
+ partition_list[index].erase_size = (uint32)strtoul(erase_size_str, NULL, 16);
+ // XXX-sdtim or XXX-mount
+ ssize_t index_sdtim = str_indexof(partition_list[index].name, "-sdtim");
+ ssize_t index_mount = str_indexof(partition_list[index].name, "-mount");
+ if(index_sdtim > 0 || index_mount > 0) {
+ if(index_sdtim > 0) {
+ memcpy(name_temp, partition_list[index].name, index_sdtim);
+ } else {
+ memcpy(name_temp, partition_list[index].name, index_mount);
+ }
+ if(index > 0) {
+ partition_list[index].partition_start = partition_list[index - 1].partition_start + partition_list[index - 1].partition_size;
+ }
+ } else {
+ if(strlen(name_temp) > 0) {
+ memset(name_temp, 0x0, 32);
+ if(index > 0) {
+ partition_list[index].partition_start = partition_list[index - 2].partition_start;
+ }
+ } else {
+ if(index > 0) {
+ partition_list[index].partition_start = partition_list[index - 1].partition_start + partition_list[index - 1].partition_size;
+ }
+ }
+ }
+ partition_list[index].used = TRUE;
+ } else {
+ LOGE("sscanf(%s) fail:%d", buff, errno);
+ return NULL;
+ }
+ index++;
+ }
+ memset(buff, 0x0, 64);
+ }
+ fclose(fp);
+
+ int i = 0;
+ while(i < MBTK_PARTITION_NUM_MAX) {
+ if(partition_list[i].used) {
+ LOGD("%s(%s) : %08x %08x", partition_list[i].name, partition_list[i].dev,
+ partition_list[i].partition_start, partition_list[i].partition_size);
+ }
+ i++;
+ }
+
+ partition_inited = TRUE;
+ return partition_list;
+}
+
+int mbtk_partition_get_by_name(char *partition_name, mbtk_partition_info_t *info)
+{
+ FILE *fp = fopen("/proc/mtd", "r");
+ if(fp == NULL) {
+ LOGE("fopen(/proc/mtd) fail:%d", errno);
+ return -1;
+ }
+
+ char buff[64];
+ char size_str[16];
+ char erase_size_str[16];
+ char name[32];
+ memset(buff, 0x0, sizeof(buff));
+ while(fgets(buff, sizeof(buff), fp)) {
+ if(strstr(buff, partition_name)) {
+ memset(size_str, 0x0, sizeof(size_str));
+ memset(erase_size_str, 0x0, sizeof(erase_size_str));
+ memset(name, 0x0, sizeof(name));
+ memcpy(info->dev, "/dev/", 5);
+ if(4 == sscanf(buff, "%s %s %s %s", info->dev + 5, size_str, erase_size_str, name)) {
+ if(name[0] == '\"' && name[strlen(name) - 1] == '\"') {
+ memcpy(info->name, name + 1, strlen(name) - 2); // No copy ""
+ } else {
+ LOGE("partition(%s) name error.", buff);
+ return -1;
+ }
+
+ if(info->dev[strlen(info->dev) - 1] == ':') {
+ info->dev[strlen(info->dev) - 1] = '\0';
+ }
+
+ info->partition_size = (uint32)strtoul(size_str, NULL, 16);
+ info->erase_size = (uint32)strtoul(erase_size_str, NULL, 16);
+ //info->partition_start += info->partition_size;
+ break;
+ } else {
+ LOGE("sscanf(%s) fail:%d", buff, errno);
+ return -1;
+ }
+ }
+ memset(buff, 0x0, sizeof(buff));
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_ntp.c b/mbtk/libmbtk_lib/common/mbtk_ntp.c
new file mode 100755
index 0000000..5b23e37
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_ntp.c
@@ -0,0 +1,299 @@
+/*
+* FILE: ntp.c
+* NOTE: socket网络编程学习,NTP时间获取程序
+*
+* TIME: 2021年11月13日00:05:39
+*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+#include "mbtk_log.h"
+
+#define NTP_PORT 123
+#define TIME_PORT 37
+#define NTP_SERVER_IP "cn.pool.ntp.org"
+
+#define NTP_PORT_STR "123"
+#define NTPV1 "NTP/V1"
+#define NTPV2 "NTP/V2"
+
+#define NTPV3 "NTP/V3"
+#define NTPV4 "NTP/V4"
+#define TIME "TIME/UDP"
+
+#define NTP_PCK_LEN 48
+
+#define LI 0
+#define VN 3
+#define MODE 3
+#define STRATUM 0
+#define POLL 4
+#define PREC -6
+
+#define JAN_1970 0x83aa7e80 /* 1900 年~1970 年之间的时间秒数 */
+#define NTPFRAC(x) (4294 * (x) + ((1981 * (x)) >> 11))
+#define USEC(x) (((x) >> 12) - 759 * ((((x) >> 10) + 32768) >> 16))
+
+
+time_t sys_time;
+typedef struct _ntp_time
+{
+ unsigned int coarse;
+ unsigned int fine;
+} ntp_time;
+
+/* NTP时钟同步报文 */
+struct ntp_packet
+{
+ unsigned char leap_ver_mode;
+ unsigned char startum;
+ char poll;
+ char precision;
+ int root_delay;
+ int root_dispersion;
+ int reference_identifier;
+ ntp_time reference_timestamp;
+ ntp_time originage_timestamp;
+ ntp_time receive_timestamp;
+ ntp_time transmit_timestamp;
+};
+
+char protocol[32];
+
+int construct_packet(char *packet)
+{
+ char version = 1;
+ long tmp_wrd;
+ int port;
+ time_t timer;
+ strcpy(protocol, NTPV4);
+ /*判断协议版本*/
+ if(!strcmp(protocol, NTPV1)||!strcmp(protocol, NTPV2)||!strcmp(protocol, NTPV3)||!strcmp(protocol, NTPV4))
+ {
+ memset(packet, 0, NTP_PCK_LEN);
+ port = NTP_PORT;
+ /*设置 16 字节的包头*/
+ version = protocol[5] - 0x30;
+ tmp_wrd = htonl((LI << 30)|(version << 27) \
+ |(MODE << 24)|(STRATUM << 16)|(POLL << 8)|(PREC & 0xff));
+ memcpy(packet, &tmp_wrd, sizeof(tmp_wrd));
+
+ /*设置 Root Delay、 Root Dispersion 和 Reference Indentifier */
+ tmp_wrd = htonl(1<<16);
+ memcpy(&packet[4], &tmp_wrd, sizeof(tmp_wrd));
+ memcpy(&packet[8], &tmp_wrd, sizeof(tmp_wrd));
+ /*设置 Timestamp 部分*/
+ time(&timer);
+ /*设置 Transmit Timestamp coarse*/
+ tmp_wrd = htonl(JAN_1970 + (long)timer);
+ memcpy(&packet[40], &tmp_wrd, sizeof(tmp_wrd));
+ /*设置 Transmit Timestamp fine*/
+ tmp_wrd = htonl((long)NTPFRAC(timer));
+ memcpy(&packet[44], &tmp_wrd, sizeof(tmp_wrd));
+ return NTP_PCK_LEN;
+ }
+ else if (!strcmp(protocol, TIME))/* "TIME/UDP" */
+ {
+ port = TIME_PORT;
+ memset(packet, 0, 4);
+ return 4;
+ }
+
+ return 0;
+}
+
+/*获取 NTP 时间*/
+int get_ntp_time(int sk, struct addrinfo *addr, struct ntp_packet *ret_time)
+{
+ fd_set pending_data;
+ struct timeval block_time;
+ char data[NTP_PCK_LEN * 8];
+ socklen_t data_len = addr->ai_addrlen;
+ int packet_len, count = 0, result, i,re;
+
+ /* 组织请求报文 */
+ if (!(packet_len = construct_packet(data)))
+ {
+ return 0;
+ }
+ /*客户端给服务器端发送 NTP 协议数据包*/
+ if ((result = sendto(sk, data, packet_len, 0, addr->ai_addr, data_len)) < 0)
+ {
+ LOGE("sendto");
+ return 0;
+ }
+ /*调用select()函数,并设定超时时间为10s*/
+ FD_ZERO(&pending_data);
+ FD_SET(sk, &pending_data);
+ block_time.tv_sec=10;
+ block_time.tv_usec=0;
+ if (select(sk + 1, &pending_data, NULL, NULL, &block_time) > 0)
+ {
+ /*接收服务器端的信息*/
+ if ((count = recvfrom(sk, data, NTP_PCK_LEN * 8, 0, addr->ai_addr, &data_len)) < 0)
+ {
+ LOGE("recvfrom");
+ return 0;
+ }
+
+ // if (protocol == TIME)
+ if(!strcmp(protocol,TIME))
+ {
+ memcpy(&ret_time->transmit_timestamp, data, 4);
+ return 1;
+ }
+ else if (count < NTP_PCK_LEN)
+ {
+ return 0;
+ }
+
+ /* 设置接收 NTP 包的数据结构 */
+ ret_time->leap_ver_mode = ntohl(data[0]);
+ ret_time->startum = ntohl(data[1]);
+ ret_time->poll = ntohl(data[2]);
+ ret_time->precision = ntohl(data[3]);
+ ret_time->root_delay = ntohl(*(int*)&(data[4]));
+ ret_time->root_dispersion = ntohl(*(int*)&(data[8]));
+ ret_time->reference_identifier = ntohl(*(int*)&(data[12]));
+ ret_time->reference_timestamp.coarse = ntohl(*(int*)&(data[16]));
+ ret_time->reference_timestamp.fine = ntohl(*(int*)&(data[20]));
+ ret_time->originage_timestamp.coarse = ntohl(*(int*)&(data[24]));
+ ret_time->originage_timestamp.fine = ntohl(*(int*)&(data[28]));
+ ret_time->receive_timestamp.coarse = ntohl(*(int*)&(data[32]));
+ ret_time->receive_timestamp.fine = ntohl(*(int*)&(data[36]));
+ ret_time->transmit_timestamp.coarse = ntohl(*(int*)&(data[40]));
+ ret_time->transmit_timestamp.fine = ntohl(*(int*)&(data[44]));
+
+ /* 将NTP时间戳转换为日期 */
+ time_t currentTime = ret_time->transmit_timestamp.coarse - JAN_1970;
+ sys_time = ret_time->transmit_timestamp.coarse - JAN_1970;
+ struct tm CurlocalTime;
+ localtime_r(¤tTime, &CurlocalTime);
+ char dateTime[30];
+ strftime(dateTime, 30, "%Y-%m-%d %H:%M:%S %A", &CurlocalTime);
+
+ LOGI("%s\n", dateTime);
+
+ return 1;
+ } /* end of if select */
+
+
+ return 0;
+}
+
+/* 修改本地时间 */
+int set_local_time(struct ntp_packet * pnew_time_packet)
+{
+ struct timeval tv;
+ tv.tv_sec = pnew_time_packet->transmit_timestamp.coarse - JAN_1970;
+ tv.tv_usec = USEC(pnew_time_packet->transmit_timestamp.fine);
+ return settimeofday(&tv, NULL);
+}
+
+int ntp_main()
+{
+ int sockfd, rc;
+ struct addrinfo hints, *res = NULL;
+ struct ntp_packet new_time_packet;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+
+ /*调用 getaddrinfo()函数, 获取地址信息*/
+ rc = getaddrinfo(NTP_SERVER_IP, NTP_PORT_STR, &hints, &res);
+ if (rc != 0)
+ {
+ LOGE("getaddrinfo");
+ return 0;
+ }
+
+ /* 创建套接字 */
+ sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); //IPv4, 数据报套接字, UDP
+ if (sockfd <0 )
+ {
+ LOGE("socket");
+ return 0;
+ }
+
+ /*调用取得 NTP 时间的函数*/
+ if (get_ntp_time(sockfd, res, &new_time_packet))
+ {
+ printf("NTP client success!\n");
+ LOGI("NTP client success!\n");
+ }
+ else
+ {
+ printf("NTP client fail!\n");
+ LOGE("NTP client fail!\n");
+ close(sockfd);
+ return 0;
+ }
+
+ close(sockfd);
+
+ return sys_time;
+}
+
+time_t ntp_server_set(const char* server_ip, const char * port)
+{
+ int sockfd, rc;
+ struct addrinfo hints, *res = NULL;
+ struct ntp_packet new_time_packet;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+
+ printf("server_ip:%s,port:%s\n", server_ip, port);
+
+ /*调用 getaddrinfo()函数, 获取地址信息*/
+ rc = getaddrinfo(NTP_SERVER_IP, NTP_PORT_STR, &hints, &res);
+ if (rc != 0)
+ {
+ printf("getaddrinfo");
+ return 0;
+ }
+
+ /* 创建套接字 */
+ sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); //IPv4, 数据报套接字, UDP
+ if (sockfd <0 )
+ {
+ printf("socket");
+ return 0;
+ }
+
+ /*调用取得 NTP 时间的函数*/
+ if (get_ntp_time(sockfd, res, &new_time_packet))
+ {
+ printf("NTP client success!\n");
+ }
+
+ close(sockfd);
+
+ return sys_time;
+}
+
+
+time_t mbtk_ntp_server_set(const char* server_ip, const char * port)
+{
+ return ntp_server_set(server_ip, port);
+}
+
+
+int mbtk_at_systime(void)
+{
+ return ntp_main();
+}
+
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_queue.c b/mbtk/libmbtk_lib/common/mbtk_queue.c
new file mode 100755
index 0000000..8abc4d1
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_queue.c
@@ -0,0 +1,218 @@
+/*************************************************************
+Description:
+ mbtk_queue.c
+ Used to implement mobiletek standard queue interfaces
+Author:
+ YangDagang
+Date:
+ 2019-7-13
+*************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mbtk_type.h"
+#include "mbtk_queue.h"
+
+/*************************************************************
+ Constants and Macros
+*************************************************************/
+
+/*************************************************************
+ Definitions:enum,struct,union
+*************************************************************/
+
+
+/*************************************************************
+ Variables:local,extern
+*************************************************************/
+
+/*************************************************************
+ Local Function Declaration
+*************************************************************/
+
+/*************************************************************
+ Extern Function Declaration
+*************************************************************/
+
+/*************************************************************
+ Function Definitions
+*************************************************************/
+/*=============================================
+FUNCTION
+ mbtk_tcpip_ptr
+
+DESCRIPTION
+ get tcpip information pointer
+
+DEPENDENCIES
+ None
+
+PARAMETERS
+ None
+
+RETURN VALUE
+ tcpip information pointer
+
+SIDE EFFECTS
+ None
+=============================================*/
+void mbtk_queue_init(mbtk_queue_node_t *queue)
+{
+ if(queue == NULL)
+ {
+ return;
+ }
+ queue->count = 0;
+ queue->payload = NULL;
+ queue->front = NULL;
+ queue->rear = NULL;
+ mbtk_mutex_init(&queue->mutex);
+}
+
+int mbtk_queue_put(mbtk_queue_node_t *queue,void *payload)
+{
+ mbtk_queue_node_t *curr = NULL;
+ mbtk_queue_node_t *p = NULL;
+
+ if(payload == NULL || queue == NULL)
+ {
+ return -1;
+ }
+ mbtk_mutex_lock(&queue->mutex);
+ curr = (mbtk_queue_node_t*)malloc(sizeof(mbtk_queue_node_t));
+ if(curr == NULL)
+ {
+ mbtk_mutex_unlock(&queue->mutex);
+ return -1;
+ }
+ curr->count = 0;
+ curr->rear = NULL;
+ curr->payload = payload;
+ if(queue->front != NULL)
+ {
+ p = queue->front;
+ p->rear = curr;
+ curr->front = p;
+ queue->front = curr;
+ }
+ else
+ {
+ //fisrt add node
+ queue->front = curr;
+ queue->rear = curr;
+ curr->front = queue;
+ }
+ queue->count++;
+ mbtk_mutex_unlock(&queue->mutex);
+ return 0;
+}
+
+int mbtk_queue_insert(mbtk_queue_node_t *queue,void *payload)
+{
+ mbtk_queue_node_t *curr = NULL;
+ mbtk_queue_node_t *p = NULL;
+
+ if(payload == NULL || queue == NULL)
+ {
+ return -1;
+ }
+ mbtk_mutex_lock(&queue->mutex);
+ curr = (mbtk_queue_node_t*)malloc(sizeof(mbtk_queue_node_t));
+ if(curr == NULL)
+ {
+ mbtk_mutex_unlock(&queue->mutex);
+ return -1;
+ }
+ curr->rear = NULL;
+ curr->count = 0;
+ curr->payload = payload;
+ if(queue->front != NULL)
+ {
+ p = queue->rear;
+ queue->rear = curr;
+ curr->front = queue;
+ curr->rear = p;
+ p->front = curr;
+ }
+ else
+ {
+ //fisrt add node
+ queue->front = curr;
+ queue->rear = curr;
+ curr->front = queue;
+ }
+ queue->count++;
+ mbtk_mutex_unlock(&queue->mutex);
+ return 0;
+}
+
+void* mbtk_queue_get(mbtk_queue_node_t *queue)
+{
+ mbtk_queue_node_t *curr = NULL;
+ void *payload = NULL;
+
+ if((queue == NULL) || mbtk_queue_empty(queue))
+ {
+ return NULL;
+ }
+ mbtk_mutex_lock(&queue->mutex);
+ curr = queue->rear;
+ payload = curr->payload;
+ if(curr->rear != NULL)
+ {
+ queue->rear = curr->rear;
+ curr->rear->front = queue;
+ }
+ else
+ {
+ queue->front = NULL;
+ queue->rear = NULL;
+ }
+ free(curr);
+ curr = NULL;
+ queue->count--;
+ mbtk_mutex_unlock(&queue->mutex);
+ return payload;
+}
+
+bool mbtk_queue_empty(mbtk_queue_node_t *queue)
+{
+ bool is_empty = FALSE;
+
+ mbtk_mutex_lock(&queue->mutex);
+ if(queue != NULL)
+ {
+ if((queue->front == NULL) && (queue->rear == NULL))
+ {
+ is_empty = TRUE;
+ }
+ }
+ mbtk_mutex_unlock(&queue->mutex);
+ return is_empty;
+}
+
+bool mbtk_queue_is_full(mbtk_queue_node_t *queue)
+{
+ bool is_full = FALSE;
+
+ mbtk_mutex_lock(&queue->mutex);
+ if((queue != NULL) && (queue->count == MBTK_QUEUE_MAX_NUM))
+ {
+ is_full = TRUE;
+ }
+ mbtk_mutex_unlock(&queue->mutex);
+ return is_full;
+}
+
+void mbtk_queue_deinit(mbtk_queue_node_t *queue)
+{
+ if(queue == NULL)
+ {
+ return;
+ }
+ queue->count = 0;
+ queue->payload = NULL;
+ queue->front = NULL;
+ queue->rear = NULL;
+ mbtk_mutex_deinit(&queue->mutex);
+}
diff --git a/mbtk/libmbtk_lib/common/mbtk_str.c b/mbtk/libmbtk_lib/common/mbtk_str.c
new file mode 100755
index 0000000..ff2db9e
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_str.c
@@ -0,0 +1,250 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <mbtk_str.h>
+
+/*
+* Converts all of the characters in this String to lower.
+*
+* Parameters:
+* src - The string should be converted.
+* dest - The lowercase string.
+* len - The length of result string.Must be "strlen(src) + 1"
+* Returns:
+* The string, converted to lowercase,or NULL for fail.
+*/
+void*
+str_tolower
+(
+ const void *src,
+ void *dest,
+ size_t len
+)
+{
+ const char *s = (char*)src;
+ char *d = (char*)dest;
+ if(!s
+ || !d
+ || (strlen(d) + 1 > len)){
+ return NULL;
+ }
+
+ char* temp = d;
+ while(*s){
+ *temp++ = tolower(*s++);
+ }
+ *temp = '\0';
+
+ return dest;
+}
+
+/*
+* Converts all of the characters in this String to upper case.
+*
+* Parameters:
+* src - The string should be converted.
+* dest - The uppercase string.
+* len - The length of result string.Must be "strlen(str_ptr) + 1"
+* Returns:
+* The string, converted to uppercase.or NULL for fail.
+*/
+void*
+str_toupper
+(
+ const void *src,
+ void *dest,
+ size_t len
+)
+{
+ const char *s = (char*)src;
+ char *d = (char*)dest;
+ if(!s
+ || !d
+ || (strlen(d) + 1 > len)){
+ return NULL;
+ }
+ char* temp = d;
+ while(*s){
+ *temp++ = toupper(*s++);
+ }
+ *temp = '\0';
+ return dest;
+}
+
+/*
+* Remove the head and tail spaces.
+*/
+void*
+str_trim
+(
+ const void* str,
+ void *result,
+ size_t len
+)
+{
+ if(str == NULL || result == NULL
+ || len <= strlen((char*)str))
+ {
+ return NULL;
+ }
+
+ char* str_ptr = (char*)str;
+ while(*str_ptr && (*str_ptr == ' ' || *str_ptr == '\t' || *str_ptr == '\n' || *str_ptr == '\r')){
+ str_ptr++;
+ }
+
+ memset(result,0x0,len);
+ if(*str_ptr && strlen(str_ptr) > 0)
+ {
+ memset(result,0x0,len);
+ memcpy(result,str_ptr,strlen(str_ptr));
+ str_ptr = (char*)result + strlen((char*)result) - 1;
+ while(*str_ptr && (*str_ptr == ' ' || *str_ptr == '\t' || *str_ptr == '\n' || *str_ptr == '\r')){
+ *str_ptr = '\0';
+ str_ptr--;
+ }
+ }
+
+ return result;
+}
+
+/*
+* Returns true if and only if this string contains the specified sequence of char values.
+*
+* Parameters:
+* str - The substring to search from.
+* sub_str - The substring to search for.
+* Returns:
+* True if str contains sub_str, false otherwise.
+*/
+bool
+str_contains
+(
+ const void* str,
+ const void* sub_str
+)
+{
+ const char *s = (char*)str;
+ const char *s_sub = (char*)sub_str;
+
+ if(!s || !s_sub){
+ return FALSE;
+ }
+
+ return str_indexof(s,s_sub)==-1?FALSE:TRUE;
+}
+
+/*
+* Returns the index within this string of the first occurrence of the specified substring.
+* If no such substring, then -1 is returned.
+*
+* Parameters:
+* str - The substring to search from.
+* sub_str - The substring to search for.
+* Returns:
+* The index of the first occurrence of the specified substring,
+* or -1 if there is no such occurrence.
+*/
+ssize_t
+str_indexof
+(
+ const void* str,
+ const void* sub_str
+)
+{
+ const char *s = (char*)str;
+ const char *s_sub = (char*)sub_str;
+
+ if(!s || !s_sub){
+ return -1;
+ }
+ char* position = strstr(s,s_sub);
+ if(!position){
+ return -1;
+ }else{
+ return position - s;
+ }
+}
+
+/*
+* Returns a new string that is a substring of this string. The substring begins
+* at the specified beginIndex and extends to the character at index endIndex - 1.
+* Thus the length of the substring is endIndex-beginIndex.
+*
+* Examples:
+* "hamburger".substring(4, 8) returns "urge"
+* "smiles".substring(1, 5) returns "mile"
+*
+* Parameters:
+* begin_index The beginning index, inclusive.
+* end_index The ending index, exclusive.
+* Returns:
+* The specified substring or NULL.
+*/
+void*
+str_substring
+(
+ const void* str,
+ size_t begin_index,
+ size_t end_index,
+ void *sub_str,
+ size_t len
+)
+{
+ const char* s = (char*)str;
+ char *result = (char*)sub_str;
+ if(!s
+ || !result
+ || begin_index >= end_index
+ || begin_index >= strlen(s)
+ || end_index - begin_index + 1 > len){
+ return NULL;
+ }
+
+ if(end_index > strlen(s)){
+ end_index = strlen(s);
+ }
+
+ memcpy(result,s + begin_index,end_index - begin_index);
+ result[end_index - begin_index] = '\0';
+
+ return result;
+}
+
+bool str_startwith(const char* str, const void* prefix)
+{
+ if (!str || !(char*) prefix) {
+ return FALSE;
+ }
+ if (strlen((char*) str) < strlen((char*) prefix)) {
+ return FALSE;
+ }
+ return str_indexof(str, (char*) prefix) ? FALSE : TRUE;
+}
+
+void* strstr_hex(char *haystack,int haystack_len,
+ const char *needle,int needle_len)
+{
+ int index = 0;
+ if(haystack_len < needle_len)
+ return NULL;
+
+ while(index <= haystack_len - needle_len) {
+ if(!memcmp(haystack + index,needle,needle_len)){
+ return haystack + index;
+ }
+ index++;
+ }
+
+ return NULL;
+}
+
+bool str_empty(const void *str)
+{
+ if (str && strlen((char*)str) > 0)
+ return false;
+
+ return true;
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_task.c b/mbtk/libmbtk_lib/common/mbtk_task.c
new file mode 100755
index 0000000..935369a
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_task.c
@@ -0,0 +1,139 @@
+/*************************************************************
+Description:
+ mbtk_task.c
+ Used to implement mobiletek standard task or thread interfaces
+Author:
+ YangDagang
+Date:
+ 2019-7-13
+*************************************************************/
+#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 "mbtk_type.h"
+#include "mbtk_queue.h"
+#include "mbtk_task.h"
+#include "mbtk_log.h"
+
+/*************************************************************
+ Constants and Macros
+*************************************************************/
+
+/*************************************************************
+ Definitions:enum,struct,union
+*************************************************************/
+
+
+/*************************************************************
+ Variables:local,extern
+*************************************************************/
+
+/*************************************************************
+ Local Function Declaration
+*************************************************************/
+
+/*************************************************************
+ Extern Function Declaration
+*************************************************************/
+
+/*************************************************************
+ Function Definitions
+*************************************************************/
+void mbtk_mutex_init(mbtk_mutex *mutex)
+{
+ pthread_mutex_init(&mutex->crit_sect, NULL);
+}
+
+void mbtk_mutex_deinit(mbtk_mutex *mutex)
+{
+ pthread_mutex_destroy(&mutex->crit_sect);
+}
+
+void mbtk_mutex_lock(mbtk_mutex *mutex)
+{
+ pthread_mutex_lock(&mutex->crit_sect);
+}
+
+void mbtk_mutex_unlock(mbtk_mutex *mutex)
+{
+ pthread_mutex_unlock(&mutex->crit_sect);
+}
+
+int mbtk_task_start(mbtk_task_info *task)
+{
+ static pthread_attr_t thread_attr;
+ pthread_attr_init(&thread_attr);
+ if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+ {
+ LOGE("pthread_attr_setdetachstate() fail.");
+ return -1;
+ }
+
+ if (pthread_create((pthread_t*)task->task_id,
+ &thread_attr, task->thread_run, task->args) != 0)
+ {
+ LOGE("%s errno: %d (%s)",__func__, errno, strerror(errno));
+ return -1;
+ }
+ pthread_attr_destroy(&thread_attr);
+
+ return 0;
+}
+
+int mbtk_task_queue_start(void *param,mbtk_task_cb_handle cb)
+{
+ int res = 0;
+ mbtk_task_queue_info *ts = (mbtk_task_queue_info *)param;
+
+ if(cb == NULL)
+ {
+ return MBTK_FAILE;
+ }
+ mbtk_queue_init(&ts->queue);
+ mbtk_mutex_init(&ts->mutex);
+ pthread_cond_init(&ts->cond, NULL);
+ res = pthread_create(&ts->thread_id,NULL,cb,NULL);
+ usleep(500000);
+ return res;
+}
+
+void mbtk_task_queue_stop(void *param)
+{
+ mbtk_task_queue_info *ts = (mbtk_task_queue_info *)param;
+ pthread_cancel(ts->thread_id);
+}
+
+int mbtk_signal_send(void *param,mbtk_signal_info* info)
+{
+ int res = 0;
+ mbtk_task_queue_info *ts = (mbtk_task_queue_info *)param;
+
+ mbtk_mutex_lock(&ts->mutex);
+ res = mbtk_queue_put(&ts->queue,(void*)info);
+ pthread_cond_signal(&ts->cond);
+ mbtk_mutex_unlock(&ts->mutex);
+ return res;
+}
+
+mbtk_signal_info *mbtk_signal_get(void *param)
+{
+ void *res = NULL;
+ mbtk_task_queue_info *ts = (mbtk_task_queue_info *)param;
+
+ mbtk_mutex_lock(&ts->mutex);
+ res = mbtk_queue_get(&ts->queue);
+ if(res == NULL){
+ // extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
+ // pthread_mutex_t *__restrict __mutex)
+ pthread_cond_wait(&ts->cond, (pthread_mutex_t*)(&ts->mutex));
+ res = mbtk_queue_get(&ts->queue);
+ }
+ mbtk_mutex_unlock(&ts->mutex);
+ return res;
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_utf.c b/mbtk/libmbtk_lib/common/mbtk_utf.c
new file mode 100755
index 0000000..771186d
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_utf.c
@@ -0,0 +1,703 @@
+//
+// Created by hitmoon on 15-12-17.
+//
+#include "mbtk_utf.h"
+#include <stdio.h>
+#include <wchar.h>
+#include <string.h>
+
+static const int halfShift = 10;
+/* used for shifting by 10 bits */
+
+static const UTF32 halfBase = 0x0010000UL;
+static const UTF32 halfMask = 0x3FFUL;
+
+#define UNI_SUR_HIGH_START (UTF32)0xD800
+#define UNI_SUR_HIGH_END (UTF32)0xDBFF
+#define UNI_SUR_LOW_START (UTF32)0xDC00
+#define UNI_SUR_LOW_END (UTF32)0xDFFF
+#define false 0
+#define true 1
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF16(
+ const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF32 *source = *sourceStart;
+ UTF16 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted;
+ break;
+ }
+ ch = *source++;
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16) ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_LEGAL_UTF32) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ --source; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF32(
+ const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF16 *source = *sourceStart;
+ UTF32 *target = *targetStart;
+ UTF32 ch, ch2;
+ while (source < sourceEnd) {
+ const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ if (target >= targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ *target++ = ch;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+#ifdef CVTUTF_DEBUG
+ if (result == sourceIllegal) {
+ fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x/n", ch, ch2);
+ fflush(stderr);
+}
+#endif
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Index into the table below with the first byte of a UTF-8 sequence to
+ * get the number of trailing bytes that are supposed to follow it.
+ * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
+ * left as-is for anyone who may want to do such conversion, which was
+ * allowed in earlier algorithms.
+ */
+static const char trailingBytesForUTF8[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
+};
+
+/*
+ * Magic values subtracted from a buffer value during UTF8 conversion.
+ * This table contains as many values as there might be trailing bytes
+ * in a UTF-8 sequence.
+ */
+static const UTF32 offsetsFromUTF8[6] = {0x00000000UL, 0x00003080UL, 0x000E2080UL,
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL};
+
+/*
+ * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
+ * into the first byte, depending on how many bytes follow. There are
+ * as many entries in this table as there are UTF-8 sequence types.
+ * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
+ * for *legal* UTF-8 will be 4 or fewer bytes total.
+ */
+static const UTF8 firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
+
+/* --------------------------------------------------------------------- */
+
+/* The interface converts a whole buffer to avoid function-call overhead.
+ * Constants have been gathered. Loops & conditionals have been removed as
+ * much as possible for efficiency, in favor of drop-through switches.
+ * (See "Note A" at the bottom of the file for equivalent code.)
+ * If your compiler supports it, the "isLegalUTF8" call can be turned
+ * into an inline function.
+ */
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF16toUTF8(
+ const UTF16 **sourceStart, const UTF16 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF16 *source = *sourceStart;
+ UTF8 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned int bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32) 0x80) {
+ bytesToWrite = 1;
+ } else if (ch < (UTF32) 0x800) {
+ bytesToWrite = 2;
+ } else if (ch < (UTF32) 0x10000) {
+ bytesToWrite = 3;
+ } else if (ch < (UTF32) 0x110000) {
+ bytesToWrite = 4;
+ } else {
+ bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4:
+ *--target = (UTF8) ((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 3:
+ *--target = (UTF8) ((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 2:
+ *--target = (UTF8) ((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Utility routine to tell whether a sequence of bytes is legal UTF-8.
+ * This must be called with the length pre-determined by the first byte.
+ * If not calling this from ConvertUTF8to*, then the length can be set by:
+ * length = trailingBytesForUTF8[*source]+1;
+ * and the sequence is illegal right away if there aren't that many bytes
+ * available.
+ * If presented with a length > 4, this returns false. The Unicode
+ * definition of UTF-8 goes up to 4-byte sequences.
+ */
+
+static Boolean isLegalUTF8(const UTF8 *source, int length) {
+ UTF8 a;
+ const UTF8 *srcptr = source + length;
+ switch (length) {
+ default:
+ return false;
+ /* Everything else falls through when "true"... */
+ case 4:
+ if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 3:
+ if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
+ case 2:
+ if ((a = (*--srcptr)) > 0xBF) return false;
+
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0:
+ if (a < 0xA0) return false;
+ break;
+ case 0xED:
+ if (a > 0x9F) return false;
+ break;
+ case 0xF0:
+ if (a < 0x90) return false;
+ break;
+ case 0xF4:
+ if (a > 0x8F) return false;
+ break;
+ default:
+ if (a < 0x80) return false;
+ }
+
+ case 1:
+ if (*source >= 0x80 && *source < 0xC2) return false;
+ }
+ if (*source > 0xF4) return false;
+ return true;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Exported function to return whether a UTF-8 sequence is legal or not.
+ * This is not used here; it's just exported.
+ */
+Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
+ int length = trailingBytesForUTF8[*source] + 1;
+ if (source + length > sourceEnd) {
+ return false;
+ }
+ return isLegalUTF8(source, length);
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF16(
+ const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF8 *source = *sourceStart;
+ UTF16 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead + 1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5:
+ ch += *source++;
+ ch <<= 6; /* remember, illegal UTF-8 */
+ case 4:
+ ch += *source++;
+ ch <<= 6; /* remember, illegal UTF-8 */
+ case 3:
+ ch += *source++;
+ ch <<= 6;
+ case 2:
+ ch += *source++;
+ ch <<= 6;
+ case 1:
+ ch += *source++;
+ ch <<= 6;
+ case 0:
+ ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead + 1); /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead + 1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16) ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= (extraBytesToRead + 1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ source -= (extraBytesToRead + 1); /* Back up source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16) ((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16) ((ch & halfMask) + UNI_SUR_LOW_START);
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF32toUTF8(
+ const UTF32 **sourceStart, const UTF32 *sourceEnd,
+ UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF32 *source = *sourceStart;
+ UTF8 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ ch = *source++;
+ if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ if (ch < (UTF32) 0x80) {
+ bytesToWrite = 1;
+ } else if (ch < (UTF32) 0x800) {
+ bytesToWrite = 2;
+ } else if (ch < (UTF32) 0x10000) {
+ bytesToWrite = 3;
+ } else if (ch <= UNI_MAX_LEGAL_UTF32) {
+ bytesToWrite = 4;
+ } else {
+ bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ result = sourceIllegal;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ --source; /* Back up source pointer! */
+ target -= bytesToWrite;
+ result = targetExhausted;
+ break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4:
+ *--target = (UTF8) ((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 3:
+ *--target = (UTF8) ((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 2:
+ *--target = (UTF8) ((ch | byteMark) & byteMask);
+ ch >>= 6;
+ case 1:
+ *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* --------------------------------------------------------------------- */
+
+ConversionResult ConvertUTF8toUTF32(
+ const UTF8 **sourceStart, const UTF8 *sourceEnd,
+ UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) {
+ ConversionResult result = conversionOK;
+ const UTF8 *source = *sourceStart;
+ UTF32 *target = *targetStart;
+ while (source < sourceEnd) {
+ UTF32 ch = 0;
+ int extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted;
+ break;
+ }
+ /* Do this check whether lenient or strict */
+ if (!isLegalUTF8(source, extraBytesToRead + 1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5:
+ ch += *source++;
+ ch <<= 6;
+ case 4:
+ ch += *source++;
+ ch <<= 6;
+ case 3:
+ ch += *source++;
+ ch <<= 6;
+ case 2:
+ ch += *source++;
+ ch <<= 6;
+ case 1:
+ ch += *source++;
+ ch <<= 6;
+ case 0:
+ ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
+
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead + 1); /* Back up the source pointer! */
+ result = targetExhausted;
+ break;
+ }
+ if (ch <= UNI_MAX_LEGAL_UTF32) {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead + 1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = ch;
+ }
+ } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+ result = sourceIllegal;
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ }
+ *sourceStart = source;
+ *targetStart = target;
+ return result;
+}
+
+/* ---------------------------------------------------------------------
+
+ Note A.
+ The fall-through switches in UTF-8 reading code save a
+ temp variable, some decrements & conditionals. The switches
+ are equivalent to the following loop:
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
+ In UTF-8 writing code, the switches on "bytesToWrite" are
+ similarly unrolled loops.
+
+ --------------------------------------------------------------------- */
+
+const unsigned char *utf32toutf8(wchar_t *source, unsigned char *target, size_t size, int *len){
+
+ wchar_t *s_start;
+ unsigned char *t_start;
+
+ s_start = source;
+ t_start = target;
+
+ if (ConvertUTF32toUTF8((const UTF32**) &s_start, (UTF32*)s_start + wcslen(source), (UTF8**)&t_start, (UTF8*)t_start + size, strictConversion) == conversionOK) {
+ *len = t_start - target;
+ }
+ else {
+ *len = 0;
+ }
+ target[*len] = '\0';
+ return (const unsigned char*)target;
+}
+
+
+unsigned char *utf16toutf8(unsigned short *source, unsigned char *target, size_t size, int *len){
+
+ unsigned short *s_start;
+ unsigned char *t_start;
+
+ s_start = source;
+ t_start = target;
+
+ if (ConvertUTF16toUTF8((const UTF16**) &s_start, (UTF16*)s_start + strlen((const char*)source) / 2, (UTF8**)&t_start, (UTF8*)t_start + size, strictConversion) == conversionOK) {
+ *len = t_start - target;
+ }
+ else {
+ *len = 0;
+ }
+ target[*len] = '\0';
+ return target;
+}
+
+unsigned short *utf8toutf16(unsigned char *source, unsigned short *target, size_t size, int *len)
+{
+ unsigned char *s_start;
+ unsigned short *t_start;
+
+ s_start = source;
+ t_start = target;
+
+ if (ConvertUTF8toUTF16((const UTF8 **)&s_start, s_start + strlen((const char*)source), &t_start, t_start + size, strictConversion) == conversionOK) {
+ *len = t_start - target;
+ }
+ else {
+ *len = 0;
+ }
+
+ return target;
+}
+
+u_int32_t next_char(unsigned char **string) {
+
+ int len = strlen((const char*)*string);
+ unsigned char ch[4];
+ int i = 0;
+
+ if (len < 4){
+ for (i = 0; i < len; i++)
+ ch[i] = (*string)[i];
+ }
+ else {
+ ch[0] = (*string)[0];
+ ch[1] = (*string)[1];
+ ch[2] = (*string)[2];
+ ch[3] = (*string)[3];
+ }
+
+ if(ch[0] < 0x80) {
+ *string = (*string + 1);
+ return ch[0];
+ }
+ else if (ch[0] >= 0xc0 && ch[0] <= 0xdf) {
+ *string = (*string + 2);
+ return ch[1] << 8 | ch[0];
+ }
+ else if (ch[0] >= 0xe0 && ch[0] <= 0xef) {
+ *string = (*string + 3);
+ return ch[2] << 16 | ch[1] << 8 | ch[0];
+ }
+ else if (ch[0] >= 0xf0 && ch[0] <= 0xf7) {
+ *string = (*string + 4);
+ return ch[3] << 24 | ch[2] << 16 | ch[1] << 8 | ch[0];
+ }
+
+ return *(u_int32_t*)ch;
+}
+
+
+int utf8len(unsigned char *string)
+{
+ unsigned char *end;
+ int ret = 0;
+
+ end = string + strlen((const char*)string);
+ while(string < end) {
+ next_char(&string);
+ ret++;
+ }
+ return ret;
+}
+
+int is_acsii(unsigned char *string)
+{
+ while(*string) {
+ if (*string >= 0x80)
+ return 0;
+ string++;
+ }
+ return 1;
+}
+
+size_t utf8_get_size(unsigned char *source, size_t num)
+{
+ size_t ret = 0;
+
+ unsigned char *cur = source;
+ while (num-- && *cur) {
+ next_char(&cur);
+ }
+ ret = cur - source;
+
+ return ret;
+}
diff --git a/mbtk/libmbtk_lib/common/mbtk_utils.c b/mbtk/libmbtk_lib/common/mbtk_utils.c
new file mode 100755
index 0000000..fe4d716
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_utils.c
@@ -0,0 +1,569 @@
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/types.h>
+
+#include "mbtk_type.h"
+#include "mbtk_utils.h"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "mbtk_utils"
+#include "mbtk_log.h"
+
+#define MBTK_AT_BUF_SIZE 2048
+#define MBTK_AT_CLIENT_SOCKET "/data/sock_mbtk_at"
+#define PROC_CMDLINE "/proc/cmdline"
+#define TIME_FORMAT "%F %T"
+
+static int at_fd = -1;
+static bool at_timeout = FALSE;
+
+static void
+at_timer_alrm(int signo)
+{
+ LOGW("AT Timeout.[%d]\n",signo);
+ at_timeout = TRUE;
+}
+
+
+/*
+* Exec shell command.
+*/
+bool mbtk_cmd_line
+(
+ const char *cmd,
+ char *buf,
+ int buf_size
+)
+{
+ FILE *fcmd;
+ bool result = FALSE;
+ fcmd = popen(cmd, "r");
+ memset(buf, 0, buf_size);
+ if(fcmd)
+ {
+ int pos = 0;
+ int len = 0;
+
+ while(!ferror(fcmd) && !feof(fcmd))
+ {
+ if(buf_size - pos == 0)
+ {
+ break;
+ }
+ len = fread(buf + pos,1,buf_size - pos,fcmd);
+ if(len > 0)
+ pos += len;
+ }
+
+ if(buf_size == pos)
+ buf[buf_size - 1] = '\0';
+
+ pclose(fcmd);
+ result = TRUE;
+ }
+
+ LOGV("%s [result:%d]: %s",cmd,result,buf);
+
+ return result;
+}
+
+bool mbtk_cmd_line_ex
+(
+ const char *cmd,
+ mbtk_cmd_cb_func cb
+)
+{
+#define BUFF_SIZE 1024
+ FILE *fcmd;
+ bool result = FALSE;
+ // Get stdout and stderr data.
+ // xxx 2>&1
+ char buff[BUFF_SIZE + 1] = {0};
+ snprintf(buff, BUFF_SIZE + 1, "%s 2>&1", cmd);
+ fcmd = popen(buff, "r");
+ if(!cb)
+ {
+ return FALSE;
+ }
+ if(fcmd)
+ {
+ int len = 0;
+ if(setvbuf(fcmd, NULL, _IOLBF, BUFF_SIZE)) {
+ LOGE("setvbuf() fail:%d", errno);
+ }
+ errno = 0;
+ LOGI("ferror - %d,feof - %d",ferror(fcmd),feof(fcmd));
+ while(!ferror(fcmd) && !feof(fcmd))
+ {
+ memset(buff, 0, BUFF_SIZE + 1);
+ len = fread(buff,1,BUFF_SIZE,fcmd);
+ if(len > 0)
+ {
+ cb(buff,len);
+ }
+ else
+ {
+ LOGE("len - %d,errno - %d",len,errno);
+ }
+ }
+
+ pclose(fcmd);
+ result = TRUE;
+
+ cb(NULL,0);
+ }
+ else
+ {
+ LOGE("popen() fail.[errno=%d]",errno);
+ cb(NULL,0);
+ }
+
+ return result;
+}
+
+
+
+#if 1
+// Send msg to stanet_daemon
+int mbtk_send_at(const void *at_req,void* at_rsp,int rsp_size,int timeout)
+{
+ if(at_fd < 0)
+ {
+ struct sockaddr_un servaddr;
+ at_fd = socket(AF_LOCAL,SOCK_STREAM,0);
+ if(at_fd < 0)
+ {
+ LOGE("socket fail.(%d)\n",errno);
+ at_fd = -1;
+ return -1;
+ }
+
+ // Set O_NONBLOCK
+// int flags = fcntl(at_fd, F_GETFL, 0);
+// if (flags < 0) {
+// LOGE("Get flags error:%s\n", strerror(errno));
+// return -1;
+// }
+// flags |= O_NONBLOCK;
+// if (fcntl(at_fd, F_SETFL, flags) < 0) {
+// LOGE("Set flags error:%s\n", strerror(errno));
+// return -1;
+// }
+
+ memset(&servaddr,0x0,sizeof(servaddr));
+ servaddr.sun_family = AF_LOCAL;
+ strcpy(servaddr.sun_path,MBTK_AT_CLIENT_SOCKET);
+
+ if(connect(at_fd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
+ {
+ LOGE("connect fail.(%d)\n",errno);
+ close(at_fd);
+ at_fd = -1;
+ return -1;
+ }
+ }
+
+ at_timeout = FALSE;
+ int n = write(at_fd,at_req,strlen((char*)at_req));
+ if(n == -1)
+ {
+ LOGE("write fail[%d].\n",errno);
+ close(at_fd);
+ at_fd = -1;
+ return -1;
+ }
+
+ // Set timer
+ signal(SIGALRM, at_timer_alrm);
+ struct itimerval val;
+ // Only time
+ val.it_interval.tv_sec = 0;
+ val.it_interval.tv_usec = 0;
+ // Time
+ if(timeout >= 1000)
+ {
+ val.it_value.tv_sec = timeout/1000;
+ val.it_value.tv_usec = timeout%1000;
+ }
+ else
+ {
+ val.it_value.tv_sec = 0;
+ val.it_value.tv_usec = timeout;
+ }
+ if (setitimer(ITIMER_REAL, &val, NULL) == -1)
+ {
+ LOGE("setitimer fail.[%d]",errno);
+ return -1;
+ }
+
+ memset(at_rsp,0x0,rsp_size);
+ while(!at_timeout)
+ {
+ n = read(at_fd,at_rsp,rsp_size);
+ if(n < 0)
+ {
+ if(errno == EWOULDBLOCK)
+ {
+ usleep(50000);
+ continue;
+ }
+ else
+ {
+ LOGW("read error.[%d]",errno);
+ break;
+ }
+ }
+ else if (n > 0)
+ {
+ LOGI("RSP:%s",(char*)at_rsp);
+ break;
+ }
+ else
+ {
+ LOGW("read error.[%d]",errno);
+ break;
+ }
+ }
+
+ val.it_value.tv_sec = 0;
+ val.it_value.tv_usec = 0;
+ val.it_interval = val.it_value;
+ setitimer(ITIMER_REAL, &val, NULL);
+
+ if(n > 0)
+ return 0;
+
+ return -1;
+}
+#else
+int mbtk_send_at(const void *at_req,void* at_rsp,int rsp_size,int timeout)
+{
+ if(!at_req || !at_rsp || rsp_size <= 0)
+ {
+ LOGE("ARG error.");
+ return -1;
+ }
+
+ // Return "ERROR" if AT fail.
+ const char* result = sendCmd(0,(const char*)at_req);
+ memset(at_rsp,0x0,rsp_size);
+ snprintf(at_rsp,rsp_size,"%s",result);
+
+ return 0;
+}
+#endif
+
+/*
+* Set timer as microseconds.
+*/
+int mbtk_timer_set(mbtk_timer_alrm_func func,uint32 timeout_ms)
+{
+ signal(SIGALRM, func);
+ struct itimerval val;
+ // Only time
+ val.it_interval.tv_sec = 0;
+ val.it_interval.tv_usec = 0;
+ // Time
+ if(timeout_ms >= 1000)
+ {
+ val.it_value.tv_sec = timeout_ms/1000;
+ val.it_value.tv_usec = timeout_ms%1000;
+ }
+ else
+ {
+ val.it_value.tv_sec = 0;
+ val.it_value.tv_usec = timeout_ms;
+ }
+ if (setitimer(ITIMER_REAL, &val, NULL) == -1)
+ {
+ LOGE("setitimer fail.[errno - %d]",errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+* Clear current timer.
+*/
+int mbtk_timer_clear()
+{
+ struct itimerval value;
+ value.it_value.tv_sec = 0;
+ value.it_value.tv_usec = 0;
+ value.it_interval = value.it_value;
+ if (setitimer(ITIMER_REAL, &value, NULL) == -1)
+ {
+ LOGE("setitimer fail.[errno - %d]",errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* MRD still need to read /proc/cmdline after we drop root permission,
+ * so cache it in this function */
+int mbtk_get_kernel_cmdline(char *buf, int len)
+{
+ static char cmdline[MBTK_CMDLINE_LEN];
+ static int is_init = 0;
+ int ret = -1;
+ int fd;
+
+ if(!buf || len <= 0) return -1;
+
+ if(is_init)
+ goto INITED;
+
+ fd = open(PROC_CMDLINE, O_RDONLY);
+ if (fd < 0)
+ goto ERR_RET;
+
+ ret = read(fd, cmdline, MBTK_CMDLINE_LEN);
+ close(fd);
+
+ if(ret <= 0 || ret > MBTK_CMDLINE_LEN)
+ goto ERR_RET;
+ cmdline[ret - 1] = '\0';
+
+INITED:
+ ret = strlen(cmdline) + 1;
+ if(ret > len)
+ ret = len;
+
+ strncpy(buf, cmdline, ret);
+ buf[ret - 1] = '\0';
+
+ is_init = 1;
+
+ return ret;
+
+ERR_RET:
+ return -1;
+}
+
+/** returns 1 if line starts with prefix, 0 if it does not */
+int strStartsWith(const char *line, const char *prefix)
+{
+ if(prefix == NULL || strlen(prefix) == 0) {
+ return 1;
+ }
+
+ for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) {
+ if (*line != *prefix) {
+ return 0;
+ }
+ }
+
+ return *prefix == '\0';
+}
+
+char* mbtk_time_text_get(char *buff, size_t buff_size)
+{
+ long now_nsec = 0;
+ if(buff == NULL || buff_size <= 0) {
+ return NULL;
+ }
+ memset(buff, 0x0, buff_size);
+#if 0
+ time_t now;
+ now = time(&now);
+ if(now == -1) {
+ LOGE("time() fail.");
+ return NULL;
+ }
+ struct tm *now_tm = gmtime(&now);
+#else
+ struct timespec now;
+ if(-1 == clock_gettime(CLOCK_REALTIME, &now)) {
+ LOGE("clock_gettime() fail.");
+ return NULL;
+ }
+
+ struct tm *now_tm = gmtime((time_t*)(&(now.tv_sec)));
+ now_nsec = now.tv_nsec;
+#endif
+
+ if(now_tm == NULL) {
+ LOGE("gmtime() fail.");
+ return NULL;
+ }
+
+ if(0 == strftime(buff, buff_size, TIME_FORMAT, now_tm)) {
+ LOGE("strftime() fail.");
+ return NULL;
+ }
+
+ snprintf(buff + strlen(buff), buff_size - strlen(buff),
+ "-%03ld", now_nsec / 1000000);
+
+ return buff;
+}
+
+mbtk_byteorder_enum mbtk_byteorder_get()
+{
+ union {
+ short a;
+ char c[sizeof(short)];
+ } un;
+ un.a = 0x0102;
+ if(sizeof(short) == 2) {
+ if(un.c[0] == 1 && un.c[1] == 2) {
+ return MBTK_BYTEORDER_BIG;
+ } else if(un.c[0] == 2 && un.c[1] == 1) {
+ return MBTK_BYTEORDER_LITTLE;
+ } else {
+ return MBTK_BYTEORDER_UNKNOWN;
+ }
+ } else {
+ LOGE("Unknown byte order.");
+ return MBTK_BYTEORDER_UNKNOWN;
+ }
+}
+
+uint16 byte_2_uint16(const void *buff, bool big_endian)
+{
+ const uint8* ptr = (const uint8*)buff;
+ if(big_endian) {
+ return (uint16)((ptr[0] << 8) | ptr[1]);
+ } else {
+ return (uint16)((ptr[1] << 8) | ptr[0]);
+ }
+}
+
+int uint16_2_byte(uint16 a, void *buff, bool big_endian)
+{
+ uint8* ptr = (uint8*)buff;
+ if(big_endian) {
+ ptr[0] = (uint8)(a >> 8);
+ ptr[1] = (uint8)a;
+ } else {
+ ptr[1] = (uint8)(a >> 8);
+ ptr[0] = (uint8)a;
+ }
+ return sizeof(uint16);
+}
+
+uint32 byte_2_uint32(const void *buff, bool big_endian)
+{
+ const uint8* ptr = (const uint8*)buff;
+ if(big_endian) {
+ return (uint32)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]);
+ } else {
+ return (uint32)((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]);
+ }
+}
+
+int uint32_2_byte(uint32 a, void *buff, bool big_endian)
+{
+ uint8* ptr = (uint8*)buff;
+ if(big_endian) {
+ ptr[0] = (uint8)(a >> 24);
+ ptr[1] = (uint8)(a >> 16);
+ ptr[2] = (uint8)(a >> 8);
+ ptr[3] = (uint8)a;
+ } else {
+ ptr[3] = (uint8)(a >> 24);
+ ptr[2] = (uint8)(a >> 16);
+ ptr[1] = (uint8)(a >> 8);
+ ptr[0] = (uint8)a;
+ }
+ return sizeof(uint32);
+}
+
+uint64 byte_2_uint64(const void *buff, bool big_endian)
+{
+ const uint8* ptr = (const uint8*)buff;
+ if(big_endian) {
+ return (uint64)(((uint64)ptr[0] << 56) | ((uint64)ptr[1] << 48) | ((uint64)ptr[2] << 40) | ((uint64)ptr[3] << 32) | (ptr[4] << 24) | (ptr[5] << 16) | (ptr[6] << 8) | ptr[7]);
+ } else {
+ return (uint64)(uint64)(((uint64)ptr[7] << 56) | ((uint64)ptr[6] << 48) | ((uint64)ptr[5] << 40) | ((uint64)ptr[4] << 32) | (ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]);
+ }
+}
+
+int uint64_2_byte(uint64 a, void *buff, bool big_endian)
+{
+ uint8* ptr = (uint8*)buff;
+ if(big_endian) {
+ ptr[0] = (uint8)(a >> 56);
+ ptr[1] = (uint8)(a >> 48);
+ ptr[2] = (uint8)(a >> 40);
+ ptr[3] = (uint8)(a >> 32);
+ ptr[4] = (uint8)(a >> 24);
+ ptr[5] = (uint8)(a >> 16);
+ ptr[6] = (uint8)(a >> 8);
+ ptr[7] = (uint8)a;
+ } else {
+ ptr[7] = (uint8)(a >> 56);
+ ptr[6] = (uint8)(a >> 48);
+ ptr[5] = (uint8)(a >> 40);
+ ptr[4] = (uint8)(a >> 32);
+ ptr[3] = (uint8)(a >> 24);
+ ptr[2] = (uint8)(a >> 16);
+ ptr[1] = (uint8)(a >> 8);
+ ptr[0] = (uint8)a;
+ }
+ return sizeof(uint64);
+}
+
+void* memdup(const void* data, int data_len)
+{
+ if(data && data_len > 0)
+ {
+ uint8* result = (uint8*)malloc(data_len);
+ if(result == NULL)
+ {
+ return NULL;
+ }
+ memcpy(result, data, data_len);
+ return result;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+int app_already_running(const char *pid_file)
+{
+ int fd;
+ char buff[16];
+
+ fd = open(pid_file, O_RDWR | O_CREAT, 0644);
+ if(fd < 0) {
+ LOGE("Open %s fail:%d", pid_file, errno);
+ exit(1);
+ }
+
+ if(flock(fd, LOCK_EX | LOCK_NB)) {
+ if(EWOULDBLOCK == errno) {
+ LOGE("%s is running.", pid_file);
+ exit(1);
+ } else {
+ close(fd);
+ return 1;
+ }
+ }
+
+ ftruncate(fd, 0);
+ sprintf(buff, "%ld", (long)getpid());
+ write(fd, buff, strlen(buff) + 1);
+ return 0;
+}
+
diff --git a/mbtk/libmbtk_lib/common/mbtk_version.c b/mbtk/libmbtk_lib/common/mbtk_version.c
new file mode 100755
index 0000000..a144c93
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/mbtk_version.c
@@ -0,0 +1,130 @@
+/*
+* mbtk_version.c
+*
+* mbtk_source compilation informations.
+*
+*/
+/******************************************************************************
+
+ EDIT HISTORY FOR FILE
+
+ WHEN WHO WHAT,WHERE,WHY
+-------- -------- -------------------------------------------------------
+2024/6/7 LiuBin Initial version
+
+******************************************************************************/
+#include "mbtk_version.h"
+#include "mbtk_log.h"
+
+#define STR_GET(str) (#str)
+
+static mbtk_build_def_info_t def_infos[MBTK_BUILD_DEF_NUM];
+static bool inited = FALSE;
+
+static void def_item_set(mbtk_build_define_enum def_id, char *name, char *value)
+{
+ switch(def_id)
+ {
+ case MBTK_BUILD_DEF_AF_SUPPORT:
+ {
+ strcpy(name, STR_GET(MBTK_BUILD_DEF_AF_SUPPORT));
+#ifdef MBTK_AF_SUPPORT
+ strcpy(value, "Y");
+#else
+ strcpy(value, "N");
+#endif
+ break;
+ }
+ case MBTK_BUILD_DEF_YX_SUPPORT:
+ {
+ strcpy(name, STR_GET(MBTK_BUILD_DEF_YX_SUPPORT));
+#ifdef MBTK_YX_SUPPORT
+ strcpy(value, "Y");
+#else
+ strcpy(value, "N");
+#endif
+ break;
+ }
+ case MBTK_BUILD_DEF_SG_SUPPORT:
+ {
+ strcpy(name, STR_GET(MBTK_BUILD_DEF_SG_SUPPORT));
+#ifdef MBTK_SG_SUPPORT
+ strcpy(value, "Y");
+#else
+ strcpy(value, "N");
+#endif
+ break;
+ }
+ case MBTK_BUILD_DEF_MBTK_ALL_CID_SUPPORT:
+ {
+ strcpy(name, STR_GET(MBTK_BUILD_DEF_MBTK_ALL_CID_SUPPORT));
+#ifdef MBTK_ALL_CID_SUPPORT
+ strcpy(value, "Y");
+#else
+ strcpy(value, "N");
+#endif
+ break;
+ }
+ case MBTK_BUILD_DEF_MBTK_GNSS_MODE:
+ {
+ strcpy(name, STR_GET(MBTK_BUILD_DEF_MBTK_GNSS_MODE));
+#if defined(MBTK_GNSS_6228)
+ strcpy(value, "6228");
+#elif defined(MBTK_GNSS_5311)
+ strcpy(value, "5311");
+#else
+ strcpy(value, "Unknown");
+#endif
+ break;
+ }
+ case MBTK_BUILD_DEF_MBTK_DUMP_SUPPORT:
+ {
+ strcpy(name, STR_GET(MBTK_BUILD_DEF_MBTK_DUMP_SUPPORT));
+#ifdef MBTK_DUMP_SUPPORT
+ strcpy(value, "Y");
+#else
+ strcpy(value, "N");
+#endif
+ break;
+ }
+ default:
+ {
+ strcpy(name, "Unknown");
+ strcpy(value, "Unknown");
+ break;
+ }
+ }
+}
+
+static void def_info_reset()
+{
+ if(!inited) {
+ int index = 0;
+ while(index < MBTK_BUILD_DEF_NUM) {
+ memset(&(def_infos[index]), 0, sizeof(mbtk_build_def_info_t));
+ def_item_set(index, def_infos[index].name, def_infos[index].value);
+ index++;
+ }
+ inited = TRUE;
+ }
+}
+
+void mbtk_build_def_get(char *buff, int buff_len)
+{
+ if(buff && buff_len > 0) {
+ def_info_reset();
+
+ int len = 0;
+ int index = 0;
+ while(index < MBTK_BUILD_DEF_NUM) {
+ len += snprintf(buff + len, buff_len - len, "%s:%s\n", def_infos[index].name, def_infos[index].value);
+ index++;
+ }
+ }
+}
+
+void mbtk_lib_info_print()
+{
+ MBTK_SOURCE_INFO_PRINT("mbtk_lib");
+}
+
diff --git a/mbtk/libmbtk_lib/common/ringbuffer.c b/mbtk/libmbtk_lib/common/ringbuffer.c
new file mode 100755
index 0000000..d5225cc
--- /dev/null
+++ b/mbtk/libmbtk_lib/common/ringbuffer.c
@@ -0,0 +1,90 @@
+#include "ringbuffer.h"
+
+/**
+ * @file
+ * Implementation of ring buffer functions.
+ */
+
+void ring_buffer_init(ring_buffer_t *buffer, char *buf, size_t buf_size) {
+ RING_BUFFER_ASSERT(RING_BUFFER_IS_POWER_OF_TWO(buf_size) == 1);
+ buffer->buffer = buf;
+ buffer->buffer_mask = buf_size - 1;
+ buffer->tail_index = 0;
+ buffer->head_index = 0;
+}
+
+void ring_buffer_queue(ring_buffer_t *buffer, char data) {
+ /* Is buffer full? */
+ if(ring_buffer_is_full(buffer)) {
+ /* Is going to overwrite the oldest byte */
+ /* Increase tail index */
+ buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK(buffer));
+ }
+
+ /* Place data in buffer */
+ buffer->buffer[buffer->head_index] = data;
+ buffer->head_index = ((buffer->head_index + 1) & RING_BUFFER_MASK(buffer));
+}
+
+void ring_buffer_queue_arr(ring_buffer_t *buffer, const char *data, ring_buffer_size_t size) {
+ /* Add bytes; one by one */
+ ring_buffer_size_t i;
+ for(i = 0; i < size; i++) {
+ ring_buffer_queue(buffer, data[i]);
+ }
+}
+
+uint8_t ring_buffer_dequeue(ring_buffer_t *buffer, char *data) {
+ if(ring_buffer_is_empty(buffer)) {
+ /* No items */
+ return 0;
+ }
+
+ *data = buffer->buffer[buffer->tail_index];
+ buffer->tail_index = ((buffer->tail_index + 1) & RING_BUFFER_MASK(buffer));
+ return 1;
+}
+
+ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *buffer, char *data, ring_buffer_size_t len) {
+ if(ring_buffer_is_empty(buffer)) {
+ /* No items */
+ return 0;
+ }
+
+ char *data_ptr = data;
+ ring_buffer_size_t cnt = 0;
+ while((cnt < len) && ring_buffer_dequeue(buffer, data_ptr)) {
+ cnt++;
+ data_ptr++;
+ }
+ return cnt;
+}
+
+uint8_t ring_buffer_peek(ring_buffer_t *buffer, char *data, ring_buffer_size_t index) {
+ if(index >= ring_buffer_num_items(buffer)) {
+ /* No items at index */
+ return 0;
+ }
+
+ /* Add index to pointer */
+ ring_buffer_size_t data_index = ((buffer->tail_index + index) & RING_BUFFER_MASK(buffer));
+ *data = buffer->buffer[data_index];
+ return 1;
+}
+
+uint8_t ring_buffer_is_empty(ring_buffer_t *buffer) {
+ return (buffer->head_index == buffer->tail_index);
+}
+
+uint8_t ring_buffer_is_full(ring_buffer_t *buffer) {
+ return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK(buffer)) == RING_BUFFER_MASK(buffer);
+}
+
+ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *buffer) {
+ return ((buffer->head_index - buffer->tail_index) & RING_BUFFER_MASK(buffer));
+}
+
+void ring_buffer_clean(ring_buffer_t *buffer) {
+ buffer->tail_index = 0;
+ buffer->head_index = 0;
+}