blob: 72c207c6d5cceaad941929a841111e4e1f8415da [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001/**
2 * \file mbtk_gnss.c
3 * \brief gnss module.
4 *
5 * Detailed description
6 * \Author: Sniper <js.wang@mobiletek.cn>
7 * \Version: 1.0.0
8 * \Date: 2022-03-16
9 */
10#include <stdio.h>
11#include <string.h>
12#include <strings.h>
13#include <stdlib.h>
14#include <errno.h>
15#include <termios.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <signal.h>
19#include <sys/types.h>
20#include <unistd.h>
21#include <pthread.h>
22#include <termios.h>
23#include <time.h>
24#include <sys/ioctl.h>
25#include "mbtk_type.h"
26#include "mbtk_gnss.h"
27#include "mbtk_http.h"
28#include "mbtk_log.h"
29#include "ringbuffer.h"
30
31// #define DEBUG 1
32
33#ifdef DEBUG
34 #define gnss_log(...) printf(__VA_ARGS__)
35#else
36 #define gnss_log(...)
37#endif
38
39// 默认为 9600,打开为 115200,但是 AT+MGPSCMD 会重启。
40#define BAUDRATE_115200 1
41
42#define TTFF_TEST 0
43
44#define MBTK_GNSS_DEV "/dev/ttyS2"
45
46#define MBTK_UART_RECV_BUFFER_SIZE 1024
47#define MBTK_UART_SEND_BUFFER_MAX 128
48
49/******************************************************************************
50 * 时间处理相关的宏
51 *****************************************************************************/
52// 获取当前时间
53#define GET_TIME() { gettimeofday(&time_m, NULL); \
54 time_m.tv_sec += TIMEOUT_SEC;\
55}
56// 设置从循环中退出的时间
57#define SET_TIME_OUT(x) { gettimeofday(&time_m, NULL); \
58 time_m.tv_sec += x;\
59}
60// 检测时间是否超时,超时则退出当前函数
61#define CHK_TIME() { gettimeofday(&time_n, NULL); \
62 if(time_n.tv_sec > time_m.tv_sec) { \
63 printf("\ntimeout!!!\n\n");\
64 close(fd); \
65 return ret; \
66 } \
67}
68// 检测时间是否超时,超时则退出当前循环
69#define CHK_TIME_BREAK() { gettimeofday(&time_n, NULL); \
70 if(time_n.tv_sec > time_m.tv_sec) { \
71 printf("\ntimeout!!!\n\n");\
72 break; \
73 } \
74}
75// 检测延时是否到达,到达则退出当前循环
76#define DELAY_TIME_BREAK() { gettimeofday(&time_n, NULL); \
77 if(time_n.tv_sec > time_m.tv_sec) { \
78 break; \
79 } \
80}
81
82typedef void (*gnss_msg_func_t)
83(
84 int index,
85 char *in_data,
86 void *out_ptr
87);
88
89struct mbtk_gnss_cmd_msg_t
90{
91 int index; // 序号
92 char *cmd_str; // 匹配字符
93 gnss_msg_func_t gnss_msg_func; // 回调函数
94 int is_continue; // 是否随NEMA数据一起输出
95};
96
97typedef enum
98{
99 E_MT_LOC_MSG_ID_STATUS_INFO = 0, /**< pv_data = &E_QL_LOC_STATUS_VALUE_T */
100 E_MT_LOC_MSG_ID_LOCATION_INFO, /**< pv_data = &QL_LOC_LOCATION_INFO_T */
101 E_MT_LOC_MSG_ID_SV_INFO, /**< pv_data = &QL_LOC_SV_STATUS_T */
102 E_MT_LOC_MSG_ID_NMEA_INFO, /**< pv_data = &QL_LOC_NMEA_INFO_T */
103 E_MT_LOC_MSG_ID_CAPABILITIES_INFO, /**< pv_data = &E_QL_LOC_CAPABILITIES_T */
104 E_MT_LOC_MSG_ID_AGPS_STATUS, /**< pv_data = &QL_LOC_AGPS_STATUS_T */
105 E_MT_LOC_MSG_ID_NI_NOTIFICATION, /**< pv_data = &QL_LOC_NI_NOTIFICATION_INTO_T */
106 E_MT_LOC_MSG_ID_XTRA_REPORT_SERVER, /**< pv_data = &QL_LOC_XTRA_REPORT_SERVER_INTO_T */
107}e_mt_loc_msg_id_t;
108
109typedef struct
110{
111 int64_t timestamp; /**< System Timestamp, marked for when got the nmea data */
112 int length; /**< NMEA string length. */
113 char nmea[255 + 1]; /**< NMEA string.*/
114}mopen_gnss_nmea_info_t; /* Message */
115
116struct mbtk_gnss_handle_t
117{
118 int dev_fd;
119 pthread_t uart_pthread;
120 pthread_t gnss_pthread;
121 mbtk_gnss_handler_func_t gnss_handler_func;
122 int mode; // 0 - stop, 1 - single, 2 - periodic, 3 - start
123 pthread_mutex_t _cond_mutex;
124 int reset_state;
125 int inited;
126 ring_buffer_t ring_buffer;
127 int getap_status;
128 char *rb;
129
130#if TTFF_TEST
131 pthread_t ttff_pid;
132 int location_state;
133#endif
134 /********************
135 存储handle的地址指针
136 phandle = &handle
137 handle = mbtk_gnss_handle
138 *********************/
139 uint32 *phandle; // handle的地址指针
140};
141
142#if TTFF_TEST
143struct mbtk_gnss_ttff_t
144{
145 int type;
146 int timeout_sec;
147 int test_count;
148 int average_loc_time;
149};
150
151// ttff 测试 flag
152static int location_test = 0;
153static pthread_mutex_t loc_cond_mutex_r = PTHREAD_MUTEX_INITIALIZER;
154static pthread_cond_t loc_sync_cond = PTHREAD_COND_INITIALIZER;
155#endif
156
157struct mopen_gnss_device_info_t
158{
159 int device_info_valid;
160 int usrt_bandrate;
161 char product_name[10];
162 char dev_config[6];
163 char hw_ver[6];
164 char fw_ver[32];
165 char pn[16];
166 char sn[16];
167 char nmea_ver[4];
168};
169
170static struct mopen_gnss_device_info_t mopen_gnss_device_info;
171static struct mbtk_gnss_handle_t *mbtk_gnss_handle = NULL;
172static int firmware_extren_state = 0;
173
174static char g_no_sv = 0;// 参与定位的卫星数量
175
176int mopen_gnss_get_nmea_config(uint32 h_gnss);
177int mopen_gnss_get_ant_state_info(uint32 h_gnss);
178
179static void get_gnss_time_info(int cmd, char *str, void *data);
180static void get_gnss_agnss_state(int cmd, char *str, void *data);
181static void get_gnss_device_info(int type, char *str, void *usr_ptr);
182static void gnss_uart_info(int cmd, char *str, void *data);
183static void gnss_gsa_info(int cmd, char *str, void *data);
184static int mopen_uart_change(int fd, int check);
185
186static int select_read( int fd, int timeout );
187ssize_t deal_read(int fd, void *buf, size_t count);
188
189static struct mbtk_gnss_cmd_msg_t mbtk_gnss_cmd_msg_map[] = {
190{ 1, "$OK", NULL, 0},
191{ 2, "$Fail", NULL, 0},
192{ 3, "RMC", get_gnss_time_info, 1},
193{ 4, "GGA", get_gnss_time_info, 1},
194{ 5, "$PDTINFO", get_gnss_device_info, 0},
195{ 6, "$CFGNMEA", get_gnss_device_info, 0},
196{ 7, "$CFGPRT", gnss_uart_info, 0},
197{ 8, "$CFGAID", get_gnss_agnss_state, 0},
198{ 9, "$ANTSTAT", NULL, 0},
199#if TTFF_TEST
200{10, "GSA", gnss_gsa_info, 1},
201#endif
202};
203
204/**
205 * \brief strstr_n
206 *
207 * find string return number
208 *
209 * \param param
210 * \return return type
211 */
212int strstr_n(const char *s1, const char *s2)
213{
214 int n;
215 int strlen = 0;
216
217 if(*s2)
218 {
219 while(*s1)
220 {
221 for(n = 0; *(s1+n) == *(s2 + n); n++)
222 {
223 if(!*(s2 + n + 1))
224 {
225 strlen++;
226 return strlen;
227 }
228 }
229 s1++;
230 strlen++;
231 }
232 return 0;
233 }
234 else
235 return 0;
236}
237
238/**
239 * @brief gnss_get_para_from_nmea
240 *
241 * @details 从buf里面得到第num个逗号所在的位置
242 *
243 * @param param
244 *
245 * @return 0~0xfe,代表逗号所在位置的偏移.
246 * 0xff,代表不存在第cx个逗号
247 */
248static int gnss_get_para_from_nmea(const char *data, char *out_data, int num)
249{
250 int i = 0;
251 int n[2] = {0};
252 int tmp;
253
254 // 找到第num个",",结果放到 n[0]
255 for (i = 0; i < num; ++i) {
256 tmp = strstr_n(&data[n[0]], ",");
257 if(0 == tmp) {
258 gnss_log("%s %d : error\n", __func__, __LINE__);
259 gnss_log("error: [%d] %s\n", num, data);
260 return -1;
261 }
262 n[0] += tmp;
263 }
264 if ((n[1] = strstr_n(&data[n[0]], ",")) ||
265 (n[1] = strstr_n(&data[n[0]], "*")) &&
266 (n[1] > 1)) {
267 memcpy(out_data, &data[n[0]], n[1] - 1);
268 } else {
269 gnss_log("%s %d : error [%d]\n" , __func__, __LINE__, n[1]);
270 gnss_log("error: [%d] %s\n", num, data);
271 return -1;
272 }
273
274 return 0;
275}
276/**
277* @brief get_timestamp
278*
279* @details
280*
281* @param param
282*
283* @return return type
284*/
285static time_t get_timestamp(char *time)
286{
287 char tmp_char[4] = {0};
288 struct tm* tmp_time = (struct tm*)malloc(sizeof(struct tm));
289
290 memset(tmp_time, 0, sizeof(struct tm));
291 memset(tmp_char, 0, sizeof(tmp_char));
292 memcpy(tmp_char, &time[4], 2);
293 tmp_time->tm_sec = atoi(tmp_char);
294 memcpy(tmp_char, &time[2], 2);
295 tmp_time->tm_min = atoi(tmp_char);
296 memcpy(tmp_char, &time[0], 2);
297 tmp_time->tm_hour = atoi(tmp_char);
298 memcpy(tmp_char, &time[6], 2);
299 tmp_time->tm_mday = atoi(tmp_char);
300 memcpy(tmp_char, &time[8], 2);
301 tmp_time->tm_mon = atoi(tmp_char);
302 memcpy(tmp_char, &time[10], 2);
303 tmp_time->tm_year = 100 + atoi(tmp_char);
304
305 time_t _t = mktime(tmp_time);//按当地时区解析tmp_time
306 // gnss_log("timestamp: %ld\n",_t);
307 free(tmp_time);
308
309 return _t;
310}
311/**
312 * @brief get_gnss_device_info
313 *
314 * @details 获取设备信息
315 *
316 * @param type: 5-从$PDTINFO获取
317 * 6-从$CFGNMEA获取
318 *
319 * @return return type
320 */
321static void get_gnss_device_info(int type, char *str, void *usr_ptr)
322{
323 char tmp_str[32] = {0};
324 int i, ret;
325
326 if(5 == type) // define mbtk_gnss_cmd_msg_map
327 {
328 // $PDTINFO get product info
329 char *tmp_ptr[6] = {mopen_gnss_device_info.product_name,
330 mopen_gnss_device_info.dev_config,
331 mopen_gnss_device_info.hw_ver,
332 mopen_gnss_device_info.fw_ver,
333 mopen_gnss_device_info.pn,
334 mopen_gnss_device_info.sn
335 };
336 for (i = 0; i < 6; ++i) {
337 memset(tmp_str, 0, sizeof(tmp_str));
338 // get product name
339 ret = gnss_get_para_from_nmea(str, tmp_str, i + 1);
340 if(ret)
341 continue;
342 memcpy(tmp_ptr[i], tmp_str, strlen(tmp_str));
343 }
344 gnss_log("*************************\n");
345 gnss_log("-Pn: %s\n dc: %s\n hv: %s\n fw: %s\n pn: %s\n sn: %s\n ",
346 mopen_gnss_device_info.product_name,
347 mopen_gnss_device_info.dev_config,
348 mopen_gnss_device_info.hw_ver,
349 mopen_gnss_device_info.fw_ver,
350 mopen_gnss_device_info.pn,
351 mopen_gnss_device_info.sn);
352 }
353 if(6 == type) // define mbtk_gnss_cmd_msg_map
354 {
355 // $CFGNMEA get nmea version
356 memset(tmp_str, 0, sizeof(tmp_str));
357 ret = gnss_get_para_from_nmea(str, tmp_str, 1);
358 if(ret)
359 return;
360 memcpy(mopen_gnss_device_info.nmea_ver, tmp_str, strlen(tmp_str));
361 mopen_gnss_device_info.device_info_valid = TRUE;
362 }
363}
364
365static short int from_hex(char a)
366{
367 if (a >= 'A' && a <= 'F')
368 return a - 'A' + 10;
369 else if (a >= 'a' && a <= 'f')
370 return a - 'a' + 10;
371 else
372 return a - '0';
373}
374
375static int str_to_hex(char *str)
376{
377 unsigned char str_len = strlen(str);
378 int i;
379 int ret = 0;
380
381 for (i = 0; i < str_len; ++i) {
382 ret = ret * 16 + from_hex(str[i]);
383 }
384 return ret;
385}
386
387static void get_gnss_agnss_state(int cmd, char *str, void *data)
388{
389 int ret;
390 char tmp_str[10] = {0};
391 int agps;
392 static int count = 0;
393
394 ret = gnss_get_para_from_nmea(str, tmp_str, 2);
395 if(ret) {
396 printf("\n%s[%d] error!\n" , __FUNCTION__, __LINE__);
397 }
398 agps = str_to_hex(tmp_str);
399 gnss_log("\n%s[%d] agnss: %s[%x]\n" , __FUNCTION__, __LINE__, tmp_str, agps);
400 if(0 == agps && count < 5) {
401 mopen_gnss_get_aidinfo(mbtk_gnss_handle);
402 count++;
403 } else {
404 printf("\nagnss: %s\n", str);
405 count = 0;
406 }
407 // $CFGAID,0,00000000,00000000,00*3E
408}
409// 1节=1海里/小时=1.852公里/小时
410/**
411 * @brief function description
412 *
413 * @details 获取位置信息
414 *
415 * @param type: 1-从$RMC获取
416 * 2-从$GGA获取
417 * @return return type
418 */
419static void get_gnss_loc_info(int type, char *str,
420 struct mbtk_gnss_location_info_t *_mopen_location_info)
421
422{
423 char tmp_str[32] = {0};
424 int ret;
425
426 if(1 == type)
427 {
428 // $PDTINFO get product info
429 memset(tmp_str, 0, sizeof(tmp_str));
430 // get product name
431 ret = gnss_get_para_from_nmea(str, tmp_str, 7);
432 if(ret)
433 return;
434 _mopen_location_info->speed = atof(tmp_str);
435 memset(tmp_str, 0, sizeof(tmp_str));
436 // get product name
437 ret = gnss_get_para_from_nmea(str, tmp_str, 8);
438 if(ret)
439 return;
440 _mopen_location_info->bearing = atof(tmp_str);
441 }
442 else if(2 == type)
443 {
444 // $XXGGA get product info
445 memset(tmp_str, 0, sizeof(tmp_str));
446 // get product name
447 ret = gnss_get_para_from_nmea(str, tmp_str, 2);
448 if(ret)
449 return;
450 _mopen_location_info->latitude = atof(tmp_str);
451 memset(tmp_str, 0, sizeof(tmp_str));
452 // get product name
453 ret = gnss_get_para_from_nmea(str, tmp_str, 4);
454 if(ret)
455 return;
456 _mopen_location_info->longitude = atof(tmp_str);
457 memset(tmp_str, 0, sizeof(tmp_str));
458 // get product name
459 ret = gnss_get_para_from_nmea(str, tmp_str, 9);
460 if(ret)
461 return;
462 _mopen_location_info->altitude = atof(tmp_str);
463 }
464}
465
466static void get_gnss_time_info(int cmd, char *str, void *data)
467{
468 int ret;
469 char param[36] = {0};
470 struct mbtk_gnss_location_info_t *mopen_location_info_ptr = (struct mbtk_gnss_location_info_t *)data;
471
472 if (3 == cmd) {
473 memset(param, 0, sizeof(param));
474 // get time
475 ret = gnss_get_para_from_nmea(str, param, 1);
476 if(ret)
477 return;
478 // get date
479 ret = gnss_get_para_from_nmea(str, &param[6], 9);
480 if(ret)
481 return;
482
483 mopen_location_info_ptr->timestamp = get_timestamp(param);
484 get_gnss_loc_info(1, str, mopen_location_info_ptr);
485 } else if(4 == cmd) /* GGA */{
486 get_gnss_loc_info(2, str, mopen_location_info_ptr);
487 ret = gnss_get_para_from_nmea(str, param, 7);
488 if(ret)
489 return;
490 char no_sv = (char)atoi(param);
491 gnss_log("SV number: %d, %d\n", g_no_sv, no_sv);
492 /*
493 只能在临时固件下,才能获取APdata星历数据
494 在6颗卫星保存文件,每增加2颗保存一次。
495 */
496 if (1 == firmware_extren_state &&
497 g_no_sv < (no_sv - 1) && no_sv > 5) {
498
499 g_no_sv = no_sv;
500 mbtk_gnss_get_ap_data();
501 }
502 }
503}
504
505static void gnss_uart_info(int cmd, char *str, void *data)
506{
507 int ret;
508 char tmp_str[12] = {0};
509
510 // $CFGPRT,1,h0,9600,129,3*57
511 ret = gnss_get_para_from_nmea(str, tmp_str, 3);
512 if(ret)
513 return;
514 mopen_gnss_device_info.usrt_bandrate = atoi(tmp_str);
515 gnss_log("CFGPRT: %s\n", str);
516 gnss_log("Uart bandrate: %d\n" , mopen_gnss_device_info.usrt_bandrate);
517 gnss_log("*************************\n");
518}
519/**
520 * \brief function description
521 *
522 * Detailed 处理gnss数据
523 *
524 * \param param
525 * \return return type
526 */
527static void process_gnss_callback(struct mbtk_gnss_handle_t *handle,
528 const char *data, int data_len)
529{
530 int ret = 0;
531 int i = 0;
532 static struct mbtk_gnss_location_info_t mopen_location_info;
533 static int64_t tmp_time = 0;
534 mopen_gnss_nmea_info_t nmea_info;
535
536 memset(&nmea_info, 0, sizeof(nmea_info));
537 if(0 == tmp_time)
538 memset(&mopen_location_info, 0, sizeof(mopen_location_info));
539
540 for (i = 0;
541 i < (sizeof(mbtk_gnss_cmd_msg_map) / sizeof(struct mbtk_gnss_cmd_msg_t));
542 ++i) {
543 if(strstr_n(data, mbtk_gnss_cmd_msg_map[i].cmd_str)) {
544 if(mbtk_gnss_cmd_msg_map[i].gnss_msg_func)
545 mbtk_gnss_cmd_msg_map[i].gnss_msg_func(mbtk_gnss_cmd_msg_map[i].index,
546 data, &mopen_location_info);
547 break;
548 }
549 }
550 if(0 == mbtk_gnss_cmd_msg_map[i].is_continue)
551 return;
552
553 tmp_time = mopen_location_info.timestamp;
554 nmea_info.timestamp = mopen_location_info.timestamp;
555 nmea_info.length = data_len;
556 memcpy(nmea_info.nmea, data, data_len);
557 gnss_log("nmea:[%d] %s", data_len, data);
558 if(handle->gnss_handler_func && handle->mode == 3 &&
559 nmea_info.timestamp)
560 handle->gnss_handler_func(handle, E_MT_LOC_MSG_ID_NMEA_INFO, &nmea_info, NULL);
561 if(handle->gnss_handler_func && handle->mode == 1 &&
562 mopen_location_info.latitude &&
563 mopen_location_info.longitude &&
564 mopen_location_info.altitude &&
565 mopen_location_info.timestamp &&
566 mopen_location_info.speed)
567 {
568 handle->gnss_handler_func(handle, E_MT_LOC_MSG_ID_LOCATION_INFO, &mopen_location_info, NULL);
569 memset(&mopen_location_info, 0, sizeof(mopen_location_info));
570 }
571
572 return;
573}
574
575/**
576 * \brief get_gnss_from_str
577 *
578 * Detailed 从串口数据解析出每条消息
579 *
580 * \param param
581 * \return return type
582 */
583static int get_gnss_from_str(struct mbtk_gnss_handle_t *handle,
584 const char *data, int data_len)
585{
586 char *tail = NULL;
587 static int seek = 0;
588 // 等待 OK, 如果20条结果没有等到,就异常
589 static int reset_count = 0;
590 int i = 0, ret = -1;
591
592 if (handle->reset_state)
593 {
594 // 等待 reset 回复的 OK
595 if(0 != memcmp(data, "$OK", 3) && reset_count < 20) {
596 printf("gnss reset invalid: [%s]\n", data);
597 reset_count++;
598 return -1;
599 }
600 if (reset_count > 19) {
601 printf("%s: device reset timeout!!!\n", __FUNCTION__);
602 LOGI("%s: device reset timeout!!!\n", __FUNCTION__);
603 }
604 reset_count = 0;
605 gnss_log("reset ok: %s\n", data);
606#if BAUDRATE_115200
607 ret = mopen_uart_change(handle->dev_fd, 0);
608 if(ret) {
609 printf("reset Uart set 115200 error\n");
610 }
611#endif
612 pthread_mutex_lock(&handle->_cond_mutex);
613 handle->reset_state = 0;
614 pthread_mutex_unlock(&handle->_cond_mutex);
615 }
616
617 if((data[0] == '$' || data[0] == '#') &&
618 data[data_len - 1] == '\n' &&
619 data_len < 128) {
620 process_gnss_callback(handle, data, data_len);
621 } else {
622 gnss_log("nmea error: %s\n", data);
623 }
624
625 return 1;
626}
627
628void mopen_gnss_NonBlock(int fd, int cmd)
629{
630 int flags;
631
632 flags = fcntl(fd, F_GETFL, 0);
633 if(cmd)
634 flags |= O_NONBLOCK;
635 else
636 flags &= ~O_NONBLOCK;
637
638 fcntl(fd, F_SETFL, flags);
639}
640
641int set_baudrate(int fd, int baudrate)
642{
643 struct termios options, oldtio;
644
645 if(fcntl(fd, F_SETFL, 0) < 0) {
646 printf("fcntl failed!\n");
647 return -1;
648 }
649
650 if(tcgetattr(fd, &oldtio) != 0) {
651 printf("setup serial error!\n");
652 return -1;
653 }
654
655 /* Get the current options for the port... */
656 tcgetattr(fd, &options);
657
658 /* Set the baud rates to baudrate... */
659 cfsetispeed(&options,baudrate);
660 cfsetospeed(&options,baudrate);
661 tcsetattr(fd, TCSANOW, &options);
662
663 if (0 != tcgetattr(fd, &options))
664 {
665 printf("get options error!\n");
666 return -1;
667 }
668
669 /*
670 * 8bit Data,no partity,1 stop bit...
671 */
672 options.c_cflag &= ~PARENB;//无奇偶校验
673 options.c_cflag &= ~CSTOPB;//停止位,1位
674 options.c_cflag &= ~CSIZE; //数据位的位掩码
675 options.c_cflag |= CS8; //数据位,8位
676
677 cfmakeraw(&options);
678
679 /*
680 * Set the new options for the port...
681 */
682 if (tcsetattr(fd, TCSANOW, &options) != 0)
683 {
684 printf("setup serial error!\n");
685 return -1 ;
686 }
687
688 return 0 ;
689}
690/*
691 自适应波特率设置
692 */
693static int auto_set_uart_baudrate(int fd)
694{
695 char rbuf[512];
696 int rByte = 0;
697 int b[3] = {B115200, B9600, 0};
698 int ret = B9600;
699 struct timeval time_m, time_n;
700 // 时间超时标志
701 int timeout_sign = 0;
702 // 先测试默认的9600波特率
703 SET_TIME_OUT(3);
704 do {
705 gettimeofday(&time_n, NULL);
706 if(time_n.tv_sec > time_m.tv_sec) {
707 printf("Baudrate--test-9600--- timeout!\n");
708 if(timeout_sign)
709 break;
710 set_baudrate(fd, B115200);
711 ret = B115200;
712 timeout_sign = 1;
713 SET_TIME_OUT(3);
714 continue;
715 }
716
717 if(select_read(fd, 1) > 0)
718 usleep(50000);
719 else
720 continue;
721
722 rByte = deal_read(fd,&rbuf,sizeof(rbuf));
723 if(rByte > 0) {
724 gnss_log("Auto Baudrate[%d]%s\n", rByte, rbuf);
725 if(strstr(rbuf, "$"))
726 return ret;
727 memset(rbuf, 0, sizeof(rbuf));
728 } else {
729 printf("*** read error\n");
730 }
731 }while(1);
732
733 return -1;
734}
735
736int mopen_gnss_open(char *dev, int baudrate)
737{
738 int ret;
739 int fd = 0;
740
741 fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
742 if(fd < 0) {
743 return -1;
744 }
745 gnss_log("curent dev: %s, fd: %d \n", dev, fd);
746
747 if(baudrate) {
748 gnss_log("set baudrate: %d \n", baudrate);
749 ret = set_baudrate(fd, baudrate);
750 if(-1 == ret) {
751 close(fd);
752 return -1;
753 }
754 } else {
755 set_baudrate(fd, B9600);
756 }
757
758 return fd;
759}
760
761static int mopen_gnss_read(int fd, char* buf, unsigned int buf_len)
762{
763 buf_len=(buf_len > MBTK_UART_RECV_BUFFER_SIZE ? MBTK_UART_RECV_BUFFER_SIZE : buf_len);
764 return read(fd, buf, buf_len);
765}
766
767int mopen_gnss_write(int fd, const char* buf, unsigned int buf_len)
768{
769 size_t size;
770 size_t size_to_wr;
771 ssize_t size_written;
772 if(MBTK_UART_SEND_BUFFER_MAX < buf_len)
773 {
774 return -1;
775 }
776 for(size = 0; size < buf_len;)
777 {
778 size_to_wr = buf_len - size;
779 if( size_to_wr > MBTK_UART_SEND_BUFFER_MAX)
780 size_to_wr = MBTK_UART_SEND_BUFFER_MAX;
781
782 size_written = write(fd, &buf[size], size_to_wr);
783 if (size_written==-1)
784 {
785 return -1;
786 }
787 gnss_log("send cmd: %s", &buf[size]);
788 size += size_written;
789 if(size_written != size_to_wr)
790 {
791 return size;
792 }
793 }
794 return size;
795}
796
797int mopen_gnss_close(int fd)
798{
799 return close(fd);
800}
801
802static void gnss_info_pthread(void* hdl)
803{
804 struct mbtk_gnss_handle_t *gnss_handle = (struct mbtk_gnss_handle_t *)hdl;
805 int ret = 0, i;
806 char tmp;
807 char tmp_arr[128] = {0};
808
809 pthread_detach(pthread_self());
810
811 memset(tmp_arr, 0, sizeof(tmp_arr));
812 while(mbtk_gnss_handle->inited)
813 {
814 for (i = 0; i < 256; ++i) {
815 if (0 == mbtk_gnss_handle->inited)
816 goto exit;
817 ret = ring_buffer_peek(&gnss_handle->ring_buffer, &tmp, i);
818 if (0 == ret) {
819 usleep(300000);
820 gnss_log("ring_buffer_peek ringbuffer read error\n");
821 i--;
822 continue;
823 }
824 if (tmp == '\n') {
825 break;
826 }
827 }
828
829 if (i > (256 - 2))
830 continue;
831
832 ret = ring_buffer_dequeue_arr(&gnss_handle->ring_buffer, tmp_arr, i + 1);
833
834 if(ret > 0 && 0 == mbtk_gnss_handle->getap_status) {
835 // gnss_log("NEMA:[%d] %s", ret, tmp_arr);
836 get_gnss_from_str(gnss_handle, tmp_arr, ret);
837 memset(tmp_arr, 0, sizeof(tmp_arr));
838 } else {
839 gnss_log("ringbuffer read error\n");
840 }
841 usleep(5000);
842 }
843 exit:
844 pthread_exit(NULL);
845}
846
847static void gnss_uart_pthread(void* hdl)
848{
849 struct mbtk_gnss_handle_t *gnss_handle = (struct mbtk_gnss_handle_t *)hdl;
850 int ret = 0;
851 char buf[MBTK_UART_RECV_BUFFER_SIZE] = {0};
852
853 pthread_detach(pthread_self());
854
855 memset(buf, 0, sizeof(buf));
856 while(mbtk_gnss_handle->inited)
857 {
858 while(mbtk_gnss_handle->getap_status){
859 // 在读AP_DATA星历时,不能输出NMEA
860 printf("g");
861 usleep(100000);
862 }
863 ret = mopen_gnss_read(gnss_handle->dev_fd, buf, MBTK_UART_RECV_BUFFER_SIZE);
864 if(ret > 0) {
865 // gnss_log("read: [%d] %s\n", ret, buf);
866 ring_buffer_queue_arr(&gnss_handle->ring_buffer, buf, ret);
867 memset(buf, 0, sizeof(buf));
868 } else {
869 gnss_log("read error\n");
870 }
871 usleep(100000);
872 }
873
874 pthread_exit(NULL);
875}
876
877ssize_t deal_read(int fd, void *buf, size_t count)
878{
879 int ret = 0;
880
881#if 0
882 ret = read(fd, buf, count);
883 return ret;
884#else
885 while (1)
886 {
887 ret = read(fd, buf, count);
888 if (ret == 0) {
889 printf("read serial return 0, please check serial device.\n");
890 exit(-5);
891 }
892 if(ret < 0) {
893 if ((errno == EAGAIN) || (errno == EINTR)) {
894 printf("read serial return -1, errno = %d, retry.\n", errno);
895 continue;
896 } else {
897 printf("read serial return -1, errno = %d, please check serial device.\n", errno);
898 exit(-5);
899 }
900 }
901 return ret;
902 }
903#endif
904}
905
906static int select_read( int fd, int timeout ) //1ms
907{
908 fd_set set;
909 struct timeval t;
910 int ret;
911 int i = timeout;
912
913 do {
914 FD_ZERO(&set);
915 FD_SET(fd, &set);
916 t.tv_sec = 0;
917 t.tv_usec = 100;
918
919 ret = select(FD_SETSIZE, &set, NULL, NULL, &t );
920 if(ret == 0) continue;
921 if(ret < 0 && errno == EINTR)continue;
922 else return ret;
923 } while(i--);
924
925 return ret;
926}
927
928// check: 是否需要校验
929static int mopen_uart_change(int fd, int check)
930{
931 int rByte = 0, i = 20;
932 char name[32];
933 char rbuf[1024];
934
935 sprintf(name,"$CFGPRT,1,h0,115200,129,3\r\n");
936 rByte = write( fd, name, strlen(name));
937 tcdrain(fd);
938
939 set_baudrate(fd, B115200);
940 usleep(200000);
941 tcflush(fd, TCIFLUSH);
942
943 if (0 == check)
944 return 0;
945 do{
946 rByte = 0;
947 memset(rbuf, 0, sizeof(rbuf));
948 if(select_read(fd, 1) > 0) {
949 rByte = deal_read(fd, &rbuf, sizeof(rbuf) - 1);
950 rbuf[rByte] = 0;
951 gnss_log("%s: %s", __FUNCTION__, rbuf);
952 }
953 if(strstr(rbuf, "$")) {
954 return 0;
955 } else {
956 gnss_log("%d rByte = %d, [%s]\n", 20 - i, rByte, rbuf);
957 }
958 usleep(5000 * 100);
959 }while(i--);
960
961 return -1;
962}
963
964#define GPS_DEV "/sys/devices/soc.0/d4000000.apb/mbtk-dev-op/gps_power"
965
966static int mopen_open_gps(int state)
967{
968 int fd, ret;
969 char s[4] = "on";
970 fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644);
971 if(fd < 0) {
972 LOGE("[%s] file [%s] open error\n", __FUNCTION__, GPS_DEV);
973 return -1;
974 }
975 if(0 == state)
976 {
977 memcpy(s, "off", 3);
978 }
979 ret = write(fd, s, 4);
980 if (ret < 0) {
981 LOGE("%s: error writing to file!\n", __FUNCTION__);
982 close(fd);
983 return -2;
984 }
985
986 close(fd);
987 return 0;
988}
989
990int mbtk_gnss_client_init(uint32 *ph_gnss)
991{
992 int ret;
993
994 if(ph_gnss == NULL) {
995 printf("ARG error or has inited.");
996 return -1;
997 }
998
999 if (mbtk_gnss_handle) {
1000 printf("GNSS has inited.");
1001 *ph_gnss = (uint32)mbtk_gnss_handle;
1002 return 0;
1003 }
1004 mbtk_gnss_handle = malloc(sizeof(struct mbtk_gnss_handle_t));
1005 if(NULL == mbtk_gnss_handle)
1006 {
1007 printf("malloc memory error\n");
1008 return -3;
1009 }
1010 memset(mbtk_gnss_handle, 0, sizeof(struct mbtk_gnss_handle_t));
1011 memset(&mopen_gnss_device_info, 0, sizeof(mopen_gnss_device_info));
1012
1013 ret = mopen_open_gps(1);
1014 if(ret) {
1015 printf("GNSS open init error\n");
1016 return -4;
1017 }
1018 sleep(1);
1019
1020 mbtk_gnss_handle->dev_fd = mopen_gnss_open(MBTK_GNSS_DEV, 0);
1021
1022 printf("Gnss Config Uart Baudrate Start -> \n");
1023 ret = auto_set_uart_baudrate(mbtk_gnss_handle->dev_fd);
1024 if(-1 == ret) {
1025 ret = -2;
1026 goto err;
1027 } else if (B9600 == ret) {
1028 ret = mopen_uart_change(mbtk_gnss_handle->dev_fd, 1);
1029 if(ret)
1030 {
1031 printf("GNSS Uart set B115200 error\n");
1032 mopen_gnss_close(mbtk_gnss_handle->dev_fd);
1033 mopen_open_gps(0);
1034 return -1;
1035 }
1036 }
1037 printf("Gnss Config Uart Baudrate Successful.\n");
1038
1039 mbtk_gnss_handle->rb = malloc(MBTK_UART_RECV_BUFFER_SIZE);
1040 if(NULL == mbtk_gnss_handle->rb)
1041 {
1042 printf("malloc memory error\n");
1043 return -1;
1044 }
1045
1046 ring_buffer_init(&mbtk_gnss_handle->ring_buffer,
1047 mbtk_gnss_handle->rb,
1048 MBTK_UART_RECV_BUFFER_SIZE);
1049
1050 mbtk_gnss_handle->inited = 1;
1051
1052 pthread_mutex_init(&mbtk_gnss_handle->_cond_mutex, NULL);
1053 pthread_create(&mbtk_gnss_handle->uart_pthread, NULL, (void *)gnss_uart_pthread, (void *)mbtk_gnss_handle);
1054 pthread_create(&mbtk_gnss_handle->gnss_pthread, NULL, (void *)gnss_info_pthread, (void *)mbtk_gnss_handle);
1055
1056 mopen_gnss_get_ant_state_info((uint32)mbtk_gnss_handle);
1057 mopen_gnss_get_device_info((uint32)mbtk_gnss_handle);
1058 mopen_gnss_get_nmea_config((uint32)mbtk_gnss_handle);
1059 mopen_gnss_get_uart((uint32)mbtk_gnss_handle);
1060 mopen_gnss_get_aidinfo((uint32)mbtk_gnss_handle);
1061
1062 *ph_gnss = (uint32)mbtk_gnss_handle;
1063 mbtk_gnss_handle->phandle = ph_gnss;
1064
1065 return 0;
1066 err:
1067 mopen_gnss_close(mbtk_gnss_handle->dev_fd);
1068 mopen_open_gps(0);
1069 firmware_extren_state = 0;
1070 if (mbtk_gnss_handle) free(mbtk_gnss_handle);
1071 mbtk_gnss_handle = NULL;
1072
1073 return ret;
1074}
1075static int _kill_pthread(pthread_t pid, int kill)
1076{
1077 int ret;
1078
1079 if (kill) {
1080 ret = pthread_cancel(pid);
1081 pthread_join(pid, NULL);
1082 }
1083 do{
1084 ret = pthread_kill(pid, 0);
1085 if(ret == ESRCH)
1086 gnss_log("The specified thread does not exist or has terminated\n");
1087 else if(ret == EINVAL)
1088 gnss_log("Useless signal\n");
1089 else
1090 gnss_log("The thread exists\n");
1091 usleep(100000);
1092 }while(0 == ret);
1093
1094 return 0;
1095}
1096int mbtk_gnss_client_deinit(uint32 h_gnss)
1097{
1098 int ret;
1099 struct mbtk_gnss_handle_t *gnss_handle = (struct mbtk_gnss_handle_t *)h_gnss;
1100
1101 if(h_gnss == NULL)
1102 {
1103 gnss_log("ARG error or not inited.");
1104 return -1;
1105 }
1106 gnss_handle->inited = 0;
1107#if TTFF_TEST
1108 // ttff测试线程在运行,而且不是临时固件模式
1109 if (gnss_handle->ttff_pid &&
1110 0 == firmware_extren_state &&
1111 0 == location_test) {
1112 gnss_log("kill thread ttff.\n");
1113 _kill_pthread(gnss_handle->ttff_pid, 1);
1114 }
1115#endif
1116 gnss_log("kill thread info 0.\n");
1117 _kill_pthread(gnss_handle->gnss_pthread, 0);
1118
1119 gnss_log("kill thread uart.\n");
1120 _kill_pthread(gnss_handle->uart_pthread, 0);
1121
1122 mopen_gnss_close(gnss_handle->dev_fd);
1123
1124 ret = mopen_open_gps(0);
1125 if(ret)
1126 {
1127 printf("GNSS close init error\n");
1128 return -1;
1129 }
1130
1131 firmware_extren_state = 0;
1132 if (gnss_handle->rb) free(gnss_handle->rb);
1133 free(h_gnss);
1134 mbtk_gnss_handle = NULL;
1135
1136 return 0;
1137}
1138
1139int mopen_gnss_send_cmd(uint32 h_gnss, const char *cmd, int cmd_len)
1140{
1141 struct mbtk_gnss_handle_t *gnss_handle = (struct mbtk_gnss_handle_t *)h_gnss;
1142 return mopen_gnss_write(gnss_handle->dev_fd, cmd, cmd_len);
1143}
1144
1145/**
1146 * \brief mbtk_gnss_dev_reset
1147 *
1148 * Detailed description
1149 *
1150 * \param
1151 * type: 0 软件复位
1152 * 1 芯片级复位(看门狗)
1153 * 2 板级复位
1154 * 3 接收机停止
1155 * mode :
1156 * 0 : 热启动
1157 * 1 : 温启动
1158 * 2 : 冷启动
1159 * \return return type
1160 */
1161int mbtk_gnss_dev_reset(uint32 h_gnss, int type, int mode)
1162{
1163 int ret;
1164 struct mbtk_gnss_handle_t *handle = (struct mbtk_gnss_handle_t *)h_gnss;
1165 // h00 热启动
1166 // h01 温启动
1167 // h85 冷启动
1168 char send_buf[24] = {0};
1169
1170 if(0 == h_gnss){
1171 printf("%s handler invalid.\n", __func__);
1172 return -1;
1173 }
1174
1175 if (1 == handle->reset_state) {
1176 printf("%s already reset_state.\n", __func__);
1177 return -2;
1178 }
1179
1180 if (0 == mode || 1 == mode) {
1181 snprintf(send_buf, sizeof(send_buf), "$RESET,%d,h0%d\r\n", type, mode);
1182 } else if (2 == mode) {
1183 snprintf(send_buf, sizeof(send_buf), "$RESET,%d,h85\r\n", type);
1184 } else if (3 == mode) {
1185 snprintf(send_buf, sizeof(send_buf), "$RESET,%d,hFF\r\n", type);
1186 } else {
1187 printf("%s reset mode invalid.\n", __func__);
1188 return -2;
1189 }
1190
1191 if ( 1 == firmware_extren_state ) {
1192 if (mode > 1) {
1193 mbtk_gnss_firmware_update();
1194 } else {
1195 memset(send_buf, 0, sizeof(send_buf));
1196 // 在有GLONASS固件的情况下,冷启动指令为: $CFGSYS,H101
1197 // 只发$RESET,0,hFF, 会重置波特率,待验证
1198 snprintf(send_buf, sizeof(send_buf), "$CFGSYS,H101\r\n");
1199 }
1200 }
1201
1202 gnss_log("%s : %s\n", __FUNCTION__, send_buf);
1203 LOGI("%s : %s", __FUNCTION__, send_buf);
1204 pthread_mutex_lock(&handle->_cond_mutex);
1205 handle->reset_state = 1;
1206 pthread_mutex_unlock(&handle->_cond_mutex);
1207 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1208 if(ret < 0)
1209 {
1210 printf("%s %d FAIL. ret:%d\n", __FUNCTION__, __LINE__, ret);
1211 return -1;
1212 }
1213
1214 // 加载GLONASS固件后,波特率为115200
1215 if ( 0 == firmware_extren_state ) {
1216 set_baudrate(handle->dev_fd, B9600);
1217 gnss_log("%s : set B9600\n", __FUNCTION__);
1218 }
1219
1220 return 0;
1221}
1222
1223int mopen_gnss_get_device_info(uint32 h_gnss)
1224{
1225 int ret;
1226 char *send_buf = "$PDTINFO\r\n";
1227 if(0 == h_gnss)
1228 {
1229 printf("%s handler invalid.\n", __func__);
1230 return -1;
1231 }
1232
1233 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1234 if(ret < 0)
1235 {
1236 printf("mopen_gnss_client_init FAIL. ret:%d\n",ret);
1237 return -1;
1238 }
1239
1240 return 0;
1241}
1242/**
1243 * @brief mopen_gnss_set_system_config
1244 *
1245 * @details 设置卫星系统配置
1246 *
1247 * @param mode
1248 * 0 -> H01(1) –GPS L1+SBAS+QZSS
1249 * 1 -> H10 – BDS B1
1250 * 2 -> H101 2 – GPS+GLONASS+GALILEO+SBAS+QZSS
1251 * 3 -> H11 3 – GPS+BDS+GALILEO+SBAS+QZSS
1252 * @return return type
1253 */
1254int mbtk_gnss_set_system_config(uint32 h_gnss, int mode)
1255{
1256 int ret;
1257 char send_buf[20] = "$CFGSYS,H10\r\n";
1258 char *str_mode[4] = {"H01", "H10", "H101", "H11"};
1259 if(0 == h_gnss)
1260 {
1261 printf("%s handler invalid.\n", __func__);
1262 return -1;
1263 }
1264 if( mode > 3 )
1265 {
1266 printf("%s param invalid.\n", __func__);
1267 return -2;
1268 }
1269 snprintf(send_buf, sizeof(send_buf), "$CFGSYS,%s\r\n", str_mode[mode]);
1270 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1271 if(ret < 0)
1272 {
1273 printf("%s FAIL. ret:%d\n", __FUNCTION__, ret);
1274 return -3;
1275 }
1276
1277 return 0;
1278}
1279/**
1280 * @brief mopen_gnss_set_nema_config
1281 *
1282 * @details 设定NMEA 配置
1283 * 输出的NMEA 协议版本
1284 * h30 - 在 NMEA 标准 version 3.0 基础上扩展北斗相关的语句(NMEA 3.0)
1285 * h51 - 在标准NMEA4.1 基础上扩展北斗相关语(NMEA 4.1)
1286 * 默认配置: h51
1287 *
1288 * @param mode
1289 * 0 -> h30
1290 * 1 -> h51
1291 *
1292 * @return return type
1293 */
1294int mbtk_gnss_set_nema_config(uint32 h_gnss, int mode)
1295{
1296 int ret;
1297 char send_buf[16] = "$CFGNMEA,h30\r\n";
1298 if(0 == h_gnss)
1299 {
1300 printf("%s handler invalid.\n", __func__);
1301 return -1;
1302 }
1303
1304 if (mode) {
1305 send_buf[10] = '5';
1306 send_buf[11] = '1';
1307 }
1308 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1309 if(ret < 0)
1310 {
1311 printf("%s FAIL. ret:%d\n", __FUNCTION__, ret);
1312 return -3;
1313 }
1314
1315 return 0;
1316}
1317int mopen_gnss_aidpos(uint32 h_gnss)
1318{
1319 int ret;
1320 char *send_buf = "$AIDPOS,4002.229934,N,11618.096855,E,37.254\r\n";
1321 if(0 == h_gnss)
1322 {
1323 printf("%s handler invalid.\n", __func__);
1324 return -1;
1325 }
1326
1327 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1328 if(ret < 0)
1329 {
1330 printf("mopen_gnss_client_init FAIL. ret:%d\n",ret);
1331 return -1;
1332 }
1333 return 0;
1334}
1335/**
1336 * @brief mopen_gnss_get_aidinfo
1337 *
1338 * @details 查询辅助数据状态
1339 * $CFGAID,0,D7FBFBDF,00000000,08*47
1340 * @param param
1341 *
1342 * @return return type
1343 */
1344int mopen_gnss_get_aidinfo(uint32 h_gnss)
1345{
1346 int ret;
1347 // char *send_buf = "$AIDINFO\r\n";
1348 char *send_buf = "$CFGAID,0\r\n";
1349 if(0 == h_gnss)
1350 {
1351 printf("%s handler invalid.\n", __func__);
1352 return -1;
1353 }
1354
1355 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1356 if(ret < 0)
1357 {
1358 printf("%s FAIL. ret:%d\n", __FUNCTION__, ret);
1359 return -1;
1360 }
1361 return 0;
1362}
1363/**
1364 * @brief mopen_gnss_get_uart
1365 *
1366 * @details get uart config info.
1367 * $CFGPRT,1,h0,9600,129,3*57
1368 *
1369 * @param param
1370 *
1371 * @return return type
1372 */
1373int mopen_gnss_get_uart(uint32 h_gnss)
1374{
1375 int ret;
1376 char *send_buf = "$CFGPRT,1\r\n";
1377 // char *send_buf = "$CFGPRT,2\r\n";
1378 if(0 == h_gnss)
1379 {
1380 printf("%s handler invalid.\n", __func__);
1381 return -1;
1382 }
1383
1384 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1385 if(ret < 0)
1386 {
1387 printf("mopen_gnss_client_init FAIL. ret:%d\n",ret);
1388 return -1;
1389 }
1390 return 0;
1391}
1392
1393int mopen_gnss_set_uart(uint32 h_gnss, int baudrate)
1394{
1395 int ret;
1396 char send_buf[28] = {0};
1397 // char *send_buf = "$CFGPRT,1,h0,9600,1,3\r\n";
1398
1399 if(0 == h_gnss)
1400 {
1401 printf("%s handler invalid.\n", __func__);
1402 return -1;
1403 }
1404 sprintf(send_buf, "$CFGPRT,1,h0,%d,1,3\r\n", baudrate);
1405 gnss_log("%s %s", __FUNCTION__, send_buf);
1406 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1407 if(ret < 0)
1408 {
1409 printf("mopen_gnss_client_init FAIL. ret:%d\n",ret);
1410 return -1;
1411 }
1412 return 0;
1413}
1414
1415int mopen_gnss_get_msg_output(uint32 h_gnss)
1416{
1417 int ret;
1418 char *send_buf = "$CFGMSG,0,1\r\n"; // msg class, msg id
1419
1420 if(0 == h_gnss)
1421 {
1422 printf("%s handler invalid.\n", __func__);
1423 return -1;
1424 }
1425 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1426 if(ret < 0)
1427 {
1428 printf("%s FAIL. ret:%d\n", __func__, ret);
1429 return -1;
1430 }
1431 return 0;
1432}
1433
1434int mopen_gnss_set_msg_output(uint32 h_gnss)
1435{
1436 int ret;
1437 char *send_buf = "$CFGMSG,0,1,1\r\n";// msg class, msg id, msg switch
1438
1439 if(0 == h_gnss)
1440 {
1441 printf("%s handler invalid.\n", __func__);
1442 return -1;
1443 }
1444 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1445 if(ret < 0)
1446 {
1447 gnss_log("%s FAIL. ret:%d\n", __func__, ret);
1448 return -1;
1449 }
1450 return 0;
1451}
1452
1453int mopen_gnss_set_lowpower(uint32 h_gnss)
1454{
1455 int ret;
1456 char *send_buf = "$CFGLOWPOWER,0\r\n";// 0 - nomale, 1 - lowpower
1457
1458 if(0 == h_gnss)
1459 {
1460 printf("%s handler invalid.\n", __func__);
1461 return -1;
1462 }
1463 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1464 if(ret < 0)
1465 {
1466 gnss_log("%s FAIL. ret:%d\n", __func__, ret);
1467 return -1;
1468 }
1469 return 0;
1470}
1471
1472int mopen_gnss_get_ant_state_info(uint32 h_gnss)
1473{
1474 int ret;
1475 char *cmd1_buf = "$ANTSTAT,1\r\n";
1476 char *cmd2_buf = "$ANTSTAT1\r\n";
1477
1478 if(0 == h_gnss)
1479 {
1480 printf("%s handler invalid.\n", __func__);
1481 return -1;
1482 }
1483 ret = mopen_gnss_send_cmd(h_gnss, cmd1_buf, strlen(cmd1_buf));
1484 if(ret < 0)
1485 {
1486 gnss_log("%s FAIL. ret:%d\n", __func__, ret);
1487 return -1;
1488 }
1489 ret = mopen_gnss_send_cmd(h_gnss, cmd2_buf, strlen(cmd2_buf));
1490 if(ret < 0)
1491 {
1492 gnss_log("%s FAIL. ret:%d\n", __func__, ret);
1493 return -1;
1494 }
1495 return 0;
1496}
1497
1498int mopen_gnss_get_nmea_config(uint32 h_gnss)
1499{
1500 int ret;
1501 char *send_buf = "$CFGNMEA\r\n";
1502
1503 if(0 == h_gnss)
1504 {
1505 printf("%s handler invalid.\n", __func__);
1506 return -1;
1507 }
1508 ret = mopen_gnss_send_cmd(h_gnss, send_buf, strlen(send_buf));
1509 if(ret < 0)
1510 {
1511 gnss_log("%s FAIL. ret:%d\n", __func__, ret);
1512 return -1;
1513 }
1514 return 0;
1515}
1516
1517int mbtk_gnss_add_rx_msg_handler(uint32 h_gnss, mbtk_gnss_handler_func_t handler_ptr)
1518{
1519 struct mbtk_gnss_handle_t *gnss_handle = (struct mbtk_gnss_handle_t *)h_gnss;
1520
1521 if(0 == h_gnss && NULL == handler_ptr)
1522 {
1523 printf("%s handler invalid.\n", __func__);
1524 return -1;
1525 }
1526 gnss_handle->gnss_handler_func = handler_ptr;
1527
1528 return 0;
1529}
1530
1531#define AGNSS_TLE_FILE "/tmp/agnss_tle"
1532
1533static void http_data_cb_func(
1534 int session_id, mbtk_http_data_type_enum type,
1535 void *data,int data_len)
1536{
1537 static int agnss_fd = 0;
1538 int ret = 0;
1539
1540 if(type == MBTK_HTTP_DATA_HEADER) {
1541 gnss_log("Header(%d):%s\n", data_len, (char*)data);
1542 if(agnss_fd > 0)
1543 return;
1544 unlink(AGNSS_TLE_FILE);
1545 agnss_fd = open(AGNSS_TLE_FILE, O_RDWR|O_CREAT|O_TRUNC, 0644);
1546 if (agnss_fd <= 0)
1547 gnss_log("file open error\n");
1548 gnss_log("agnss file open: %d\n", agnss_fd);
1549 } else if(type == MBTK_HTTP_DATA_CONTENT) {
1550 gnss_log("http Data(%d)\n", data_len);
1551
1552 ret = write(agnss_fd, (char*)data, data_len);
1553 if (ret < 0) {
1554 gnss_log("%s: error writing to file!\n", __FUNCTION__);
1555 } else if (ret < data_len) {
1556 gnss_log("%s: wrote less the buffer size!\n", __FUNCTION__);
1557 }
1558 } else {
1559 gnss_log(">>>>>Complete<<<<<\n");
1560 if(agnss_fd <= 0)
1561 return;
1562 close(agnss_fd);
1563 agnss_fd = 0;
1564 }
1565}
1566
1567static int gnss_http_requst(char *id, char *pw)
1568{
1569 char tmp[128] = {0};
1570
1571 int http_handle = mbtk_http_handle_get(TRUE, http_data_cb_func);
1572 if(http_handle < 0)
1573 {
1574 printf("mbtk_http_handle_get() fail.");
1575 return -1;
1576 }
1577
1578 int http_session = mbtk_http_session_create(http_handle, HTTP_OPTION_POST, HTTP_VERSION_1_1);
1579 if(http_handle < 0)
1580 {
1581 printf("mbtk_http_session_create() fail.");
1582 return -2;
1583 }
1584
1585 if(mbtk_http_session_url_set(http_handle, http_session, "http://unicore-api.rx-networks.cn/rxn-api/locationApi/rtcm")) {
1586 printf("mbtk_http_session_url_set() fail.\n");
1587 return -3;
1588 }
1589
1590 char* post_data = "[{\"rtAssistance\":{\"format\":\"rtcm\",\"msgs\":[\"GPS:2NAF\",\"BDS:2NAF\",\"QZS:2NAF\"]}}]\r\n";
1591
1592 mbtk_http_session_head_add(http_handle, http_session, \
1593 "Host", "unicore-api.rx-networks.cn");
1594
1595 sprintf(tmp, "RXN-BASIC cId=%s,mId=Unicore,dId=12-23-34-45-58,pw=%s", id, pw);
1596 mbtk_http_session_head_add(http_handle, http_session, \
1597 "Authorization", tmp);
1598
1599 mbtk_http_session_head_add(http_handle, http_session, \
1600 "Content-Type", "application/json");
1601
1602 mbtk_http_session_head_add(http_handle, http_session, \
1603 "Accept", "application/octet-stream");
1604 mbtk_http_session_content_set(http_handle, http_session,
1605 post_data, strlen(post_data));
1606
1607 if(mbtk_http_session_start(http_handle, http_session)) {
1608 printf("mbtk_http_session_start() fail.\n");
1609 return -4;
1610 }
1611
1612 if(mbtk_http_handle_free(http_handle))
1613 {
1614 printf("mbtk_http_handle_free() fail.");
1615 return -5;
1616 }
1617
1618 return 0;
1619}
1620
1621/**********************************
1622
1623 ID1: TempID1Expire20221031
1624 Base 64 PW1: RlJYdkFTNE9DWXJhN2ZWTA==
1625**************************************/
1626#define AGNSS_CONFIG_FILE "/etc/mbtk/gps.conf"
1627
1628/**
1629 * @brief mopen_gnss_download_tle
1630 *
1631 * @details 下载星历数据
1632 * (卫星星历,又称为两行轨道数据(TLE,Two-Line Orbital Element))
1633 * 保存到文件:AGNSS_TLE_FILE
1634 * @param param
1635 *
1636 * @return return type
1637 */
1638int mbtk_gnss_download_tle(void)
1639{
1640 FILE *fp;
1641 char StrLine[64];
1642 char _id[24] = {0};
1643 char _passwd[28] = {0};
1644 int i;
1645 if((fp = fopen(AGNSS_CONFIG_FILE, "r")) == NULL)
1646 {
1647 printf("open %s error!\n", AGNSS_CONFIG_FILE);
1648 return -1;
1649 }
1650
1651 while (!feof(fp))
1652 {
1653 memset(StrLine, 0, 64);
1654 fgets(StrLine, 64, fp);
1655 gnss_log("%s\n", StrLine);
1656 i = strstr_n(StrLine, ": ");
1657 if(i && strstr_n(StrLine, "ID"))
1658 {
1659 memcpy(_id, &StrLine[i + 1], strlen(StrLine) - i - 2);
1660 }
1661 else if( i && strstr_n(StrLine, "Base 64"))
1662 {
1663 memcpy(_passwd, &StrLine[i + 1], strlen(StrLine) - i - 2);
1664 }
1665 }
1666 fclose(fp);
1667 gnss_log("%s : %s[%d], %s[%d]\n", __FUNCTION__, _id, strlen(_id), _passwd, strlen(_passwd));
1668
1669 return gnss_http_requst(_id, _passwd);
1670}
1671
1672/**
1673 * @brief mopen_gnss_injects_aidpos
1674 *
1675 * @details 注入星历, 128 bytes
1676 *
1677 * @param param
1678 *
1679 * @return return type
1680 */
1681int mbtk_gnss_injects_aidpos(uint32 h_gnss)
1682{
1683 int ret;
1684 int agnss_fd = 0;
1685 int size = 0;
1686
1687 if(0 == h_gnss)
1688 {
1689 printf("%s handler invalid.\n", __func__);
1690 return -1;
1691 }
1692
1693 agnss_fd = open(AGNSS_TLE_FILE, O_RDWR);
1694 if (agnss_fd <= 0)
1695 {
1696 printf("%s open file FAIL. errno:%d\n", __FUNCTION__, errno);
1697 return -1;
1698 }
1699 char* databuf = (char*)malloc(128);
1700 if(databuf == NULL)
1701 {
1702 gnss_log("%s malloc() fail.", __FUNCTION__);
1703 return -1;
1704 }
1705 memset(databuf, 0, 128);
1706 while(0 < (size = read(agnss_fd, databuf, 128)))
1707 {
1708 gnss_log("%s Write[%d]\r\n", __FUNCTION__, size);
1709 ret = mopen_gnss_send_cmd(h_gnss, databuf, size);
1710 if(ret < 0)
1711 {
1712 printf("%s send cmd FAIL. ret:%d\n", __FUNCTION__, ret);
1713 break;
1714 }
1715 memset(databuf, 0, 128);
1716 }
1717 close(agnss_fd);
1718 free(databuf);
1719 mopen_gnss_get_aidinfo(h_gnss);
1720
1721 return 0;
1722}
1723/**
1724 * @brief mopen_gnss_set_mode
1725 *
1726 * @details detailed description
1727 *
1728 * @param mode
1729 * 0 : stop
1730 * 1 : 输出一次坐标
1731 * 2 : stop
1732 * 3 : 输出nmea数据到回调函数
1733 * 0 - stop, 1 - single, 2 - periodic, 3 - start
1734 *
1735 * @return return type
1736 */
1737int mbtk_gnss_set_mode(uint32 h_gnss, int mode)
1738{
1739 struct mbtk_gnss_handle_t *gnss_handle = (struct mbtk_gnss_handle_t *)h_gnss;
1740 if(0 == h_gnss)
1741 {
1742 printf("%s handler invalid.\n", __func__);
1743 return -1;
1744 }
1745 gnss_handle->mode = mode;
1746
1747 return 0;
1748}
1749
1750int mbtk_gnss_print_version(uint32 h_gnss)
1751{
1752 printf("*************************\n");
1753 printf("-Pn: %s\n dc: %s\n hv: %s\n fw: %s\n pn: %s\n sn: %s\n ",
1754 mopen_gnss_device_info.product_name,
1755 mopen_gnss_device_info.dev_config,
1756 mopen_gnss_device_info.hw_ver,
1757 mopen_gnss_device_info.fw_ver,
1758 mopen_gnss_device_info.pn,
1759 mopen_gnss_device_info.sn);
1760 printf("Uart bandrate: %d\n" , mopen_gnss_device_info.usrt_bandrate);
1761 printf("*************************\n");
1762
1763 return 0;
1764}
1765
1766/**
1767* @brief 使用popen调用终端并获取执行结果
1768*
1769* @param[in] cmd 命令内容
1770* @param[out] result 保存结果的地址
1771* @return 0或1 执行状态,成功或失败
1772*/
1773int exec_cmd(const char *cmd, char *result)
1774{
1775 FILE *pipe = popen(cmd, "r");
1776 if(!pipe)
1777 return -1;
1778
1779 char buffer[256] = {0};
1780 while(!feof(pipe))
1781 {
1782 if(fgets(buffer, 256, pipe))
1783 {
1784 printf("%s", buffer);
1785 memset(buffer, 0, sizeof(buffer));
1786 }
1787 }
1788 pclose(pipe);
1789 return 0;
1790}
1791
1792#define GNSS_AP_DATA_FILE "/etc/mbtk/rtm.bin"
1793
1794int mbtk_gnss_get_ap_data(void)
1795{
1796 int state = 0;
1797 uint32 *ph_gnss = NULL;
1798 mbtk_gnss_handler_func_t cb;
1799 int current_mode;
1800 const char* cmd = "mbtk_gnss_update getap -d /dev/ttyS2 -b 115200 -a /etc/mbtk/rtm.bin";
1801
1802 if(access(GNSS_AP_DATA_FILE, F_OK) != -1) {
1803 unlink(GNSS_AP_DATA_FILE);
1804 }
1805 mbtk_gnss_handle->getap_status = 1;
1806 sleep(1);
1807 printf("Mopen Gnss Get Ap Data -> \n");
1808 int ret = exec_cmd(cmd, NULL);
1809
1810 usleep(100000);
1811 mbtk_gnss_handle->getap_status = 0;
1812 if(0 != ret) {
1813 printf("Gnss getap result: %x\n", ret);
1814 return -1;
1815 }
1816 LOGI("%s %d: %d.\n", __FUNCTION__, __LINE__, ret);
1817 return ret;
1818}
1819/*
1820 sync : 1
1821 */
1822int mbtk_gnss_firmware_update(void)
1823{
1824 int state = 0;
1825 uint32 *ph_gnss = NULL;
1826 mbtk_gnss_handler_func_t cb;
1827 int current_mode;
1828 int fd = -1;
1829 int ret = 0;
1830
1831 const char* cmd_1 = "mbtk_gnss_update downbl -d /dev/ttyS2 \
1832 -l /etc/mbtk/bootloader_r3.0.0_build6773_uartboot_921600.pkg";
1833
1834 const char* cmd_2 = "mbtk_gnss_update sendap -d /dev/ttyS2 -b 921600 -a /etc/mbtk/rtm.bin";
1835
1836 const char* cmd_3 = "mbtk_gnss_update downfw -d /dev/ttyS2 -b 921600\
1837 -f /etc/mbtk/UC6228CI-R3.4.21.0Build16211_G1L1E1_mfg.pkg";
1838 // /etc/mbtk/UC6228CI-R3.4.0.0Build7258_mfg.pkg
1839
1840 if (mbtk_gnss_handle) {
1841 printf("%s gnss thread runing!!!\n", __func__);
1842 if (mbtk_gnss_handle->gnss_handler_func)
1843 cb = mbtk_gnss_handle->gnss_handler_func;
1844
1845 ph_gnss = mbtk_gnss_handle->phandle;
1846 current_mode = mbtk_gnss_handle->mode;
1847 // 主线程是否在运行
1848 if (mbtk_gnss_handle->gnss_pthread)
1849 state = 1;
1850 mbtk_gnss_client_deinit(mbtk_gnss_handle);
1851 }
1852 printf("Mopen Gnss Bootloader Update -> \n");
1853 //int ret = exec_cmd(cmd_1, NULL);
1854
1855 fd=initial_serialPort("/dev/ttyS2");
1856 ret = downloadBL(fd, "/etc/mbtk/bootloader_r3.0.0_build6773_uartboot_921600.pkg");
1857 if(0 != ret) {
1858 printf("Gnss update result: %x\n", ret);
1859 close(fd);
1860 return -1;
1861 }
1862
1863 if(access(GNSS_AP_DATA_FILE, F_OK) != -1)
1864 {
1865 printf("Mopen Gnss Send AP Data -> \n");
1866 //ret = exec_cmd(cmd_2, NULL);
1867
1868 set_baudrate(fd, B921600);
1869 ret = sendAPData(fd, "/etc/mbtk/rtm.bin");
1870
1871 if(0 != ret) {
1872 close(fd);
1873 printf("Gnss update result: %x\n", ret);
1874 }
1875 }
1876
1877 printf("Mopen Gnss Firmware Update -> \n");
1878 //ret = exec_cmd(cmd_3, NULL);
1879 set_baudrate(fd, B921600);
1880 ret = downloadFW(fd, "/etc/mbtk/UC6228CI-R3.4.21.0Build16211_G1L1E1_mfg.pkg");
1881 close(fd);
1882
1883 if(0 != ret) {
1884 printf("Gnss update result: %x\n", ret);
1885 return -2;
1886 }
1887
1888 if (0 == firmware_extren_state)
1889 firmware_extren_state = 1;
1890 if (state && ph_gnss) {
1891 ret = mbtk_gnss_client_init(ph_gnss);
1892 if (cb) {
1893 mbtk_gnss_handle->gnss_handler_func = cb;
1894 mbtk_gnss_handle->mode = current_mode;
1895 }
1896 }
1897
1898 LOGI("%s %d: %d.\n", __FUNCTION__, __LINE__, ret);
1899 return ret;
1900}
1901
1902int mbtk_at_gnss(int start_stop, void *cb)
1903{
1904 static uint32 loc = 0;
1905 int ret = -1;
1906
1907 LOGI("%s %d", __FUNCTION__, __LINE__);
1908 switch (start_stop) {
1909 case 0: {
1910 ret = mbtk_gnss_set_mode(loc, 0);
1911 if(ret)
1912 return -3;
1913 ret = mbtk_gnss_client_deinit(loc);
1914 if(ret)
1915 return -3;
1916 loc = 0;
1917 return 0;
1918 }
1919 case 1: {
1920 if (0 != loc)
1921 return -1;
1922
1923 ret = mbtk_gnss_client_init(&loc);
1924 if(ret || 0 == loc)
1925 return -1;
1926
1927 if(NULL == cb)
1928 return -2;
1929
1930 ret = mbtk_gnss_add_rx_msg_handler(loc, (mbtk_gnss_handler_func_t)cb);
1931 if(ret)
1932 return -2;
1933 ret = mbtk_gnss_set_mode(loc, 3);
1934 break;
1935 }
1936 case 2: {
1937 ret = mbtk_gnss_set_mode(loc, 0);
1938 break;
1939 }
1940 case 3: {
1941 ret = mbtk_gnss_set_mode(loc, 3);
1942 break;
1943 }
1944 case 4: {
1945 ret = mopen_uart_change(((struct mbtk_gnss_handle_t *)loc)->dev_fd, 1);
1946 if(ret) {
1947 printf("reset Uart set 115200 error\n");
1948 }
1949 break;
1950 }
1951 case 6: {
1952 ret = mbtk_gnss_firmware_update();
1953 if(ret) {
1954 printf("gnss firmware update error!!\n");
1955 }
1956 break;
1957 }
1958 case 11:{
1959 ret = mbtk_gnss_set_system_config((uint32)mbtk_gnss_handle,3);//GPS+BD
1960 break;
1961 }
1962 case 10:{
1963 ret = mbtk_gnss_set_system_config((uint32)mbtk_gnss_handle,0);// only GPS
1964 break;
1965 }
1966 case 9:{
1967 ret = mbtk_gnss_set_system_config((uint32)mbtk_gnss_handle,2);//GPS+GLONASS
1968 break;
1969 }
1970 default:
1971 break;
1972 }
1973
1974 return ret;
1975}
1976/*
1977 0 热启动
1978 1 冷启动
1979 2 温启动
1980 */
1981int mbtk_at_gnss_reset(int type)
1982{
1983 switch (type)
1984 {
1985 case 0: {
1986 // $RESET,0,h0
1987 return mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 0, 0);
1988 }
1989 case 1: {
1990 // $RESET,0,h85
1991 return mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 0, 2);
1992 }
1993 case 2: {
1994 // $RESET,0,h01
1995 return mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 0, 1);
1996 }
1997 case 3: {
1998 return mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 0, 3);
1999 }
2000 case 4: {
2001 return mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 3, 0);
2002 }
2003 case 5: {
2004 return mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 1, 0);
2005 }
2006 default:
2007 break;
2008 }
2009 return -9;
2010}
2011
2012#if TTFF_TEST
2013static void gnss_gsa_info(int cmd, char *str, void *data)
2014{
2015 char tmp_str[32] = {0};
2016 int ret;
2017
2018 gnss_log("[ GSA ]: ");
2019 // $xxGSA
2020 ret = gnss_get_para_from_nmea(str, tmp_str, 1);
2021 if(0 == ret && ('A' == tmp_str[0])){
2022 gnss_log("Smode: %s, ", tmp_str);
2023 memset(tmp_str, 0, 32);
2024 } else {
2025 printf("%s [exit]: %s\n", __FUNCTION__, str);
2026 return;
2027 }
2028
2029 /* 定位模式:
2030 1-未定位
2031 2-2D 定位
2032 3-3D 定位
2033 */
2034 ret = gnss_get_para_from_nmea(str, tmp_str, 2);
2035 if(ret){
2036 gnss_log("L%d %s error! \n");
2037 return;
2038 }
2039
2040 gnss_log("fs: %s - [%d]", tmp_str, atoi(tmp_str));
2041 if ( atoi(tmp_str) != mbtk_gnss_handle->location_state ) {
2042 mbtk_gnss_handle->location_state = atoi(tmp_str);
2043 if (mbtk_gnss_handle->location_state > 1 && location_test) {
2044 pthread_mutex_lock(&loc_cond_mutex_r);
2045 location_test = 0;
2046 pthread_cond_signal(&loc_sync_cond);
2047 pthread_mutex_unlock(&loc_cond_mutex_r);
2048 }
2049 }
2050 gnss_log(" -- \n");
2051}
2052
2053int mbtk_gnss_test_ttff(int type, int timeout_sec)
2054{
2055 struct timeval tnow;
2056 struct timespec tout;
2057 long t_start, t_end;
2058 int ret;
2059
2060 pthread_mutex_lock(&loc_cond_mutex_r);
2061 location_test = 1;
2062 pthread_mutex_unlock(&loc_cond_mutex_r);
2063
2064 switch (type)
2065 {
2066 case 0: {
2067 // $RESET,0,h0
2068 mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 0, 0);
2069 break;
2070 }
2071 case 1: {
2072 // $RESET,0,hFF
2073 mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 0, 3);
2074 break;
2075 }
2076 case 2: {
2077 // $RESET,0,h01
2078 mbtk_gnss_dev_reset((uint32)mbtk_gnss_handle, 0, 1);
2079 break;
2080 }
2081 case 3: {
2082 // 在有GLONASS固件的情况下,冷启动指令为: $CFGSYS,H101
2083 // 只发$RESET,0,hFF, 会重置波特率,待验证
2084 mopen_gnss_set_system_config((uint32)mbtk_gnss_handle, 2);
2085 break;
2086 }
2087 case 4: {
2088 if ( 0 == firmware_extren_state )
2089 return -2;
2090
2091 ret = mopen_gnss_firmware_update();
2092 if(ret) {
2093 printf("gnss firmware update error!!\n");
2094 }
2095 break;
2096 }
2097 default:
2098 break;
2099 }
2100 if (0 == timeout_sec )
2101 timeout_sec = 60 * 3;
2102 gettimeofday(&tnow, NULL);
2103 t_start = tnow.tv_sec * 1000 * 1000 + tnow.tv_usec;
2104 tout.tv_sec = tnow.tv_sec + timeout_sec;
2105 tout.tv_nsec = tnow.tv_usec;
2106 if (tout.tv_nsec > 1000000000)
2107 {
2108 tout.tv_sec += 1;
2109 tout.tv_nsec -= 1000000000;
2110 }
2111 pthread_mutex_lock(&loc_cond_mutex_r);
2112 ret = pthread_cond_timedwait(&loc_sync_cond, &loc_cond_mutex_r, &tout);
2113 pthread_mutex_unlock(&loc_cond_mutex_r);
2114 gettimeofday(&tnow, NULL);
2115 t_end = tnow.tv_sec * 1000 * 1000 + tnow.tv_usec;
2116 gnss_log("gnss ttff time:%ld\n", t_end - t_start);
2117 if(ret == ETIMEDOUT) {
2118 location_test = 0;
2119 return -1;
2120 }
2121
2122 return (t_end - t_start)/1000;
2123}
2124
2125#define GNSS_TEST_FILE "/tmp/gnss_test"
2126#define INSERT_CUT_OFF_RULE() { memset(buffer, 0, sizeof(buffer)); \
2127 sprintf(buffer, "----------------------------------\r\n"); \
2128 ret = write(fd, buffer, strlen(buffer)); \
2129 if (ret < 0) { \
2130 printf("%s write error !!\n", __func__); \
2131 } \
2132}
2133
2134void *gnss_ttff_thread(void *data)
2135{
2136 struct mbtk_gnss_ttff_t *handle = (struct mbtk_gnss_ttff_t *)data;
2137 int fd, ret, i;
2138 int index, time_ms;
2139 float loc_time;
2140 char buffer[128] = {0};
2141
2142 pthread_detach(pthread_self());
2143
2144 if ( !access(GNSS_TEST_FILE, F_OK) ){
2145 unlink(GNSS_TEST_FILE);
2146 }
2147
2148 pthread_cond_init(&loc_sync_cond, NULL);
2149 pthread_mutex_init(&loc_cond_mutex_r, NULL);
2150 fd = open(GNSS_TEST_FILE, O_RDWR|O_CREAT|O_TRUNC, 0644);
2151 if (fd <= 0) {
2152 gnss_log("file open error\n");
2153 }
2154 INSERT_CUT_OFF_RULE()
2155 sprintf(buffer, "type: %d, timeout: %d, count: %d\r\n", handle->type,
2156 handle->timeout_sec,
2157 handle->test_count);
2158 ret = write(fd, buffer, strlen(buffer));
2159 if (ret < 0) {
2160 printf("%s write error !!\n", __func__);
2161 }
2162 INSERT_CUT_OFF_RULE()
2163 for (i = 0; i < handle->test_count; ++i) {
2164 memset(buffer, 0, sizeof(buffer));
2165 time_ms = mbtk_gnss_test_ttff(handle->type, handle->timeout_sec);
2166 if (-1 == time_ms)
2167 loc_time = time_ms;
2168 else
2169 loc_time = ((float)time_ms) / 1000;
2170 sprintf(buffer, "\t %d - [ %f s ]\r\n", i + 1, loc_time);
2171 printf("\t %d - %f\n", i + 1, loc_time);
2172 ret = write(fd, buffer, strlen(buffer));
2173 if (ret < 0) {
2174 printf("%s write error !!\n", __func__);
2175 }
2176 }
2177
2178 INSERT_CUT_OFF_RULE()
2179 close(fd);
2180 mbtk_gnss_handle->ttff_pid = 0;
2181 pthread_cond_destroy(&loc_sync_cond);
2182 pthread_mutex_destroy(&loc_cond_mutex_r);
2183 pthread_exit(NULL);
2184}
2185#endif
2186
2187int mbtk_at_gnss_start_ttff(int type, int timeout_sec, int count)
2188{
2189#if TTFF_TEST
2190 int ret;
2191 static struct mbtk_gnss_ttff_t mbtk_gnss_ttff;
2192
2193 LOGI("%s %d, %d, %d", __FUNCTION__, type, timeout_sec, count);
2194 if (NULL == mbtk_gnss_handle) {
2195 printf("%s not init!!!\n", __func__);
2196 return -1;
2197 }
2198 if (mbtk_gnss_handle->ttff_pid) {
2199 printf("%s busy!!!\n", __func__);
2200 return -2;
2201 }
2202 mbtk_gnss_ttff.type = type;
2203 mbtk_gnss_ttff.timeout_sec = timeout_sec;
2204 mbtk_gnss_ttff.test_count = count;
2205 ret = pthread_create(&mbtk_gnss_handle->ttff_pid, NULL, (void *)gnss_ttff_thread, &mbtk_gnss_ttff);
2206 if (ret != 0)
2207 {
2208 fprintf(stderr, "\n%s: Failed create pthread\n", __FUNCTION__);
2209 return ret;
2210 }
2211
2212#endif
2213 return 0;
2214}