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