blob: 515feaec9c23874923181110bd5ceeae670d0ba6 [file] [log] [blame]
b.liue77ac3a2024-07-17 17:36:57 +08001/*
2* mbtk_gnss.c
3*
4* MBTK GNSS API source.
5*
6*/
7/******************************************************************************
8
9 EDIT HISTORY FOR FILE
10
11 WHEN WHO WHAT,WHERE,WHY
12-------- -------- -------------------------------------------------------
132024/7/11 LiuBin Initial version
14
15******************************************************************************/
16#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include <errno.h>
20#include <pthread.h>
21#include <sys/socket.h>
22#include <sys/un.h>
23#include <netinet/in.h>
24#include <fcntl.h>
25#include <sys/epoll.h>
26
27#include "mbtk_gnss_inter.h"
28#include "mbtk_log.h"
29#include "mbtk_utils.h"
30
31#define GNSS_BUFF_SIZE 2048
32
33static int gnss_cli_fd = -1;
34static pthread_t read_thread_id;
35static int exit_fd[2] = {-1};
36static mbtk_gnss_callback_func gnss_cb = NULL;
37static bool gnss_busy = FALSE;
38static pthread_cond_t gnss_cond;
39static pthread_mutex_t gnss_mutex;
40static gnss_err_enum gnss_result;
41
42static int sock_read(int fd, uint8 *msg, int data_len)
43{
44 memset(msg, 0, data_len);
45 int len = 0;
46
47 int read_len = 0;
48 while(1)
49 {
50 len = read(fd, msg + read_len, data_len - read_len);
51 if(len > 0)
52 {
53 read_len += len;
54 }
55 else if(len == 0)
56 {
57 LOGE("read() end.");
58 break;
59 }
60 else
61 {
62 if(EAGAIN == errno)
63 {
b.liu42f558e2024-07-18 14:06:49 +080064 LOGV("Read end, lenght = %d", read_len);
b.liue77ac3a2024-07-17 17:36:57 +080065 }
66 else
67 {
68 LOGE("read() error[%d].", errno);
69 }
70 break;
71 }
72 }
73
74 if(read_len > 0)
75 {
76 // log_hex("DATA_RECV", msg, read_len);
77 return read_len;
78 }
79 else
80 {
81 return -1;
82 }
83}
84
85static int sock_write(int fd, uint8 *msg, int data_len)
86{
87 int len = 0;
88 int write_len = 0;
89 while(write_len < data_len)
90 {
91 len = write(fd, msg + write_len, data_len - write_len);
92 if(len > 0)
93 {
94 write_len += len;
95 }
96 else if(len == 0)
97 {
98 LOGE("write() end.");
99 break;
100 }
101 else
102 {
103 LOGE("write() error[%d].", errno);
104 break;
105 }
106 }
107
108 if(write_len > 0)
109 {
110 // log_hex("DATA_SEND", msg, write_len);
111 return write_len;
112 }
113 else
114 {
115 return -1;
116 }
117}
118
119static void gnss_timer_cb(int signo)
120{
121 if(gnss_busy) {
122 pthread_mutex_lock(&gnss_mutex);
123 pthread_cond_signal(&gnss_cond);
124 pthread_mutex_unlock(&gnss_mutex);
125 gnss_result = GNSS_ERR_TIMEOUT;
126 }
127 return;
128}
129
130static void gnss_rsp_process(const char *data, int data_len)
131{
132 int index = 0;
133 char buff[GNSS_BUFF_SIZE];
134 int buff_len = 0;
135 while(index < data_len) {
136 if(data[index] == MBTK_IND_START_FLAG) {
137 memset(buff, 0, sizeof(buff));
138 buff_len = 0;
139 } else if(data[index] == MBTK_IND_END_FLAG) {
140 buff[buff_len] = '\0';
b.liue77ac3a2024-07-17 17:36:57 +0800141 if(memcmp(MBTK_IND_LOCATION_TAG, buff, strlen(MBTK_IND_LOCATION_TAG)) == 0) {
142 if(gnss_cb) {
143 gnss_cb(MBTK_GNSS_IND_LOCATION, buff, buff_len);
144 }
145 } else if(memcmp(MBTK_IND_NMEA_TAG, buff, strlen(MBTK_IND_NMEA_TAG)) == 0) {
146 if(gnss_cb) {
147 gnss_cb(MBTK_GNSS_IND_NMEA, buff, buff_len);
148 }
149 } else {
b.liu42f558e2024-07-18 14:06:49 +0800150 LOGD("RSP[len - %d] : %s", buff_len, buff);
b.liue77ac3a2024-07-17 17:36:57 +0800151 if(gnss_busy) {
b.liu42f558e2024-07-18 14:06:49 +0800152 // XXXXXX:<result>
153 char *ptr = strstr(buff, ":");
154 if(ptr) {
155 gnss_result = atoi(ptr + 1);
156 }
b.liue77ac3a2024-07-17 17:36:57 +0800157 pthread_mutex_lock(&gnss_mutex);
158 pthread_cond_signal(&gnss_cond);
159 pthread_mutex_unlock(&gnss_mutex);
160 }
161 }
162 } else {
163 buff[buff_len++] = data[index];
164 }
165 index++;
166 }
167}
168
169static void* gnss_read_run(void* arg)
170{
171 int epoll_fd = epoll_create(5);
172 if(epoll_fd < 0)
173 {
174 LOGE("epoll_create() fail[%d].", errno);
175 return NULL;
176 }
177
178 uint32 event = EPOLLIN | EPOLLET;
179 struct epoll_event ev_cli, ev_exit;
180 ev_cli.data.fd = gnss_cli_fd;
181 ev_cli.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
182 epoll_ctl(epoll_fd,EPOLL_CTL_ADD,gnss_cli_fd,&ev_cli);
183
184 ev_exit.data.fd = exit_fd[0];
185 ev_exit.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
186 epoll_ctl(epoll_fd,EPOLL_CTL_ADD,exit_fd[0],&ev_exit);
187
188 int nready = -1;
189 struct epoll_event epoll_events[EPOLL_LISTEN_MAX];
190 while(1)
191 {
192 nready = epoll_wait(epoll_fd, epoll_events, EPOLL_LISTEN_MAX, -1);
193 if(nready > 0)
194 {
195 int i;
196 for(i = 0; i < nready; i++)
197 {
b.liu42f558e2024-07-18 14:06:49 +0800198 LOGV("fd[%d] event = %x",epoll_events[i].data.fd, epoll_events[i].events);
b.liue77ac3a2024-07-17 17:36:57 +0800199 if(epoll_events[i].events & EPOLLHUP) // Closed by server.
200 {
201
202 }
203 else if(epoll_events[i].events & EPOLLIN)
204 {
205 if(gnss_cli_fd == epoll_events[i].data.fd) // Server data arrive.
206 {
207 char buff[GNSS_BUFF_SIZE + 1];
208 int len = sock_read(gnss_cli_fd, buff, GNSS_BUFF_SIZE);
209 if(len > 0) {
210 gnss_rsp_process(buff, len);
211 }
212 }
213 else if(exit_fd[0] == epoll_events[i].data.fd) //
214 {
215 char buff[100] = {0};
216 int len = read(exit_fd[0], buff, 100);
217 if(len > 0) {
218 LOGI("CMD : %s", buff);
219 if(strcmp(buff, "EXIT") == 0) {
220 goto read_thread_exit;
221 } else {
222 LOGD("Unkonw cmd : %s", buff);
223 }
224 } else {
225 LOGE("sock_read() fail.");
226 }
227 }
228 else
229 {
230 LOGW("Unknown socket : %d", epoll_events[i].data.fd);
231 }
232 }
233 else
234 {
235 LOGW("Unknown event : %x", epoll_events[i].events);
236 }
237 }
238 }
239 else
240 {
241 LOGW("epoll_wait() fail[%d].", errno);
242 }
243 }
244
245read_thread_exit:
246 LOGD("info_read thread exit.");
247 return NULL;
248}
249
250gnss_err_enum mbtk_gnss_init(mbtk_gnss_callback_func cb)
251{
252 if(gnss_cli_fd > 0) {
253 LOGW("GNSS client has inited.");
254 return GNSS_ERR_OK;
255 }
256
257 gnss_cli_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
258 if(gnss_cli_fd < 0)
259 {
260 LOGE("socket() fail[%d].", errno);
261 goto error;
262 }
263
264 // Set O_NONBLOCK
265 int flags = fcntl(gnss_cli_fd, F_GETFL, 0);
266 if (flags < 0)
267 {
268 LOGE("Get flags error:%d", errno);
269 goto error;
270 }
271 flags |= O_NONBLOCK;
272 if (fcntl(gnss_cli_fd, F_SETFL, flags) < 0)
273 {
274 LOGE("Set flags error:%d", errno);
275 goto error;
276 }
277
278 struct sockaddr_un cli_addr;
279 memset(&cli_addr, 0, sizeof(cli_addr));
280 cli_addr.sun_family = AF_LOCAL;
281 strcpy(cli_addr.sun_path, SOCK_GNSS_PATH);
282 if(connect(gnss_cli_fd, (struct sockaddr *)&cli_addr, sizeof(cli_addr)))
283 {
284 LOGE("connect() fail[%d].", errno);
285 goto error;
286 }
287
288 if(pipe(exit_fd)) {
289 LOGE("pipe() fail[%d].", errno);
290 goto error;
291 }
292
293 if(pthread_create(&read_thread_id, NULL, gnss_read_run, NULL))
294 {
295 LOGE("pthread_create() fail.");
296 goto error;
297 }
298 pthread_mutex_init(&gnss_mutex, NULL);
299 pthread_cond_init(&gnss_cond, NULL);
300 gnss_cb = cb;
301 return GNSS_ERR_OK;
302
303error:
304 if(gnss_cli_fd > 0) {
305 close(gnss_cli_fd);
306 gnss_cli_fd = -1;
307 }
308 if(exit_fd[0] > 0) {
309 close(exit_fd[0]);
310 exit_fd[0] = -1;
311 }
312 if(exit_fd[1] > 0) {
313 close(exit_fd[1]);
314 exit_fd[1] = -1;
315 }
316
317 return GNSS_ERR_UNKNOWN;
318}
319
320gnss_err_enum mbtk_gnss_deinit()
321{
322 if(gnss_cli_fd < 0) {
323 LOGW("GNSS client not inited.");
324 return GNSS_ERR_UNKNOWN;
325 }
326
327 if(gnss_busy) {
328 LOGE("BUSY");
329 return GNSS_ERR_BUSY;
330 }
331
332 if(exit_fd[1] > 0) {
333 write(exit_fd[1], "EXIT", 4);
334 }
335
336 int ret = pthread_join(read_thread_id, NULL);
337 if(ret){
338 LOGE("pthrad_join fail(%d)",ret);
339 return GNSS_ERR_UNKNOWN;
340 }
341
342 close(gnss_cli_fd);
343 gnss_cli_fd = -1;
344 close(exit_fd[0]);
345 exit_fd[0] = -1;
346 close(exit_fd[1]);
347 exit_fd[1] = -1;
348 gnss_cb = NULL;
349 gnss_busy = FALSE;
350 pthread_mutex_destroy(&gnss_mutex);
351 pthread_cond_destroy(&gnss_cond);
352
353 return GNSS_ERR_OK;
354}
355
356gnss_err_enum mbtk_gnss_open(int type, int timeout)
357{
358 if(gnss_cli_fd < 0) {
359 LOGW("GNSS client not inited.");
360 return GNSS_ERR_UNKNOWN;
361 }
362
363 if(gnss_busy) {
364 LOGE("BUSY");
365 return GNSS_ERR_BUSY;
366 } else {
367 gnss_result = GNSS_ERR_OK;
368 gnss_busy = TRUE;
369 if(timeout > 0) {
370 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
371 }
372
373 // gnss_init:x
374 char cmd[32] = {0};
375 snprintf(cmd, sizeof(cmd), "gnss_init:%d", type);
376 sock_write(gnss_cli_fd, cmd, strlen(cmd));
377
378 pthread_mutex_lock(&gnss_mutex);
379 pthread_cond_wait(&gnss_cond, &gnss_mutex);
380 pthread_mutex_unlock(&gnss_mutex);
381
382 gnss_busy = FALSE;
383
384 return gnss_result;
385 }
386}
387
388gnss_err_enum mbtk_gnss_close(int timeout)
389{
390 if(gnss_cli_fd < 0) {
391 LOGW("GNSS client not inited.");
392 return GNSS_ERR_UNKNOWN;
393 }
394
395 if(gnss_busy) {
396 LOGE("BUSY");
397 return GNSS_ERR_BUSY;
398 } else {
399 gnss_result = GNSS_ERR_OK;
400 gnss_busy = TRUE;
401 if(timeout > 0) {
402 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
403 }
404
405 // gnss_deinit
406 char *cmd = "gnss_deinit";
407 sock_write(gnss_cli_fd, cmd, strlen(cmd));
408
409 pthread_mutex_lock(&gnss_mutex);
410 pthread_cond_wait(&gnss_cond, &gnss_mutex);
411 pthread_mutex_unlock(&gnss_mutex);
412
413 gnss_busy = FALSE;
414
415 return gnss_result;
416 }
417}
418
419
420gnss_err_enum mbtk_gnss_setting(const char *setting_cmd, int timeout)
421{
422 if(gnss_cli_fd < 0) {
423 LOGW("GNSS client not inited.");
424 return GNSS_ERR_UNKNOWN;
425 }
426
427 if(gnss_busy) {
428 LOGE("BUSY");
429 return GNSS_ERR_BUSY;
430 } else {
431 gnss_result = GNSS_ERR_OK;
432 gnss_busy = TRUE;
433 if(timeout > 0) {
434 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
435 }
436
437 // gnss_setting:cmd
438 char cmd[32] = {0};
439 snprintf(cmd, sizeof(cmd), "gnss_setting:%s", setting_cmd);
440 sock_write(gnss_cli_fd, cmd, strlen(cmd));
441
442 pthread_mutex_lock(&gnss_mutex);
443 pthread_cond_wait(&gnss_cond, &gnss_mutex);
444 pthread_mutex_unlock(&gnss_mutex);
445
446 gnss_busy = FALSE;
447
448 return gnss_result;
449 }
450}
451
452gnss_err_enum mbtk_gnss_dl(const char *fw_path, int timeout)
453{
454 if(gnss_cli_fd < 0) {
455 LOGW("GNSS client not inited.");
456 return GNSS_ERR_UNKNOWN;
457 }
458
459 if(gnss_busy) {
460 LOGE("BUSY");
461 return GNSS_ERR_BUSY;
462 } else {
463 gnss_result = GNSS_ERR_OK;
464 gnss_busy = TRUE;
465 if(timeout > 0) {
466 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
467 }
468
469 // gnss_dl:fw_name
470 char cmd[32] = {0};
471 snprintf(cmd, sizeof(cmd), "gnss_dl:%s", fw_path);
472 sock_write(gnss_cli_fd, cmd, strlen(cmd));
473
474 pthread_mutex_lock(&gnss_mutex);
475 pthread_cond_wait(&gnss_cond, &gnss_mutex);
476 pthread_mutex_unlock(&gnss_mutex);
477
478 gnss_busy = FALSE;
479
480 return gnss_result;
481 }
482}
483
484
485gnss_err_enum mbtk_gnss_ind_set(uint32 gnss_ind, int timeout)
486{
487 if(gnss_cli_fd < 0) {
488 LOGW("GNSS client not inited.");
489 return GNSS_ERR_UNKNOWN;
490 }
491
492 if(gnss_busy) {
493 LOGE("BUSY");
494 return GNSS_ERR_BUSY;
495 } else {
496 gnss_result = GNSS_ERR_OK;
497 gnss_busy = TRUE;
498 if(timeout > 0) {
499 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
500 }
501
502 // gnss_ind:ind_type
503 char cmd[32] = {0};
504 snprintf(cmd, sizeof(cmd), "gnss_ind:%d", gnss_ind);
505 sock_write(gnss_cli_fd, cmd, strlen(cmd));
506
507 pthread_mutex_lock(&gnss_mutex);
508 pthread_cond_wait(&gnss_cond, &gnss_mutex);
509 pthread_mutex_unlock(&gnss_mutex);
510
511 gnss_busy = FALSE;
512
513 return gnss_result;
514 }
515}
516