blob: d114b4b9ee1ee2006a0a979d9406f150da049678 [file] [log] [blame]
b.liu8f231a12024-05-31 17:55:06 +08001#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <errno.h>
5#include <fcntl.h>
6#include <termios.h>
7#include <string.h>
8#include <stdarg.h>
b.liu778645e2024-06-21 16:47:42 +08009#include <pty.h>
10#include <libubox/uloop.h>
yq.wang069ea922024-09-08 19:29:35 -070011#include <time.h>
12#include <sys/time.h>
b.liu8f231a12024-05-31 17:55:06 +080013
yq.wang069ea922024-09-08 19:29:35 -070014#include "gnss_utils.h"
b.liu8f231a12024-05-31 17:55:06 +080015#include "mbtk_log.h"
yq.wang069ea922024-09-08 19:29:35 -070016#include "gnss_log.h"
17#include "mbtk_gnss.h"
b.liu8f231a12024-05-31 17:55:06 +080018
19#define DATABITS CS8
20#define STOPBITS 0
21#define PARITYON 0
22#define PARITY 0
23#define MBTK_SLAVE_DEV_NAME_MAX_LEN 24
24
25int uart_baud_get(int baud)
26{
27 int rate = 0;
28 switch(baud)
29 {
30 case 300:
31 rate = B300;
32 break;
33 case 600:
34 rate = B600;
35 break;
36 case 1200:
37 rate = B1200;
38 break;
39 case 2400:
40 rate = B2400;
41 break;
42 case 4800:
43 rate = B4800;
44 break;
45 case 9600:
46 rate = B9600;
47 break;
48 case 19200:
49 rate = B19200;
50 break;
51 case 38400:
52 rate = B38400;
53 break;
54 case 57600:
55 rate = B57600;
56 break;
57 case 115200:
58 rate = B115200;
59 break;
60 case 230400:
61 rate = B230400;
62 break;
63 case 460800:
64 rate = B460800;
65 break;
66 case 921600:
67 rate = B921600;
68 break;
69 case 1500000:
70 rate = B1500000;
71 break;
72 case 2000000:
73 rate = B2000000;
74 break;
75 case 3000000:
76 rate = B3000000;
77 break;
78 case 4000000:
79 rate = B4000000;
80 break;
81 default:
82 rate = B115200;
83 break;
84 }
85
86 return rate;
87}
88
89int gnss_port_open(const char *dev, int flag, int baud, bool tty)
90{
91
92 int fd = -1;
93 if((fd = open(dev, flag)) < 0)
94 {
95 LOGE("Open %s fail errno = [%d].", dev, errno);
96 return -1;
97 }
98
99 LOGD("Open %s success.", dev);
100 if (tty)
101 {
102 int rate = uart_baud_get(baud);
103 /* set newtio */
104 struct termios newtio;
105 memset(&newtio, 0, sizeof(newtio));
106 //(void)fcntl(fd, F_SETFL, 0);
107 /* no flow control for uart by default */
108 newtio.c_cflag = rate | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
109 newtio.c_iflag = IGNPAR;
110 //newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
111 newtio.c_oflag = 0;
112 newtio.c_lflag = 0; /* disable ECHO, ICANON, etc... */
113
114 newtio.c_cc[VERASE] = 0x8; /* del */
115 newtio.c_cc[VEOF] = 4; /* Ctrl-d */
116 newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
117 newtio.c_cc[VEOL] = 0xD; /* '\0' */
118
119 tcflush(fd, TCIOFLUSH);
120 tcsetattr(fd, TCSANOW, &newtio);
121 }
122
123 return fd;
124}
125
126int gnss_port_close(int fd)
127{
128 if(fd > 0)
129 {
130 close(fd);
131 }
132 return 0;
133}
134
135int gnss_set_baudrate(int fd, int baudrate)
136{
137 struct termios options, oldtio;
138
139 if(fcntl(fd, F_SETFL, 0) < 0) {
140 LOGE("fcntl failed!");
141 return -1;
142 }
143
144 if(tcgetattr(fd, &oldtio) != 0) {
145 LOGE("setup serial error!");
146 return -1;
147 }
148
149 /* Get the current options for the port... */
150 tcgetattr(fd, &options);
151
152 /* Set the baud rates to baudrate... */
153 cfsetispeed(&options,baudrate);
154 cfsetospeed(&options,baudrate);
155 tcsetattr(fd, TCSANOW, &options);
156
157 if (0 != tcgetattr(fd, &options))
158 {
159 LOGE("get options error!");
160 return -1;
161 }
162
163 /*
164 * 8bit Data,no partity,1 stop bit...
165 */
166 options.c_cflag &= ~PARENB;//无奇偶校验
167 options.c_cflag &= ~CSTOPB;//停止位,1位
168 options.c_cflag &= ~CSIZE; //数据位的位掩码
169 options.c_cflag |= CS8; //数据位,8位
170
171 cfmakeraw(&options);
172
173 /*
174 * Set the new options for the port...
175 */
176 if (tcsetattr(fd, TCSANOW, &options) != 0)
177 {
178 LOGE("setup serial error!");
179 return -1 ;
180 }
181
182 return 0 ;
183}
184
185uint16 get_crc16(const char *ptr, uint16 count)
186{
187 uint16 crc, i;
188
189 crc = 0;
190 while(count--)
191 {
192 crc = crc ^ (int) *ptr++ << 8;
193
194 for(i = 0; i < 8; i++)
195 {
196 if(crc & 0x8000)
197 crc = crc << 1 ^ 0x1021;
198 else
199 crc = crc << 1;
200 }
201 }
202
203 return (crc & 0xFFFF);
204}
205
206int gnss_pty_open(int *master_fd, int *slave_fd, const char *dev)
207{
208 int flags = -1;
209 int ret = -1;
210 if(*master_fd > 0) {
211 LOGD("PTY has inited.");
212 return 0;
213 }
214 char spty_name[MBTK_SLAVE_DEV_NAME_MAX_LEN] = {0};
215 int result = openpty(master_fd, slave_fd, spty_name, NULL, NULL);
216 if (-1 == result) {
217 LOGE("Failed to get a pty.");
218 return -1;
219 }
220
221 LOGD("Get a pty pair, FD -- master[%d] slave[%d]", *master_fd, *slave_fd);
222 LOGD("Slave name is:%s", spty_name);
223
224 if(access(dev, F_OK) == -1)
225 {
226 LOGD("symlink %s -> %s", spty_name, dev);
227 result = symlink(spty_name, dev);
228 if (-1 == result) {
229 LOGE("symlink error.");
230 goto ERROR;
231 }
232 }
233
234 flags = fcntl(*master_fd, F_GETFL);
235 if (flags == -1)
236 {
237 LOGE("fcntl get error.");
238 goto ERROR;
239 }
240 flags |= O_NONBLOCK;
241 flags |= O_NOCTTY;
242 ret = fcntl(*master_fd, F_SETFL, flags);
243 if(ret == -1)
244 {
245 LOGE("fcntl set error.");
246 goto ERROR;
247 }
248
249 if (1) {
250 /* set newtio */
251 struct termios newtio;
252 memset(&newtio, 0, sizeof(newtio));
253 /* no flow control for uart by default */
254 newtio.c_cflag = B115200 | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
255 newtio.c_iflag = IGNPAR;
256 //newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
257 newtio.c_oflag = 0;
258 newtio.c_lflag = 0; /* disable ECHO, ICANON, etc... */
259
260 newtio.c_cc[VERASE] = 0x8; /* del */
261 newtio.c_cc[VEOF] = 4; /* Ctrl-d */
262 newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */
263 newtio.c_cc[VEOL] = 0xD; /* '\0' */
264
265 tcflush(*master_fd, TCIFLUSH);
266 tcsetattr(*master_fd, TCSANOW, &newtio);
267 }
268 return 0;
269
270ERROR:
271 if (0 < *master_fd) {
272 close(*master_fd);
273 *master_fd = -1;
274 }
275
276 if (0 < *slave_fd) {
277 close(*slave_fd);
278 *slave_fd = -1;
279 }
280
281 return -1;
282}
283
284int gnss_nmea_sscanf(const char *str, char *ret,...)
285{
286 const char *ptr = str;
287 char *argv[16];
288 int argc;
289 va_list ap;
290 int i = 0;
291
292 va_start(ap, ret);
293 argc = 0;
294 argv[argc] = ret; // First arg.
295
296 do {
297 i = 0;
298 while(*ptr && *ptr != ',' && *ptr != '*') {
299 argv[argc][i++] = *ptr++;
300 }
301 ptr++; // Jump ',' or '*'
302 argc++;
303 } while((argv[argc] = va_arg(ap, char*)) != 0);
304
305 va_end(ap);
306
307 return argc;
308}
309
310void gnssStartTimer(struct uloop_timeout *timeout, int timeVal)
311{
312 //UNUSED(timeout);
313 LOGD("%s: timeVal=%lu.", __FUNCTION__, timeVal);
314 uloop_timeout_set(timeout, timeVal);
315 return;
316}
317
318void gnssStopTimer(struct uloop_timeout *timeout)
319{
320 //UNUSED(timeout);
321 uloop_timeout_cancel(timeout);
322 return;
323}
324
yq.wang069ea922024-09-08 19:29:35 -0700325#if MBTK_GNSS_PARAM_PARSE
326static bool mbtk_gnss_time_set_flag = 0;
327
328extern long timezone;
329
330static int strstr_n(const char *s1, const char *s2)
331{
332 int n;
333 int strlen = 0;
334
335 if(*s2)
336 {
337 while(*s1)
338 {
339 for(n = 0; *(s1+n) == *(s2 + n); n++)
340 {
341 if(!*(s2 + n + 1))
342 {
343 strlen++;
344 return strlen;
345 }
346 }
347 s1++;
348 strlen++;
349 }
350 return 0;
351 }
352
353 return 0;
354}
355
356static int nmea_tokenizer_init(mbtk_nmeatokenizer* t, const char* head, const char* end, int param_num)
357{
358 int count = 0;
359 const char* p = head;
360 const char* q = end;
361 const char* tmp = NULL;
362 // the initial '$' is optional
363 if (p < q && p[0] == '$')
364 {
365 p += 1;
366 }
367 else
368 {
369 return -1;
370 }
371
372 //find '*',del '*25\r\n'
373 // get rid of checksum at the end of the sentecne
374 if (q >= p + 5 && q[-5] == '*')
375 {
376 q -= 5;
377 }
378 else
379 {
380 return -1;
381 }
382
383 while (p <= q)
384 {
385 tmp = memchr(p, ',', q-p);
386 if (tmp == NULL)
387 {
388 tmp = q;
389 }
390 // if (q > p) {
391 // q >= p include empty token: ,,
392 if (tmp >= p)
393 {
394 if (count < MAX_NMEA_TOKENS)
395 {
396 t->tokens[count].head = p;
397 t->tokens[count].end = tmp;
398 count += 1;
399 }
400 }
401
402 if (tmp <= q)
403 {
404 tmp += 1;
405 }
406
407 p = tmp;
408 }
409
410 if(count != param_num)
411 {
412 LOGD("count [%d], param_num [%d]", count, param_num);
413 return -1;
414 }
415
416 t->count = count;
417 return count;
418}
419
420static mbtk_token nmea_tokenizer_get(mbtk_nmeatokenizer* t, int index)
421{
422 mbtk_token tok;
423 static const char* dummy = "";
424
425 if (index < 0 || index >= t->count)
426 {
427 tok.head = tok.end = dummy;
428 }
429 else
430 {
431 tok = t->tokens[index];
432 }
433 return tok;
434}
435
436static time_t nmea_get_sec(mbtk_token date, mbtk_token time)
437{
438 char tmp_char[4] = {0};
439 struct tm tmp_time;
440
441 memset(&tmp_time, 0x0, sizeof(struct tm));
442 if (date.head + 6 > date.end)
443 {
444 LOGD("date get fail");
445 return -1;
446 }
447
448 memcpy(tmp_char, date.head, 2);
449 tmp_time.tm_mday = atoi(tmp_char);
450 memcpy(tmp_char, date.head + 2, 2);
451 tmp_time.tm_mon = atoi(tmp_char) - 1;
452 memcpy(tmp_char, date.head + 4, 2);
453 tmp_time.tm_year = 100 + atoi(tmp_char);
454
455 if (time.head + 6 > time.end)
456 {
457 LOGD("time get fail");
458 return -1;
459 }
460
461 memcpy(tmp_char, time.head, 2);
462 tmp_time.tm_hour = atoi(tmp_char);
463 memcpy(tmp_char, time.head + 2, 2);
464 tmp_time.tm_min = atoi(tmp_char);
465 memcpy(tmp_char, time.head + 4, 2);
466 tmp_time.tm_sec = atoi(tmp_char);
467 tmp_time.tm_isdst = -1;
468
469#if 0
470 LOGD("data:%d-%d-%d %d:%d:%d", tmp_time.tm_year + 1900,
471 tmp_time.tm_mon,
472 tmp_time.tm_mday,
473 tmp_time.tm_hour,
474 tmp_time.tm_min,
475 tmp_time.tm_sec);
476#endif
477
478 time_t _t = mktime(&tmp_time);//parse location tmp_time
479
480
481
482 return _t;
483}
484
485static int mbtk_time_type_gnss_read() {
486 int type = 0;
487 char time_type[] ={0};
488 property_get("persist.mbtk.time_type", time_type, "0");
489
490 type = atoi(time_type);
491// LOGD("time_type :%d\n", type);
492 if(type != LYNQ_TIME_TYPE_GNSS)
493 mbtk_gnss_time_set_flag = 0;
494
495 return type;
496}
497
498int gnss_ind_nmea_parse(const char *data, int data_len)
499{
500 int ret;
501 mbtk_nmeatokenizer tzer = {0};
502 if(strstr_n(data + 3, "RMC"))
503 {
504 ret = nmea_tokenizer_init(&tzer, data, data + data_len, NMEA_RMC_PARAM_NUM);
505 if(ret < 0)
506 {
507 LOGD("nmea_tokenizer_init fail");
508 return -1;
509 }
510
511 mbtk_token tok_time = nmea_tokenizer_get(&tzer,1);
512 mbtk_token tok_fixStatus = nmea_tokenizer_get(&tzer,2);
513 mbtk_token tok_date = nmea_tokenizer_get(&tzer,9);
514
515 if(tok_fixStatus.head[0] == 'A')
516 {
517 time_t _t = 0;
518 _t = nmea_get_sec(tok_date, tok_time);
519 if(_t < 0)
520 {
521 LOGD("nmea_update_date_time fail");
522 return -1;
523 }
524 else
525 {
526#ifdef MBTK_GNSS_TIME_CHECK
527 if(mbtk_check_num() == 0)
528 {
529 mbtk_gnss_time_check(_t);
530 gnss_test_log("%s", data);
531 }
532#endif
533 if( (mbtk_time_type_gnss_read() == LYNQ_TIME_TYPE_GNSS) && !mbtk_gnss_time_set_flag)
534 {
luojian252d7bc2024-09-24 16:32:38 +0800535#if 0
yq.wang069ea922024-09-08 19:29:35 -0700536 struct timeval tv;
537 tzset(); // auto set tz
luojian252d7bc2024-09-24 16:32:38 +0800538 // _t = _t - timezone;
yq.wang069ea922024-09-08 19:29:35 -0700539 LOGD("timestamp:%ld, %ld", _t, timezone);
yq.wang069ea922024-09-08 19:29:35 -0700540 tv.tv_sec = _t;
luojian252d7bc2024-09-24 16:32:38 +0800541
542#else
543 LOGD("_t: %ld\n", _t);
544 struct tm CurlocalTime;
545 localtime_r(&_t, &CurlocalTime);
546 CurlocalTime.tm_hour += 8; //cst+8 set for UTC
547 char dateTime[30];
548 strftime(dateTime, 30, "%Y-%m-%d %H:%M:%S %A", &CurlocalTime);
549 LOGD("dateTime:%s, %ld\n", dateTime, _t);
550
551 struct timeval tv;
552 tv.tv_sec = _t;
553 tv.tv_sec += 28800; //cst
554 tv.tv_usec = 0;
555
556#endif
yq.wang069ea922024-09-08 19:29:35 -0700557 if(settimeofday(&tv, NULL)) {
luojian252d7bc2024-09-24 16:32:38 +0800558 LOGD("%s: 1111, Set time fail\n", __func__);
yq.wang069ea922024-09-08 19:29:35 -0700559 mbtk_gnss_time_set_flag = 0;
560 } else {
luojian252d7bc2024-09-24 16:32:38 +0800561 LOGD("%s: 1111, Set time success \n", __func__);
yq.wang069ea922024-09-08 19:29:35 -0700562 system("hwclock -w rtc0");
563 mbtk_gnss_time_set_flag = 1;
564 }
565 }
566 }
567 }
568 }
569
570 return 0;
571}
luojian252d7bc2024-09-24 16:32:38 +0800572#endif