-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfsgpsd.c
131 lines (121 loc) · 3.56 KB
/
fsgpsd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <gps.h>
#include <math.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include "cmem.h"
#include "clog.h"
#include "fitsec.h"
#include "fsgpsd.h"
static char _gpsd_default_port[] = "2947";
#define MAX_PORTS 16
static struct gps_data_t _gps[MAX_PORTS] = {};
static size_t _gps_cnt = 0;
static pthread_t _thr;
static pthread_mutex_t _mtx = PTHREAD_MUTEX_INITIALIZER;
int libgps_get_data(int ch, FSGpsData * data)
{
int ret = -1;
if(ch < _gps_cnt){
pthread_mutex_lock(&_mtx);
if(_gps[ch].gps_fd > 0){
ret =0 ;
if(_gps[ch].status > 0) { // only when fix
if(isfinite(_gps[ch].fix.latitude) && isfinite(_gps[ch].fix.longitude)){
data->position.latitude = (int32_t)floor(_gps[ch].fix.latitude * 10000000.0);
data->position.longitude = (int32_t)floor(_gps[ch].fix.longitude * 10000000.0);
}
data->time = FSTime64from32(_gps[ch].fix.time.tv_sec) + (_gps[ch].fix.time.tv_sec/1000);
if(isfinite(_gps[ch].fix.speed)){
data->speed = (long)floor(_gps[ch].fix.speed * 100.0); // in cm/s
}else{
data->speed = 0;
}
if(isfinite(_gps[ch].fix.track)){
data->heading = (long)floor(_gps[ch].fix.track * 10.0); // in 0.1 degree
}else{
data->heading = 0;
}
data->dx = _gps[ch].fix.epx;
data->dy = _gps[ch].fix.epy;
data->dh = _gps[ch].fix.eph;
data->ds = _gps[ch].fix.eps;
ret = 1;
}
}
}
pthread_mutex_unlock(&_mtx);
return ret;
}
static void* gps_thread(char* p)
{
fd_set rset;
while(1){
FD_ZERO(&rset);
// FD_ZERO(&eset);
int maxfd = 0;
pthread_mutex_lock(&_mtx);
for(int ch; ch < _gps_cnt; ch++){
if(_gps[ch].gps_fd > 0){
FD_SET(_gps[ch].gps_fd, &rset);
// FD_SET(_gps[ch].gps_fd, &eset);
if(_gps[ch].gps_fd > maxfd){
maxfd = _gps[ch].gps_fd;
}
}
}
pthread_mutex_unlock(&_mtx);
struct timeval tv = {0, 100000};
int n = select(maxfd + 1, &rset, NULL, NULL, &tv);
pthread_testcancel ();
for(int ch = 0; n && ch < _gps_cnt; ch++){
if(FD_ISSET(_gps[ch].gps_fd, &rset)){
pthread_mutex_lock(&_mtx);
gps_read(&_gps[ch], NULL, 0);
pthread_mutex_unlock(&_mtx);
n--;
}
}
}
return NULL;
}
void libgps_stop( int ch)
{
int stop = 1;
pthread_mutex_lock(&_mtx);
gps_close(&_gps[ch]);
_gps[ch].gps_fd = 0;
for(int ch = 0; ch < _gps_cnt; ch++){
if(_gps[ch].gps_fd > 0){
stop = 0;
break;
}
}
pthread_mutex_unlock(&_mtx);
if(stop){
void * rc;
if(0 == pthread_cancel(_thr)){
pthread_join(_thr, &rc);
}
}
}
int libgps_start(char * url )
{
char * port = strrchr(url, ':');
if(port){
*(port++) = 0;
}else{
port = &_gpsd_default_port[0];
}
// select fd
int rc = gps_open(url, port, &_gps[_gps_cnt]);
if(rc == 0){
if(0 == cfetch_and_inc(&_gps_cnt)){
// 1st
pthread_create(&_thr, NULL, (void*(*)(void*))gps_thread, NULL);
}
}else{
mclog_error(GPSD, "%s:%s : %s\n", url, port, gps_errstr(rc));
}
return rc;
}