Add mbtk_gnssd
Change-Id: I2e3bc0b7c9cc310c04a4fbcbe809c525b0cfafbe
diff --git a/build.sh b/build.sh
index 8c9f438..4991331 100755
--- a/build.sh
+++ b/build.sh
@@ -127,6 +127,7 @@
[ -f out/bin/mtd_info ] && cp -f out/bin/mtd_info $1/bin
[ -f out/bin/mbtk_sdk_ready ] && cp -f out/bin/mbtk_sdk_ready $1/bin
[ -f out/bin/mbtk_reboot ] && cp -f out/bin/mbtk_reboot $1/bin
+ [ -f out/bin/mbtk_gnssd ] && cp -f out/bin/mbtk_gnssd $1/bin
}
function file_copy()
diff --git a/mbtk/Makefile b/mbtk/Makefile
index 79902be..d9e355f 100755
--- a/mbtk/Makefile
+++ b/mbtk/Makefile
@@ -9,7 +9,7 @@
DIRS += libql_lib liblynq_lib
# Build bin file.
-DIRS += mbtk_adbd mbtk_rild mbtk_logd mbtk_utils mbtk_utils_linux mbtk_sdk_ready
+DIRS += mbtk_adbd mbtk_rild mbtk_logd mbtk_utils mbtk_utils_linux mbtk_sdk_ready mbtk_gnssd
# Build test file.
DIRS += test
diff --git a/mbtk/mbtk_gnssd/Makefile b/mbtk/mbtk_gnssd/Makefile
new file mode 100755
index 0000000..e1735ff
--- /dev/null
+++ b/mbtk/mbtk_gnssd/Makefile
@@ -0,0 +1,47 @@
+BUILD_ROOT = $(shell pwd)/..
+include $(BUILD_ROOT)/Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/mbtk_gnssd
+
+INC_DIR += \
+ -I$(LOCAL_PATH) \
+ -I$(BUILD_ROOT)/libmbtk_ril
+
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lmbtk_net -lmbtk_ril -lrilutil -lprop2uci -lmtel -laudio-apu -lcutils -ltinyalsa -lacm -lubus -lubox
+
+CFLAGS +=
+
+DEFINE +=
+
+#MY_FILES_PATH:=$(LOCAL_PATH)
+#ifeq ($(CONFIG_MBTK_QL_SUPPORT),y)
+#MY_FILES_PATH += $(LOCAL_PATH)/ql
+#endif
+
+#ifeq ($(CONFIG_MBTK_PLATFORM),linux)
+#MY_FILES_PATH += $(LOCAL_PATH)/platform/linux
+#endif
+#LOCAL_SRC_FILES = $(wildcard *.c) $(wildcard *.cpp)
+LOCAL_SRC_FILES = gnss_main.c gnss_nmea.c gnss_6228.c gnss_ubus.c gnss_utils.c
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+dtarget := $(OUT_DIR)/bin/mbtk_gnssd
+
+all: $(dtarget)
+
+$(dtarget): $(OBJS)
+ @echo " BIN $@"
+ $(CC) $(CFLAGS) $(LIB_DIR) $(LIBS) $(OBJS) -o $@
+
+%.o:%.c
+ $(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+ $(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+ rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/mbtk_gnssd/gnss_6228.c b/mbtk/mbtk_gnssd/gnss_6228.c
new file mode 100755
index 0000000..2cd86a4
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_6228.c
Binary files differ
diff --git a/mbtk/mbtk_gnssd/gnss_6228.h b/mbtk/mbtk_gnssd/gnss_6228.h
new file mode 100755
index 0000000..3a2a41f
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_6228.h
@@ -0,0 +1,39 @@
+/*
+* gnss_6228.h
+*
+* UC6228CI Header.
+*
+* Author : lb
+* Date : 2024/5/20 17:53:51
+*/
+#ifndef _GNSS_6228_H
+#define _GNSS_6228_H
+#include "gnss_info.h"
+#include "mbtk_type.h"
+
+typedef struct {
+ char pdtName[32];
+ char Config[32];
+ char hwVer[32];
+ char fwVer[64];
+ char PN[64];
+ char SN[64];
+} gnss_6228_dev_info_t;
+
+int gnss_6228_dev_open();
+
+int gnss_6228_dev_close();
+
+int gnss_6228_open();
+
+int gnss_6228_close();
+
+int gnss_6228_fw_dl();
+
+void gnss_6228_dl_read_cb(const void *data, int data_len);
+
+gnss_err_enum gnss_6228_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len);
+
+void gnss_6228_set_cb(const void *data, int data_len);
+
+#endif /* _GNSS_6228_H */
diff --git a/mbtk/mbtk_gnssd/gnss_info.h b/mbtk/mbtk_gnssd/gnss_info.h
new file mode 100755
index 0000000..0e7d4fa
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_info.h
@@ -0,0 +1,75 @@
+/*
+* gnss_info.h
+*
+* GNSS informations header.
+*
+* Author : lb
+* Date : 2024/5/20 15:22:46
+*/
+#ifndef _GNSS_INFO_H
+#define _GNSS_INFO_H
+#include "mbtk_type.h"
+
+#define GNSS_ID_6228 "6228"
+#define GNSS_ID_5311 "5311"
+
+#define GNSS_PRINT_PORT_UART1 1 // 1
+#define GNSS_PRINT_PORT_USB_NMEA (1<<1) // 2
+#define GNSS_PRINT_PORT_USB_AT (1<<2) // 4
+#define GNSS_PRINT_PORT_TTY_AT (1<<3) // 8
+
+typedef enum {
+ GNSS_ERR_OK,
+ GNSS_ERR_UNSUPPORT,
+ GNSS_ERR_TIMEOUT,
+ GNSS_ERR_ARG,
+ GNSS_ERR_CHECKSUM,
+
+ GNSS_ERR_UNKNOWN
+} gnss_err_enum;
+
+typedef int (*gnss_dev_open_func)();
+typedef int (*gnss_dev_close_func)();
+typedef int (*gnss_open_func)(const char *dev);
+typedef int (*gnss_close_func)(int fd);
+typedef int (*gnss_fw_dl_func)(int fd);
+typedef void (*gnss_dl_read_cb_func)(const void *data, int data_len);
+typedef gnss_err_enum (*gnss_set_func)(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len);
+typedef void (*gnss_set_cb_func)(const void *data, int data_len);
+
+typedef enum {
+ GNSS_TYPE_6228 = 0,
+ GNSS_TYPE_5311,
+} gnss_id_enum;
+
+typedef enum {
+ GNSS_STATE_CLOSE, // GNSS is closed.
+ GNSS_STATE_CLOSING, // GNSS is closing.
+ GNSS_STATE_OPEN, // GNSS is opened.
+ GNSS_STATE_DOWNLOAD, // GNSS is downloading.
+ GNSS_STATE_READY, // GNSS is ready.
+} gnss_state_enum;
+
+typedef struct {
+ gnss_id_enum gnss_id;
+ char dev_name[32];
+ bool auto_open; // Should auto open gnss?
+ bool auto_dl_fw; // Should download firmware int the first?
+ int fd; // GNSS uart fd.
+ int exit_fd[2]; // Use to exit thread.
+ gnss_state_enum state;
+ uint32 print_port;
+ pthread_t read_pid; // Read NMEA thread.
+
+ // GNSS functions.
+ gnss_dev_open_func gnss_dev_open;
+ gnss_dev_close_func gnss_dev_close;
+ gnss_open_func gnss_open;
+ gnss_close_func gnss_close;
+ gnss_fw_dl_func gnss_fw_dl;
+ gnss_dl_read_cb_func gnss_dl_read_cb;
+ gnss_set_func gnss_set;
+ gnss_set_cb_func gnss_set_cb;
+} gnss_info_t;
+
+#endif /* _GNSS_INFO_H */
diff --git a/mbtk/mbtk_gnssd/gnss_main.c b/mbtk/mbtk_gnssd/gnss_main.c
new file mode 100755
index 0000000..0127a03
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_main.c
@@ -0,0 +1,753 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <libubox/ustream.h>
+#include <libubus.h>
+#include <signal.h>
+#include <cutils/properties.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+#include "gnss_info.h"
+
+#include "gnss_6228.h"
+
+#define GNSS_DEBUG 1
+
+#define GNSS_TAG "MBTK_GNSS"
+#define GNSS_BUFF_SIZE 2048
+#define MBTK_PROP_GNSS_LOG "persist.mbtk.gnss_log_enable"
+#define GNSS_PORT_PTY "/dev/tty_gnss_nmea"
+#define GNSS_PORT_USB_AT "/dev/ttyGS0"
+#define GNSS_PORT_USB_NMEA "/dev/ttymodem0"
+#define GNSS_PORT_UART_AT "/dev/ttyS1"
+
+#ifdef GNSS_DEBUG
+#define GNSS_NMEA_FILE_LOG "/tmp/mbtk_gnss_nmea.log"
+#define GNSS_NMEA_FILE_LOG_MAX 10485760 // 10MB
+
+#define GNSS_FILE_LOG "/tmp/mbtk_gnss.log"
+#define GNSS_FILE_LOG_MAX 10485760 // 10MB
+#endif
+
+gnss_info_t gnss_info;
+
+struct ubus_context *gnss_ubus_init(void);
+int gnss_init_config(int fd);
+
+static char gnss_buff[GNSS_BUFF_SIZE*2] = {0};
+static uint32 gnss_buff_len = 0;
+static bool nmea_found = FALSE;
+#ifdef GNSS_DEBUG
+static bool nmea_log_enable = FALSE;
+static int nmea_log_fd = -1;
+static int nmea_log_fd_len = 0;
+#endif
+static int gnss_pty_master_fd = -1;
+static int gnss_pty_slave_fd = -1;
+static int gnss_usb_at_port_fd = -1;
+static int gnss_usb_nmea_port_fd = -1;
+static int gnss_uart_at_port_fd = -1;
+static char *gnss_filter_info[] = {"RMC", "VTG", "GGA", "GSA", "GSV", "GLL", "ZDA", "GST", "TXT", "DHV", "DTM", NULL};
+
+static void help()
+{
+ LOGD("mbtk_gnssd <6228/...> <gnss_dev> <0/1>");
+}
+
+static int arg_check(int argc, char *argv[])
+{
+ if(argc != 4) {
+ goto check_fail;
+ }
+
+ // Only support 6228.
+ if(strcmp(argv[1], GNSS_ID_6228)) {
+ goto check_fail;
+ }
+
+ if(access(argv[2], R_OK | W_OK)) {
+ goto check_fail;
+ }
+
+ if(strcmp(argv[3], "0") && strcmp(argv[3], "1")) {
+ goto check_fail;
+ }
+
+ return 0;
+check_fail:
+ help();
+ return -1;
+}
+
+static int gnss_ports_open(uint32 print_port)
+{
+ if(print_port & GNSS_PRINT_PORT_TTY_AT) {
+ if(gnss_pty_open(&gnss_pty_master_fd, &gnss_pty_slave_fd, GNSS_PORT_PTY)) {
+ return -1;
+ }
+ LOGD("Open PTY port success.");
+ }
+
+ if(print_port & GNSS_PRINT_PORT_USB_AT) {
+ if((gnss_usb_at_port_fd = gnss_port_open(GNSS_PORT_USB_AT, O_RDWR | O_NONBLOCK | O_NOCTTY, 115200, FALSE)) <= 0) {
+ return -1;
+ }
+ LOGD("Open USB AT port success.");
+ }
+
+ if(print_port & GNSS_PRINT_PORT_USB_NMEA) {
+ if((gnss_usb_nmea_port_fd = gnss_port_open(GNSS_PORT_USB_NMEA, O_RDWR | O_NONBLOCK | O_NOCTTY, 115200, FALSE)) <= 0) {
+ return -1;
+ }
+ LOGD("Open USB NMEA port success.");
+ }
+
+ if(print_port & GNSS_PRINT_PORT_UART1) {
+ if((gnss_uart_at_port_fd = gnss_port_open(GNSS_PORT_UART_AT, O_RDWR | O_NONBLOCK | O_NOCTTY, 115200, TRUE)) <= 0) {
+ return -1;
+ }
+ LOGD("Open UART AT port success.");
+ }
+
+ return 0;
+}
+
+static int gnss_ports_close()
+{
+ if(gnss_usb_at_port_fd > 0) {
+ close(gnss_usb_at_port_fd);
+ gnss_usb_at_port_fd = -1;
+ }
+
+ if(gnss_usb_nmea_port_fd > 0) {
+ close(gnss_usb_nmea_port_fd);
+ gnss_usb_nmea_port_fd = -1;
+ }
+
+ if(gnss_uart_at_port_fd > 0) {
+ close(gnss_uart_at_port_fd);
+ gnss_uart_at_port_fd = -1;
+ }
+
+ if(gnss_pty_master_fd > 0) {
+ close(gnss_pty_master_fd);
+ gnss_pty_master_fd = -1;
+ }
+
+ if(gnss_pty_slave_fd > 0) {
+ close(gnss_pty_slave_fd);
+ gnss_pty_slave_fd = -1;
+ unlink(GNSS_PORT_PTY);
+ }
+
+ return 0;
+}
+
+static void nmea_print(const char *nmea, int nmea_len)
+{
+#ifdef GNSS_DEBUG
+ if(nmea_log_enable){
+ if(nmea_log_fd_len > GNSS_NMEA_FILE_LOG_MAX) {
+ close(nmea_log_fd);
+ nmea_log_fd = open(GNSS_NMEA_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if(nmea_log_fd < 0) {
+ LOGE("Open debug fd fail.");
+ }
+ nmea_log_fd_len = 0;
+ }
+
+ if(nmea_log_fd > 0) {
+ write(nmea_log_fd, nmea, nmea_len);
+ nmea_log_fd_len += nmea_len;
+ }
+ }
+#endif
+
+ if(gnss_usb_at_port_fd > 0) {
+ write(gnss_usb_at_port_fd, nmea, nmea_len);
+ }
+
+ if(gnss_usb_nmea_port_fd > 0) {
+ write(gnss_usb_nmea_port_fd, nmea, nmea_len);
+ }
+
+ if(gnss_uart_at_port_fd > 0) {
+ write(gnss_uart_at_port_fd, nmea, nmea_len);
+ }
+
+ if(gnss_pty_master_fd > 0) {
+ write(gnss_pty_master_fd, nmea, nmea_len);
+ }
+}
+
+static unsigned char nmea_checksum(const char *nmea)
+{
+ const char *p = nmea;
+ unsigned char chs = 0;
+
+ while (*p == '$') // skip '$'
+ p++;
+ while (*p != '*' && *p != 0)
+ chs ^= *p++;
+
+ return chs;
+}
+
+static bool nmea_check(const char *nmea, int nmea_len)
+{
+ char **ptr = gnss_filter_info;
+ while(*ptr) {
+ if(strstr(nmea, *ptr)) {
+ break;
+ }
+ ptr++;
+ }
+
+ if(*ptr == NULL) {
+ LOGD("Unknown NMEA[%d]:%s", nmea_len, nmea);
+ return FALSE;
+ }
+
+ char *checksum_str = strstr(nmea, "*");
+ checksum_str++; // Jump '*'
+ char checksum_buf[3] = {0};
+ snprintf(checksum_buf, 3, "%02x", nmea_checksum(nmea));
+ if(strncasecmp(checksum_buf, checksum_str, 2)) {
+ LOGD("Checksum error[%d](checksum - %s):%s", nmea_len, checksum_buf, nmea);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void gnss_nmea_process(const char *data, int data_len)
+{
+ char nmea[GNSS_BUFF_SIZE] = {0};
+ memcpy(nmea, data, data_len);
+
+ if(!nmea_check(nmea, data_len)) {
+ gnss_info.gnss_set_cb(nmea, data_len);
+ return;
+ }
+
+#ifdef GNSS_DEBUG
+ if(nmea_log_enable) {
+ LOGD("NMEA[%d]:%s", data_len, nmea);
+ }
+#endif
+
+ nmea_print(nmea, data_len);
+}
+
+#if 0
+static void gnss_cmd_rsp_process(const char *data, int data_len)
+{
+ char rsp[GNSS_BUFF_SIZE] = {0};
+ memcpy(rsp, data, data_len);
+ LOGD("RSP[%d]:%s", data_len, rsp);
+}
+#endif
+
+static bool nmea_char_check(char ch)
+{
+ if(isalnum(ch) || ch == '$' || ch == '\r' || ch == '\n' || ch == '.'
+ || ch == ',' || ch == '*' || ch == '\0' || ch == '/')
+ return TRUE;
+
+ return FALSE;
+}
+
+static void gnss_data_process(const char *data, int data_len)
+{
+ if(gnss_info.state == GNSS_STATE_OPEN) {
+ LOGD("GNSS_OPEN[%d]:%s", data_len, data);
+ } else if(gnss_info.state == GNSS_STATE_DOWNLOAD) {
+ // LOGD("GNSS_DL[%d]:%s", data_len, data);
+ gnss_info.gnss_dl_read_cb(data, data_len);
+ } else if(gnss_info.state == GNSS_STATE_READY) {
+ int index = 0;
+ while(index < data_len) {
+ if(nmea_found) {
+ if(!nmea_char_check(data[index])) {
+ gnss_buff_len = 0;
+ nmea_found = FALSE;
+#if 0
+ if(isascii(data[index])) {
+ LOGD("\n\n###%c###%s\n\n", data[index], data);
+ }
+#endif
+ continue;
+ }
+
+ if(data[index] != '\0') {
+ gnss_buff[gnss_buff_len++] = data[index];
+ if(gnss_buff[gnss_buff_len - 1] == '\n') {
+
+ if(gnss_buff_len > 6 && gnss_buff[gnss_buff_len - 5] == '*') { // $XXX*YY\r\n
+ gnss_nmea_process(gnss_buff, gnss_buff_len);
+ }
+
+ gnss_buff_len = 0;
+ nmea_found = FALSE;
+ }
+ }
+ } else {
+ if(data[index] == '$') {
+ gnss_buff_len = 0;
+ nmea_found = TRUE;
+ gnss_buff[gnss_buff_len++] = data[index];
+ }
+ }
+ index++;
+ }
+ } else {
+ LOGW("Unknown state : %d", gnss_info.state);
+ }
+}
+
+void* gnss_read_pthread(void* arg)
+{
+ LOGD("gnss_read_pthread enter.");
+ char buffer[GNSS_BUFF_SIZE];
+ int len = 0;
+ int ret = 0;
+ fd_set fdr, fdw;
+ int fd_max = 0;
+
+ FD_ZERO(&fdw);
+ FD_ZERO(&fdr);
+ FD_SET(gnss_info.fd, &fdr);
+ fd_max = (gnss_info.fd > fd_max) ? gnss_info.fd : fd_max;
+ FD_SET(gnss_info.exit_fd[0], &fdr);
+ fd_max = (gnss_info.exit_fd[0] > fd_max) ? gnss_info.exit_fd[0] : fd_max;
+ memset(gnss_buff, 0, sizeof(gnss_buff));
+ gnss_buff_len = 0;
+#if GNSS_DEBUG
+ int debug_fd = -1;
+ int debug_fd_len = 0;
+ if(nmea_log_enable) {
+ debug_fd = open(GNSS_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if(debug_fd < 0) {
+ LOGE("Open debug fd fail.");
+ }
+ nmea_log_fd = open(GNSS_NMEA_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if(nmea_log_fd < 0) {
+ LOGE("Open nmea fd fail.");
+ }
+ nmea_log_fd_len = 0;
+ }
+#endif
+
+ while(gnss_info.state >= GNSS_STATE_OPEN) {
+ ret = select(fd_max + 1, &fdr, &fdw, 0, NULL);
+ //LOGD("select - %d", ret);
+ if (ret < 0)
+ {
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ LOGE("select error, errno = %d (%s)", errno, strerror(errno));
+ break;
+ }
+ else if (ret == 0)
+ {
+ LOGE("select ret == 0");
+ break;
+ }
+
+ if (FD_ISSET(gnss_info.fd, &fdr))
+ {
+ memset(buffer, 0, GNSS_BUFF_SIZE);
+ len = read(gnss_info.fd, buffer, GNSS_BUFF_SIZE);
+ if(len > 0) {
+ //log_hex("READ", buffer, len);
+
+#if GNSS_DEBUG
+ if(nmea_log_enable){
+ if(debug_fd_len > GNSS_FILE_LOG_MAX) {
+ close(debug_fd);
+ debug_fd = open(GNSS_FILE_LOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if(debug_fd < 0) {
+ LOGE("Open debug fd fail.");
+ }
+ debug_fd_len = 0;
+ }
+
+ if(debug_fd > 0) {
+ write(debug_fd, buffer, len);
+ debug_fd_len += len;
+ }
+ }
+#endif
+
+ gnss_data_process(buffer, len);
+
+ } else if(len ==0 ){
+ LOGE("Read end : len = 0");
+ break;
+ } else {
+ if(EAGAIN == errno) {
+ usleep(50000);
+ continue;
+ } else {
+ LOGD("Read ret = -1 ,errno = %d", errno);
+ break;
+ }
+ }
+ }
+ else if (FD_ISSET(gnss_info.exit_fd[0], &fdr))
+ {
+ memset(buffer, 0, GNSS_BUFF_SIZE);
+ len = read(gnss_info.fd, buffer, GNSS_BUFF_SIZE);
+ if(len > 0) {
+ if(strcmp(buffer, "exit") == 0) {
+ LOGD("Get thread exit message.");
+ break;
+ }
+ }
+ }
+ else
+ {
+ LOGW("Unknown select event.");
+ continue;
+ }
+ }
+
+#if GNSS_DEBUG
+ if(debug_fd > 0) {
+ close(debug_fd);
+ debug_fd = -1;
+ }
+ if(nmea_log_fd > 0) {
+ close(nmea_log_fd);
+ nmea_log_fd = -1;
+ }
+#endif
+
+ gnss_info.state = GNSS_STATE_CLOSE;
+ LOGD("gnss_read_pthread exit.");
+ return NULL;
+}
+
+#if 0
+int gnss_write(int fd, const void *data, int data_len)
+{
+ int count = 0;
+ int len = 0;
+ while(1)
+ {
+ len = write(fd, data + count, data_len - count);
+ if (len > 0)
+ {
+ count += len;
+ }
+ else
+ {
+ LOGE("write() fail,ret = %d,errno = %d", len, errno);
+ break;
+ }
+
+ if (count == data_len)
+ break;
+ }
+
+ return count;
+}
+#else
+int gnss_write(int fd, const void* buf, unsigned int buf_len)
+{
+ size_t size;
+ size_t size_to_wr;
+ ssize_t size_written;
+ if(GNSS_BUFF_SIZE < buf_len)
+ {
+ return -1;
+ }
+ for(size = 0; size < buf_len;)
+ {
+ size_to_wr = buf_len - size;
+ if( size_to_wr > GNSS_BUFF_SIZE)
+ size_to_wr = GNSS_BUFF_SIZE;
+
+ size_written = write(fd, &buf[size], size_to_wr);
+ if (size_written==-1)
+ {
+ return -1;
+ }
+ size += size_written;
+ if(size_written != size_to_wr)
+ {
+ return size;
+ }
+ }
+ // LOGD("SEND %d / %d", size, buf_len);
+ return size;
+}
+#endif
+
+int gnss_init(uint32 print_port)
+{
+ if(gnss_info.state != GNSS_STATE_CLOSE) {
+ LOGW("GNSS not close:%d", gnss_info.state);
+ return 0;
+ }
+
+ int ret = 0;
+
+ gnss_info.fd = gnss_info.gnss_open(gnss_info.dev_name);
+ if(gnss_info.fd <= 0) {
+ LOGE("gnss_open(%s) fail : %d", gnss_info.dev_name, gnss_info.fd);
+ gnss_info.state = GNSS_STATE_CLOSE;
+ return -1;
+ }
+ if(pipe(gnss_info.exit_fd)) {
+ LOGE("pipe() fail[%d].", errno);
+ return -1;
+ }
+ // GNSS is opened.
+ gnss_info.state = GNSS_STATE_OPEN;
+
+ #if 0
+ // Start gnss read thread.
+ pthread_attr_t thread_attr;
+ pthread_attr_init(&thread_attr);
+ if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+ {
+ LOGE("pthread_attr_setdetachstate() fail.");
+ goto main_exit;
+ }
+
+ if(pthread_create(&gnss_info.read_pid, &thread_attr, gnss_read_pthread, NULL))
+#else
+ if(pthread_create(&gnss_info.read_pid, NULL, gnss_read_pthread, NULL))
+#endif
+ {
+ LOGE("pthread_create() fail.");
+ goto exit_with_close;
+ }
+
+ ret = gnss_info.gnss_dev_open();
+ if(ret) {
+ LOGE("gnss_dev_open() fail : %d", ret);
+ goto exit_with_thread_exit;
+ }
+
+ if(gnss_info.auto_dl_fw) {
+ gnss_info.state = GNSS_STATE_DOWNLOAD;
+ ret = gnss_info.gnss_fw_dl(gnss_info.fd);
+ if(ret) {
+ LOGE("gnss_fw_dl() fail : %d", ret);
+ goto exit_with_dev_close;
+ }
+ }
+
+ // GNSS is ready, NMEA can print from uart.
+ gnss_info.state = GNSS_STATE_READY;
+ gnss_info.print_port = print_port;
+
+ LOGD("GNSS open success.");
+
+ return gnss_ports_open(gnss_info.print_port);
+
+exit_with_dev_close:
+ if(gnss_info.gnss_dev_close()) {
+ LOGE("gnss_dev_close() fail.");
+ }
+exit_with_thread_exit:
+ gnss_info.state = GNSS_STATE_CLOSING;
+ // Wait for read thread exit.
+ ret = pthread_join(gnss_info.read_pid, NULL);
+ if(ret){
+ LOGE("pthrad_join fail(%d)",ret);
+ }
+exit_with_close:
+ if(gnss_info.gnss_close(gnss_info.fd)) {
+ LOGE("gnss_close() fail.");
+ }
+ if(gnss_info.exit_fd[0] > 0) {
+ close(gnss_info.exit_fd[0]);
+ gnss_info.exit_fd[0] = -1;
+ }
+ if(gnss_info.exit_fd[1] > 0) {
+ close(gnss_info.exit_fd[1]);
+ gnss_info.exit_fd[1] = -1;
+ }
+ gnss_info.state = GNSS_STATE_CLOSE;
+ return -1;
+}
+
+int gnss_deinit()
+{
+ if(gnss_info.state == GNSS_STATE_CLOSE) {
+ LOGW("GNSS is closed.");
+ return 0;
+ } else if(gnss_info.state == GNSS_STATE_CLOSING) {
+ LOGW("GNSS is closing...");
+ return -1;
+ } else if(gnss_info.state == GNSS_STATE_DOWNLOAD) {
+ LOGW("GNSS is downloading...");
+ return -1;
+ }
+
+ // Wait for read thread exit.
+ if(gnss_info.exit_fd[1] > 0) {
+ write(gnss_info.exit_fd[1], "exit", 4);
+ }
+
+ gnss_info.state = GNSS_STATE_CLOSING;
+ int ret = pthread_join(gnss_info.read_pid, NULL);
+ if(ret){
+ LOGE("pthrad_join fail(%d)",ret);
+ return -1;
+ }
+
+ if(gnss_info.gnss_close(gnss_info.fd)) {
+ LOGE("gnss_close() fail.");
+ return -1;
+ }
+
+ if(gnss_info.gnss_dev_close()) {
+ LOGE("gnss_dev_close() fail.");
+ return -1;
+ }
+
+ if(gnss_ports_close()) {
+ LOGE("gnss_ports_close fail.");
+ return -1;
+ }
+
+ gnss_info.fd = -1;
+ if(gnss_info.exit_fd[0] > 0) {
+ close(gnss_info.exit_fd[0]);
+ gnss_info.exit_fd[0] = -1;
+ }
+ if(gnss_info.exit_fd[1] > 0) {
+ close(gnss_info.exit_fd[1]);
+ gnss_info.exit_fd[1] = -1;
+ }
+ gnss_info.state = GNSS_STATE_CLOSE;
+ LOGD("GNSS close success.");
+ return 0;
+}
+
+int gnss_set(const void* buf, unsigned int buf_len, void *cmd_rsp, int cmd_rsp_len)
+{
+ if(cmd_rsp && buf && buf_len > 0 && cmd_rsp_len > 0) {
+ memset(cmd_rsp, 0, cmd_rsp_len);
+ return gnss_info.gnss_set(gnss_info.fd, buf, cmd_rsp, cmd_rsp_len);
+ } else {
+ return -1;
+ }
+}
+
+static void sig_process(int sig)
+{
+ LOGI("I got signal %d\n", sig);
+ if(gnss_deinit()) {
+ LOGE("gnss_deinit() fail, no exist...");
+ return;
+ }
+
+ switch(sig)
+ {
+ case SIGINT: // Ctrl + C
+ {
+ LOGI("Exit by SIGINT.\n");
+ exit(0);
+ }
+ case SIGQUIT: // Ctrl + \ (ÀàËÆ SIGINT £¬µ«Òª²úÉúcoreÎļþ)
+ {
+ LOGI("Exit by SIGQUIT.\n");
+ exit(0);
+ }
+ case SIGTERM:// ĬÈÏkill (ͬ SIGKILL £¬µ« SIGKILL ²»¿É²¶»ñ)
+ {
+ LOGI("Exit by SIGTERM.\n");
+ exit(0);
+ }
+ case SIGTSTP:// Ctrl + Z (ͬ SIGSTOP £¬µ« SIGSTOP ²»¿É²¶»ñ)
+ {
+ LOGI("Exit by SIGTSTP.\n");
+ exit(0);
+ }
+ case SIGSEGV: // Èç¿ÕÖ¸Õë
+ {
+ LOGI("Exit by SIGSEGV.\n");
+ exit(0);
+ }
+ default:
+ {
+ LOGI("Unknown sig:%d\n",sig);
+ break;
+ }
+ }
+}
+
+
+// mbtk_gnssd 6228 /dev/ttyS2 baud 0/1
+int main(int argc, char *argv[])
+{
+ mbtk_log_init("radio", GNSS_TAG);
+
+ signal(SIGINT, sig_process);
+ signal(SIGQUIT, sig_process);
+ signal(SIGTERM, sig_process);
+
+ if(arg_check(argc, argv)) {
+ return -1;
+ }
+
+#ifdef GNSS_DEBUG
+ char buff[10];
+ memset(buff, 0, 10);
+ property_get(MBTK_PROP_GNSS_LOG, buff, "");
+ if(strlen(buff) > 0 && atoi(buff) > 0) {
+ nmea_log_enable = TRUE;
+ }
+#endif
+
+ memset(&gnss_info, 0, sizeof(gnss_info_t));
+ memcpy(gnss_info.dev_name, argv[2], strlen(argv[2]));
+ gnss_info.state = GNSS_STATE_CLOSE;
+ if(!strcmp(argv[1], GNSS_ID_6228)) {
+ gnss_info.gnss_id = GNSS_TYPE_6228;
+ gnss_info.auto_open = (bool)atoi(argv[3]);
+ gnss_info.auto_dl_fw = TRUE;
+ gnss_info.gnss_dev_open = gnss_6228_dev_open;
+ gnss_info.gnss_dev_close = gnss_6228_dev_close;
+ gnss_info.gnss_open = gnss_6228_open;
+ gnss_info.gnss_close = gnss_6228_close;
+ gnss_info.gnss_fw_dl = gnss_6228_fw_dl;
+ gnss_info.gnss_dl_read_cb = gnss_6228_dl_read_cb;
+ gnss_info.gnss_set = gnss_6228_set;
+ gnss_info.gnss_set_cb = gnss_6228_set_cb;
+ } else {
+ LOGE("No support : %s", argv[1]);
+ return -1;
+ }
+
+ LOGD("GNSS : %s, Device: %s", argv[1], gnss_info.dev_name);
+ // Auto open gnss.
+ if(gnss_info.auto_open) {
+ if(gnss_init(0)) { // No print to any port.
+ LOGE("gnss_init() fail.");
+ return -1;
+ }
+ }
+
+ // Init ubus and waitting IPC commands.
+ if(gnss_ubus_init()) {
+ LOGD("main() run...");
+ uloop_run();
+ } else {
+ LOGE("gnss_ubus_init() fail.");
+ }
+
+ LOGD("main() exit.");
+ return 0;
+}
diff --git a/mbtk/mbtk_gnssd/gnss_nmea.c b/mbtk/mbtk_gnssd/gnss_nmea.c
new file mode 100755
index 0000000..8b13789
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_nmea.c
@@ -0,0 +1 @@
+
diff --git a/mbtk/mbtk_gnssd/gnss_ubus.c b/mbtk/mbtk_gnssd/gnss_ubus.c
new file mode 100755
index 0000000..30de33a
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_ubus.c
@@ -0,0 +1,358 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <libubox/ustream.h>
+#include <libubus.h>
+
+#include "gnss_info.h"
+#include "mbtk_log.h"
+
+//static struct blob_buf b;
+static struct blob_buf gps_blob;
+
+int gnss_init(uint32 print_port);
+int gnss_deinit();
+int gnss_set(const void* buf, unsigned int buf_len, void *cmd_rsp, int cmd_rsp_len);
+
+const struct blobmsg_policy gnss_init_policy[] ={
+ [0] = {
+ .name = "gnss_init_param",
+ .type = BLOBMSG_TYPE_INT32,
+ },
+};
+
+
+const struct blobmsg_policy get_agps_policy[] ={
+ [0] = {
+ .name = "server_name",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+ [1] = {
+ .name = "alam_flag",
+ .type = BLOBMSG_TYPE_INT32,
+ },
+};
+
+const struct blobmsg_policy gnss_sleep_policy[] ={
+ [0] = {
+ .name = "gnss_sleep_param",
+ .type = BLOBMSG_TYPE_INT32,
+ },
+};
+
+const struct blobmsg_policy gnss_setting_policy[] ={
+ [0] = {
+ .name = "gnss_setting_param",
+ .type = BLOBMSG_TYPE_STRING,
+ },
+};
+
+static int gps_ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req, int ret)
+{
+ blob_buf_init(&gps_blob, 0);
+ blobmsg_add_u32(&gps_blob, "event", ret);
+ ubus_send_reply(ctx, req, gps_blob.head);
+ return 0;
+}
+
+static int gps_ubus_string_reply(struct ubus_context *ctx, struct ubus_request_data *req, char *str)
+{
+ blob_buf_init(&gps_blob, 0);
+ blobmsg_add_string(&gps_blob, "gps_state_resp", str);
+ ubus_send_reply(ctx, req, gps_blob.head);
+ return 0;
+}
+
+static int ubus_gnss_init(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(obj);
+ UNUSED(method);
+ struct blob_attr *tb[1];
+ struct blob_attr *cur;
+ int init_mode = 0, err = 0, ret = 0;
+ int status = 0;
+
+ /*parsing blob to be accessed easily with tb array - parse "1" argument*/
+ err = blobmsg_parse(gnss_init_policy, 1, tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ LOGE("blobmsg_parse fail");
+ return -1;
+ }
+ cur = tb[0];
+ if (!cur) {
+ LOGE("missing parameter");
+ return -2;
+ }
+
+ init_mode = blobmsg_get_u32(cur);
+ LOGD("init_mode=%d", init_mode);
+ if(init_mode == 0) { // Close gnss.
+ ret = gnss_deinit();
+ } else {
+ if(((GNSS_PRINT_PORT_UART1 | GNSS_PRINT_PORT_USB_NMEA | GNSS_PRINT_PORT_USB_AT | GNSS_PRINT_PORT_TTY_AT) & init_mode) == init_mode) {
+ ret = gnss_init(init_mode);
+ } else { // ARG error, no print nmea.
+ ret = gnss_init(0);
+ }
+ }
+
+ LOGD("ubus_gnss_init() ret=%d", ret);
+ gps_ubus_send_reply(ctx, req, ret);
+
+ return 0;
+}
+
+static int ubus_gnss_deinit(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ UNUSED(msg);
+
+ int ret = 0;
+
+ ret = gnss_deinit();
+
+ gps_ubus_send_reply(ctx, req, ret);
+
+ return 0;
+}
+
+static int ubus_gnss_get_agps(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(obj);
+ UNUSED(method);
+ struct blob_attr *tb[ARRAY_SIZE(get_agps_policy)];
+ struct blob_attr *cur;
+ char *server_name = NULL;
+ int err = 0, alm_flag = 0, ret = 0;
+
+ err = blobmsg_parse(get_agps_policy, ARRAY_SIZE(get_agps_policy), tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ LOGE("blobmsg_parse table fail");
+ return -1;
+ }
+
+ cur = tb[0];
+ if (cur)
+ server_name = blobmsg_get_string(cur);
+ else
+ LOGE("missing parameter1");
+
+ cur = tb[1];
+ if (cur)
+ alm_flag = blobmsg_get_u32(cur);
+ else
+ LOGE("missing parameter2");
+
+ LOGD("server_name=%s, alm_flag=%d", server_name, alm_flag);
+
+ if (server_name)
+ {
+ ret = 3;
+ }
+
+ gps_ubus_send_reply(ctx, req, ret);
+
+ return 0;
+}
+
+static int ubus_gnss_set_agps(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ UNUSED(msg);
+
+ int err = 0, ret = 0;
+
+ ret = 4;
+
+
+ gps_ubus_send_reply(ctx, req, ret);
+
+ return 0;
+}
+
+static int ubus_gnss_sleep(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ struct blob_attr *tb[1];
+ struct blob_attr *cur;
+ int workmode = 0, err = 0;
+ int status = 0;
+
+ /*parsing blob to be accessed easily with tb array - parse "1" argument*/
+ err = blobmsg_parse(gnss_sleep_policy, 1, tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ LOGE("blobmsg_parse fail");
+ return -1;
+ }
+ cur = tb[0];
+ if (!cur) {
+ LOGE("missing parameter");
+ return -2;
+ }
+
+ workmode = blobmsg_get_u32(cur);
+ LOGD("workMode=%d", workmode);
+ /* Goto Sleeping.....*/
+
+ LOGD("ret=%d", status);
+ return 0;
+}
+
+static int ubus_gnss_setting(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(ctx);
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ struct blob_attr *tb[1];
+ struct blob_attr *cur;
+ int err = 0, ret = 0;
+ char *gpsCfg = NULL;
+ int status = 0;
+
+ /*parsing blob to be accessed easily with tb array - parse "1" argument*/
+ err = blobmsg_parse(gnss_setting_policy, 1, tb, blob_data(msg), blob_len(msg));
+ if (err < 0)
+ {
+ LOGE("blobmsg_parse fail");
+ return -1;
+ }
+ cur = tb[0];
+ if (!cur) {
+ LOGE("missing parameter");
+ return -2;
+ }
+
+ gpsCfg = blobmsg_get_string(cur);
+ LOGD("gpsCfg=%s", gpsCfg);
+
+ char rsp[1024];
+ ret = gnss_set(gpsCfg, strlen(gpsCfg), rsp, 1024);
+
+ LOGD("ret=%d", ret);
+ gps_ubus_send_reply(ctx, req, ret);
+
+ return 0;
+}
+
+#define ASR_GNSS_STATUS_LEN 128
+static int ubus_gnss_get_state(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ UNUSED(obj);
+ UNUSED(req);
+ UNUSED(method);
+ UNUSED(msg);
+
+ char tmpBuf[ASR_GNSS_STATUS_LEN] = {0};
+ int i = 0;
+ int len = 0;
+ int ret = 0;
+ int num = 0;
+
+ //ret = asr_gnss_get_gps_info(¶m);
+ if (0 == ret) {
+ len = snprintf(tmpBuf, sizeof(tmpBuf), "%d, %d, %d, %d, %d;", 0, 0, 0, 0, 0);
+ num = 6;
+ for(i=0; i<num; i++) {
+ len += sprintf(&tmpBuf[len], " %d, %d;", 1, 2);
+
+ if(len > ASR_GNSS_STATUS_LEN)
+ break;
+ }
+
+ LOGD("[%d]tmpBuf=%s", len, tmpBuf);
+ gps_ubus_string_reply(ctx, req, tmpBuf);
+ }
+
+ return 0;
+}
+
+static const struct ubus_method gps_ubus_methods[] = {
+ UBUS_METHOD("gnss_init", ubus_gnss_init, gnss_init_policy),
+ UBUS_METHOD_NOARG("gnss_deinit", ubus_gnss_deinit),
+ UBUS_METHOD("gnss_get_agps", ubus_gnss_get_agps, get_agps_policy),
+ UBUS_METHOD_NOARG("gnss_set_agps", ubus_gnss_set_agps),
+ UBUS_METHOD("gnss_sleep", ubus_gnss_sleep, gnss_sleep_policy),
+ UBUS_METHOD("gnss_setting", ubus_gnss_setting, gnss_setting_policy),
+ UBUS_METHOD_NOARG("gnss_get_state", ubus_gnss_get_state),
+};
+
+static struct ubus_object_type gps_object_type =
+ UBUS_OBJECT_TYPE("mbtk_gnss", gps_ubus_methods);
+
+static struct ubus_object gps_ubus_obj = {
+ .name = "mbtk_gnss",
+ .type = &gps_object_type,
+ .methods = gps_ubus_methods,
+ .n_methods = ARRAY_SIZE(gps_ubus_methods),
+};
+
+int gnss_ubus_exit(struct ubus_context *ctx)
+{
+ if(!ctx) {
+ return -1;
+ }
+
+ ubus_remove_object(ctx, &gps_ubus_obj);
+ ubus_free(ctx);
+ uloop_done();
+
+ LOGD("ubus exit done");
+ return 0;
+}
+
+struct ubus_context *gnss_ubus_init(void)
+{
+ struct ubus_context *ctx;
+
+ uloop_init();
+
+ ctx = ubus_connect(NULL);
+ if (!ctx) {
+ LOGE("Failed to connect to ubus");
+ return NULL;
+ }
+
+ ubus_add_uloop(ctx);
+ if (ubus_add_object(ctx, &gps_ubus_obj)) {
+ LOGE("Failed to add server");
+ ubus_free(ctx);
+ uloop_done();
+ return NULL;
+ }
+
+ LOGD("gps ubus init done!");
+
+ return ctx;
+}
+
diff --git a/mbtk/mbtk_gnssd/gnss_utils.c b/mbtk/mbtk_gnssd/gnss_utils.c
new file mode 100755
index 0000000..e0fa746
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_utils.c
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+
+#define DATABITS CS8
+#define STOPBITS 0
+#define PARITYON 0
+#define PARITY 0
+#define MBTK_SLAVE_DEV_NAME_MAX_LEN 24
+
+int uart_baud_get(int baud)
+{
+ int rate = 0;
+ switch(baud)
+ {
+ case 300:
+ rate = B300;
+ break;
+ case 600:
+ rate = B600;
+ break;
+ case 1200:
+ rate = B1200;
+ break;
+ case 2400:
+ rate = B2400;
+ break;
+ case 4800:
+ rate = B4800;
+ break;
+ case 9600:
+ rate = B9600;
+ break;
+ case 19200:
+ rate = B19200;
+ break;
+ case 38400:
+ rate = B38400;
+ break;
+ case 57600:
+ rate = B57600;
+ break;
+ case 115200:
+ rate = B115200;
+ break;
+ case 230400:
+ rate = B230400;
+ break;
+ case 460800:
+ rate = B460800;
+ break;
+ case 921600:
+ rate = B921600;
+ break;
+ case 1500000:
+ rate = B1500000;
+ break;
+ case 2000000:
+ rate = B2000000;
+ break;
+ case 3000000:
+ rate = B3000000;
+ break;
+ case 4000000:
+ rate = B4000000;
+ break;
+ default:
+ rate = B115200;
+ break;
+ }
+
+ return rate;
+}
+
+int gnss_port_open(const char *dev, int flag, int baud, bool tty)
+{
+
+ int fd = -1;
+ if((fd = open(dev, flag)) < 0)
+ {
+ LOGE("Open %s fail errno = [%d].", dev, errno);
+ return -1;
+ }
+
+ LOGD("Open %s success.", dev);
+ if (tty)
+ {
+ int rate = uart_baud_get(baud);
+ /* set newtio */
+ struct termios newtio;
+ memset(&newtio, 0, sizeof(newtio));
+ //(void)fcntl(fd, F_SETFL, 0);
+ /* no flow control for uart by default */
+ newtio.c_cflag = rate | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
+ newtio.c_iflag = IGNPAR;
+ //newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ newtio.c_oflag = 0;
+ newtio.c_lflag = 0; /* disable ECHO, ICANON, etc... */
+
+ newtio.c_cc[VERASE] = 0x8; /* del */
+ newtio.c_cc[VEOF] = 4; /* Ctrl-d */
+ newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
+ newtio.c_cc[VEOL] = 0xD; /* '\0' */
+
+ tcflush(fd, TCIOFLUSH);
+ tcsetattr(fd, TCSANOW, &newtio);
+ }
+
+ return fd;
+}
+
+int gnss_port_close(int fd)
+{
+ if(fd > 0)
+ {
+ close(fd);
+ }
+ return 0;
+}
+
+int gnss_set_baudrate(int fd, int baudrate)
+{
+ struct termios options, oldtio;
+
+ if(fcntl(fd, F_SETFL, 0) < 0) {
+ LOGE("fcntl failed!");
+ return -1;
+ }
+
+ if(tcgetattr(fd, &oldtio) != 0) {
+ LOGE("setup serial error!");
+ return -1;
+ }
+
+ /* Get the current options for the port... */
+ tcgetattr(fd, &options);
+
+ /* Set the baud rates to baudrate... */
+ cfsetispeed(&options,baudrate);
+ cfsetospeed(&options,baudrate);
+ tcsetattr(fd, TCSANOW, &options);
+
+ if (0 != tcgetattr(fd, &options))
+ {
+ LOGE("get options error!");
+ return -1;
+ }
+
+ /*
+ * 8bit Data,no partity,1 stop bit...
+ */
+ options.c_cflag &= ~PARENB;//无奇偶校验
+ options.c_cflag &= ~CSTOPB;//停止位,1位
+ options.c_cflag &= ~CSIZE; //数据位的位掩码
+ options.c_cflag |= CS8; //数据位,8位
+
+ cfmakeraw(&options);
+
+ /*
+ * Set the new options for the port...
+ */
+ if (tcsetattr(fd, TCSANOW, &options) != 0)
+ {
+ LOGE("setup serial error!");
+ return -1 ;
+ }
+
+ return 0 ;
+}
+
+uint16 get_crc16(const char *ptr, uint16 count)
+{
+ uint16 crc, i;
+
+ crc = 0;
+ while(count--)
+ {
+ crc = crc ^ (int) *ptr++ << 8;
+
+ for(i = 0; i < 8; i++)
+ {
+ if(crc & 0x8000)
+ crc = crc << 1 ^ 0x1021;
+ else
+ crc = crc << 1;
+ }
+ }
+
+ return (crc & 0xFFFF);
+}
+
+int gnss_pty_open(int *master_fd, int *slave_fd, const char *dev)
+{
+ int flags = -1;
+ int ret = -1;
+ if(*master_fd > 0) {
+ LOGD("PTY has inited.");
+ return 0;
+ }
+ char spty_name[MBTK_SLAVE_DEV_NAME_MAX_LEN] = {0};
+ int result = openpty(master_fd, slave_fd, spty_name, NULL, NULL);
+ if (-1 == result) {
+ LOGE("Failed to get a pty.");
+ return -1;
+ }
+
+ LOGD("Get a pty pair, FD -- master[%d] slave[%d]", *master_fd, *slave_fd);
+ LOGD("Slave name is:%s", spty_name);
+
+ if(access(dev, F_OK) == -1)
+ {
+ LOGD("symlink %s -> %s", spty_name, dev);
+ result = symlink(spty_name, dev);
+ if (-1 == result) {
+ LOGE("symlink error.");
+ goto ERROR;
+ }
+ }
+
+ flags = fcntl(*master_fd, F_GETFL);
+ if (flags == -1)
+ {
+ LOGE("fcntl get error.");
+ goto ERROR;
+ }
+ flags |= O_NONBLOCK;
+ flags |= O_NOCTTY;
+ ret = fcntl(*master_fd, F_SETFL, flags);
+ if(ret == -1)
+ {
+ LOGE("fcntl set error.");
+ goto ERROR;
+ }
+
+ if (1) {
+ /* set newtio */
+ struct termios newtio;
+ memset(&newtio, 0, sizeof(newtio));
+ /* no flow control for uart by default */
+ newtio.c_cflag = B115200 | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
+ newtio.c_iflag = IGNPAR;
+ //newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ newtio.c_oflag = 0;
+ newtio.c_lflag = 0; /* disable ECHO, ICANON, etc... */
+
+ newtio.c_cc[VERASE] = 0x8; /* del */
+ newtio.c_cc[VEOF] = 4; /* Ctrl-d */
+ newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
+ newtio.c_cc[VEOL] = 0xD; /* '\0' */
+
+ tcflush(*master_fd, TCIFLUSH);
+ tcsetattr(*master_fd, TCSANOW, &newtio);
+ }
+ return 0;
+
+ERROR:
+ if (0 < *master_fd) {
+ close(*master_fd);
+ *master_fd = -1;
+ }
+
+ if (0 < *slave_fd) {
+ close(*slave_fd);
+ *slave_fd = -1;
+ }
+
+ return -1;
+}
+
+int gnss_nmea_sscanf(const char *str, char *ret,...)
+{
+ const char *ptr = str;
+ char *argv[16];
+ int argc;
+ va_list ap;
+ int i = 0;
+
+ va_start(ap, ret);
+ argc = 0;
+ argv[argc] = ret; // First arg.
+
+ do {
+ i = 0;
+ while(*ptr && *ptr != ',' && *ptr != '*') {
+ argv[argc][i++] = *ptr++;
+ }
+ ptr++; // Jump ',' or '*'
+ argc++;
+ } while((argv[argc] = va_arg(ap, char*)) != 0);
+
+ va_end(ap);
+
+ return argc;
+}
+
+void gnssStartTimer(struct uloop_timeout *timeout, int timeVal)
+{
+ //UNUSED(timeout);
+ LOGD("%s: timeVal=%lu.", __FUNCTION__, timeVal);
+ uloop_timeout_set(timeout, timeVal);
+ return;
+}
+
+void gnssStopTimer(struct uloop_timeout *timeout)
+{
+ //UNUSED(timeout);
+ uloop_timeout_cancel(timeout);
+ return;
+}
+
diff --git a/mbtk/mbtk_gnssd/gnss_utils.h b/mbtk/mbtk_gnssd/gnss_utils.h
new file mode 100755
index 0000000..319315e
--- /dev/null
+++ b/mbtk/mbtk_gnssd/gnss_utils.h
@@ -0,0 +1,34 @@
+/*
+* gnss_utils.h
+*
+* GNSS utils header.
+*
+* Author : lb
+* Date : 2024/5/28 11:27:34
+*/
+#ifndef _GNSS_UTILS_H
+#define _GNSS_UTILS_H
+#include <libubus.h>
+
+#include "mbtk_type.h"
+
+int uart_baud_get(int baud);
+
+int gnss_port_open(const char *dev, int flag, int baud, bool tty);
+
+int gnss_port_close(int fd);
+
+int gnss_set_baudrate(int fd, int baudrate);
+
+uint16 get_crc16 (const char *ptr, uint16 count);
+
+int gnss_pty_open(int *master_fd, int *slave_fd, const char *dev);
+
+int gnss_nmea_sscanf(const char *str, char *ret,...);
+
+void gnssStartTimer(struct uloop_timeout *timeout, int timeVal);
+
+void gnssStopTimer(struct uloop_timeout *timeout);
+
+
+#endif /* _GNSS_UTILS_H */