blob: e8310b3bae4e3875df646f53b5d477dc5dfe68ca [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 {
64 LOGE("Read end, lenght = %d", read_len);
65 }
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';
141 LOGD("RSP[len - %d] : %s", buff_len, buff);
142 if(memcmp(MBTK_IND_LOCATION_TAG, buff, strlen(MBTK_IND_LOCATION_TAG)) == 0) {
143 if(gnss_cb) {
144 gnss_cb(MBTK_GNSS_IND_LOCATION, buff, buff_len);
145 }
146 } else if(memcmp(MBTK_IND_NMEA_TAG, buff, strlen(MBTK_IND_NMEA_TAG)) == 0) {
147 if(gnss_cb) {
148 gnss_cb(MBTK_GNSS_IND_NMEA, buff, buff_len);
149 }
150 } else {
151 if(gnss_busy) {
152 pthread_mutex_lock(&gnss_mutex);
153 pthread_cond_signal(&gnss_cond);
154 pthread_mutex_unlock(&gnss_mutex);
155 }
156 }
157 } else {
158 buff[buff_len++] = data[index];
159 }
160 index++;
161 }
162}
163
164static void* gnss_read_run(void* arg)
165{
166 int epoll_fd = epoll_create(5);
167 if(epoll_fd < 0)
168 {
169 LOGE("epoll_create() fail[%d].", errno);
170 return NULL;
171 }
172
173 uint32 event = EPOLLIN | EPOLLET;
174 struct epoll_event ev_cli, ev_exit;
175 ev_cli.data.fd = gnss_cli_fd;
176 ev_cli.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
177 epoll_ctl(epoll_fd,EPOLL_CTL_ADD,gnss_cli_fd,&ev_cli);
178
179 ev_exit.data.fd = exit_fd[0];
180 ev_exit.events = event; //EPOLLIN | EPOLLERR | EPOLLET;
181 epoll_ctl(epoll_fd,EPOLL_CTL_ADD,exit_fd[0],&ev_exit);
182
183 int nready = -1;
184 struct epoll_event epoll_events[EPOLL_LISTEN_MAX];
185 while(1)
186 {
187 nready = epoll_wait(epoll_fd, epoll_events, EPOLL_LISTEN_MAX, -1);
188 if(nready > 0)
189 {
190 int i;
191 for(i = 0; i < nready; i++)
192 {
193 LOGD("fd[%d] event = %x",epoll_events[i].data.fd, epoll_events[i].events);
194 if(epoll_events[i].events & EPOLLHUP) // Closed by server.
195 {
196
197 }
198 else if(epoll_events[i].events & EPOLLIN)
199 {
200 if(gnss_cli_fd == epoll_events[i].data.fd) // Server data arrive.
201 {
202 char buff[GNSS_BUFF_SIZE + 1];
203 int len = sock_read(gnss_cli_fd, buff, GNSS_BUFF_SIZE);
204 if(len > 0) {
205 gnss_rsp_process(buff, len);
206 }
207 }
208 else if(exit_fd[0] == epoll_events[i].data.fd) //
209 {
210 char buff[100] = {0};
211 int len = read(exit_fd[0], buff, 100);
212 if(len > 0) {
213 LOGI("CMD : %s", buff);
214 if(strcmp(buff, "EXIT") == 0) {
215 goto read_thread_exit;
216 } else {
217 LOGD("Unkonw cmd : %s", buff);
218 }
219 } else {
220 LOGE("sock_read() fail.");
221 }
222 }
223 else
224 {
225 LOGW("Unknown socket : %d", epoll_events[i].data.fd);
226 }
227 }
228 else
229 {
230 LOGW("Unknown event : %x", epoll_events[i].events);
231 }
232 }
233 }
234 else
235 {
236 LOGW("epoll_wait() fail[%d].", errno);
237 }
238 }
239
240read_thread_exit:
241 LOGD("info_read thread exit.");
242 return NULL;
243}
244
245gnss_err_enum mbtk_gnss_init(mbtk_gnss_callback_func cb)
246{
247 if(gnss_cli_fd > 0) {
248 LOGW("GNSS client has inited.");
249 return GNSS_ERR_OK;
250 }
251
252 gnss_cli_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
253 if(gnss_cli_fd < 0)
254 {
255 LOGE("socket() fail[%d].", errno);
256 goto error;
257 }
258
259 // Set O_NONBLOCK
260 int flags = fcntl(gnss_cli_fd, F_GETFL, 0);
261 if (flags < 0)
262 {
263 LOGE("Get flags error:%d", errno);
264 goto error;
265 }
266 flags |= O_NONBLOCK;
267 if (fcntl(gnss_cli_fd, F_SETFL, flags) < 0)
268 {
269 LOGE("Set flags error:%d", errno);
270 goto error;
271 }
272
273 struct sockaddr_un cli_addr;
274 memset(&cli_addr, 0, sizeof(cli_addr));
275 cli_addr.sun_family = AF_LOCAL;
276 strcpy(cli_addr.sun_path, SOCK_GNSS_PATH);
277 if(connect(gnss_cli_fd, (struct sockaddr *)&cli_addr, sizeof(cli_addr)))
278 {
279 LOGE("connect() fail[%d].", errno);
280 goto error;
281 }
282
283 if(pipe(exit_fd)) {
284 LOGE("pipe() fail[%d].", errno);
285 goto error;
286 }
287
288 if(pthread_create(&read_thread_id, NULL, gnss_read_run, NULL))
289 {
290 LOGE("pthread_create() fail.");
291 goto error;
292 }
293 pthread_mutex_init(&gnss_mutex, NULL);
294 pthread_cond_init(&gnss_cond, NULL);
295 gnss_cb = cb;
296 return GNSS_ERR_OK;
297
298error:
299 if(gnss_cli_fd > 0) {
300 close(gnss_cli_fd);
301 gnss_cli_fd = -1;
302 }
303 if(exit_fd[0] > 0) {
304 close(exit_fd[0]);
305 exit_fd[0] = -1;
306 }
307 if(exit_fd[1] > 0) {
308 close(exit_fd[1]);
309 exit_fd[1] = -1;
310 }
311
312 return GNSS_ERR_UNKNOWN;
313}
314
315gnss_err_enum mbtk_gnss_deinit()
316{
317 if(gnss_cli_fd < 0) {
318 LOGW("GNSS client not inited.");
319 return GNSS_ERR_UNKNOWN;
320 }
321
322 if(gnss_busy) {
323 LOGE("BUSY");
324 return GNSS_ERR_BUSY;
325 }
326
327 if(exit_fd[1] > 0) {
328 write(exit_fd[1], "EXIT", 4);
329 }
330
331 int ret = pthread_join(read_thread_id, NULL);
332 if(ret){
333 LOGE("pthrad_join fail(%d)",ret);
334 return GNSS_ERR_UNKNOWN;
335 }
336
337 close(gnss_cli_fd);
338 gnss_cli_fd = -1;
339 close(exit_fd[0]);
340 exit_fd[0] = -1;
341 close(exit_fd[1]);
342 exit_fd[1] = -1;
343 gnss_cb = NULL;
344 gnss_busy = FALSE;
345 pthread_mutex_destroy(&gnss_mutex);
346 pthread_cond_destroy(&gnss_cond);
347
348 return GNSS_ERR_OK;
349}
350
351gnss_err_enum mbtk_gnss_open(int type, int timeout)
352{
353 if(gnss_cli_fd < 0) {
354 LOGW("GNSS client not inited.");
355 return GNSS_ERR_UNKNOWN;
356 }
357
358 if(gnss_busy) {
359 LOGE("BUSY");
360 return GNSS_ERR_BUSY;
361 } else {
362 gnss_result = GNSS_ERR_OK;
363 gnss_busy = TRUE;
364 if(timeout > 0) {
365 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
366 }
367
368 // gnss_init:x
369 char cmd[32] = {0};
370 snprintf(cmd, sizeof(cmd), "gnss_init:%d", type);
371 sock_write(gnss_cli_fd, cmd, strlen(cmd));
372
373 pthread_mutex_lock(&gnss_mutex);
374 pthread_cond_wait(&gnss_cond, &gnss_mutex);
375 pthread_mutex_unlock(&gnss_mutex);
376
377 gnss_busy = FALSE;
378
379 return gnss_result;
380 }
381}
382
383gnss_err_enum mbtk_gnss_close(int timeout)
384{
385 if(gnss_cli_fd < 0) {
386 LOGW("GNSS client not inited.");
387 return GNSS_ERR_UNKNOWN;
388 }
389
390 if(gnss_busy) {
391 LOGE("BUSY");
392 return GNSS_ERR_BUSY;
393 } else {
394 gnss_result = GNSS_ERR_OK;
395 gnss_busy = TRUE;
396 if(timeout > 0) {
397 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
398 }
399
400 // gnss_deinit
401 char *cmd = "gnss_deinit";
402 sock_write(gnss_cli_fd, cmd, strlen(cmd));
403
404 pthread_mutex_lock(&gnss_mutex);
405 pthread_cond_wait(&gnss_cond, &gnss_mutex);
406 pthread_mutex_unlock(&gnss_mutex);
407
408 gnss_busy = FALSE;
409
410 return gnss_result;
411 }
412}
413
414
415gnss_err_enum mbtk_gnss_setting(const char *setting_cmd, int timeout)
416{
417 if(gnss_cli_fd < 0) {
418 LOGW("GNSS client not inited.");
419 return GNSS_ERR_UNKNOWN;
420 }
421
422 if(gnss_busy) {
423 LOGE("BUSY");
424 return GNSS_ERR_BUSY;
425 } else {
426 gnss_result = GNSS_ERR_OK;
427 gnss_busy = TRUE;
428 if(timeout > 0) {
429 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
430 }
431
432 // gnss_setting:cmd
433 char cmd[32] = {0};
434 snprintf(cmd, sizeof(cmd), "gnss_setting:%s", setting_cmd);
435 sock_write(gnss_cli_fd, cmd, strlen(cmd));
436
437 pthread_mutex_lock(&gnss_mutex);
438 pthread_cond_wait(&gnss_cond, &gnss_mutex);
439 pthread_mutex_unlock(&gnss_mutex);
440
441 gnss_busy = FALSE;
442
443 return gnss_result;
444 }
445}
446
447gnss_err_enum mbtk_gnss_dl(const char *fw_path, int timeout)
448{
449 if(gnss_cli_fd < 0) {
450 LOGW("GNSS client not inited.");
451 return GNSS_ERR_UNKNOWN;
452 }
453
454 if(gnss_busy) {
455 LOGE("BUSY");
456 return GNSS_ERR_BUSY;
457 } else {
458 gnss_result = GNSS_ERR_OK;
459 gnss_busy = TRUE;
460 if(timeout > 0) {
461 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
462 }
463
464 // gnss_dl:fw_name
465 char cmd[32] = {0};
466 snprintf(cmd, sizeof(cmd), "gnss_dl:%s", fw_path);
467 sock_write(gnss_cli_fd, cmd, strlen(cmd));
468
469 pthread_mutex_lock(&gnss_mutex);
470 pthread_cond_wait(&gnss_cond, &gnss_mutex);
471 pthread_mutex_unlock(&gnss_mutex);
472
473 gnss_busy = FALSE;
474
475 return gnss_result;
476 }
477}
478
479
480gnss_err_enum mbtk_gnss_ind_set(uint32 gnss_ind, int timeout)
481{
482 if(gnss_cli_fd < 0) {
483 LOGW("GNSS client not inited.");
484 return GNSS_ERR_UNKNOWN;
485 }
486
487 if(gnss_busy) {
488 LOGE("BUSY");
489 return GNSS_ERR_BUSY;
490 } else {
491 gnss_result = GNSS_ERR_OK;
492 gnss_busy = TRUE;
493 if(timeout > 0) {
494 mbtk_timer_set(gnss_timer_cb, timeout * 1000);
495 }
496
497 // gnss_ind:ind_type
498 char cmd[32] = {0};
499 snprintf(cmd, sizeof(cmd), "gnss_ind:%d", gnss_ind);
500 sock_write(gnss_cli_fd, cmd, strlen(cmd));
501
502 pthread_mutex_lock(&gnss_mutex);
503 pthread_cond_wait(&gnss_cond, &gnss_mutex);
504 pthread_mutex_unlock(&gnss_mutex);
505
506 gnss_busy = FALSE;
507
508 return gnss_result;
509 }
510}
511