/src/gpsd/gpsd-3.27.6~dev/libgps/libgps_core.c
Line | Count | Source |
1 | | /* libgps_core.c -- client interface library for the gpsd daemon |
2 | | * |
3 | | * Core portion of client library. Cals helpers to handle different eports. |
4 | | * |
5 | | * This file is Copyright by the GPSD project |
6 | | * SPDX-License-Identifier: BSD-2-clause |
7 | | */ |
8 | | |
9 | | #include "../include/gpsd_config.h" // must be before all includes |
10 | | |
11 | | #include <ctype.h> |
12 | | #include <errno.h> |
13 | | #include <fcntl.h> // open() |
14 | | #include <stdarg.h> |
15 | | #include <stdbool.h> |
16 | | #include <stdio.h> |
17 | | #include <stdlib.h> |
18 | | #include <string.h> |
19 | | #include <unistd.h> |
20 | | |
21 | | #include "../include/gpsd.h" |
22 | | #include "../include/libgps.h" |
23 | | #include "../include/gps_json.h" |
24 | | #include "../include/strfuncs.h" |
25 | | |
26 | | int libgps_debuglevel = 0; |
27 | | FILE *debugfp = NULL; |
28 | | |
29 | | // control the level and destination of debug trace messages |
30 | | void gps_enable_debug(int level, FILE * fp) |
31 | 0 | { |
32 | 0 | libgps_debuglevel = level; |
33 | 0 | debugfp = fp; |
34 | 0 | json_enable_debug(level - DEBUG_JSON, fp); |
35 | 0 | } |
36 | | |
37 | | /* assemble command in printf(3) style |
38 | | * do not call directly, us libgps_debug_trace() |
39 | | */ |
40 | | // HOTCODE! Do not change without profiling. |
41 | | void libgps_trace(const char *fmt, ...) |
42 | 0 | { |
43 | 0 | va_list ap; |
44 | |
|
45 | 0 | va_start(ap, fmt); |
46 | 0 | vfprintf(debugfp, fmt, ap); |
47 | 0 | va_end(ap); |
48 | 0 | } |
49 | | |
50 | | #define CONDITIONALLY_UNUSED UNUSED |
51 | | |
52 | | /* gps_open(host,) -- open a connection for reading from gpsd |
53 | | * |
54 | | * host can be: |
55 | | * a host name or host ip - to connect to host |
56 | | * port is numeric or symbolic port to connect to |
57 | | * GPSD_DBUS_EXPORT "DBUS export" - to connect to local DBUS |
58 | | * GPSD_FILE_LOCAL "local file" - to read to local file |
59 | | * port is file name to open |
60 | | * GPSD_SHARED_MEMORY "shared memory" - to connect to local chared memory |
61 | | * |
62 | | * Return: 0 osnuccess |
63 | | * less than zero on failure |
64 | | */ |
65 | | int gps_open(const char *host, const char *port, |
66 | | struct gps_data_t *gpsdata) |
67 | 0 | { |
68 | 0 | int status = -100; |
69 | |
|
70 | 0 | errno = 0; |
71 | 0 | if (!gpsdata) { |
72 | 0 | return NL_NOHOST; |
73 | 0 | } |
74 | | |
75 | | // save for later |
76 | 0 | gpsdata->source.server = host; |
77 | 0 | gpsdata->source.port = port; |
78 | |
|
79 | 0 | if (NULL != host && |
80 | 0 | 0 == strcmp(host, GPSD_LOCAL_FILE)) { |
81 | 0 | intptr_t fd; |
82 | |
|
83 | 0 | libgps_debug_trace(DEBUG_CALLS, "libgps: INFO: gps_open%sILE)\n", |
84 | 0 | host); |
85 | 0 | if (NULL == port) { |
86 | 0 | libgps_debug_trace(DEBUG_CALLS, |
87 | 0 | "libgps: ERROR: gps_open(%s) missing port\n", |
88 | 0 | host); |
89 | 0 | return FILE_FAIL; |
90 | 0 | } |
91 | 0 | fd = open(port, O_RDONLY); |
92 | 0 | if (0 > fd) { |
93 | 0 | libgps_debug_trace(DEBUG_CALLS, "libgps: ERROR: gps_open(%s) %d\n", |
94 | 0 | port, errno); |
95 | 0 | return FILE_FAIL; |
96 | 0 | } |
97 | 0 | gpsdata->gps_fd = (gps_fd_t)fd; |
98 | 0 | status = 0; |
99 | | // set up for line-buffered I/O over the daemon socket |
100 | 0 | gpsdata->privdata = |
101 | 0 | (struct privdata_t *)calloc(1, sizeof(struct privdata_t)); |
102 | 0 | if (NULL == gpsdata->privdata) { |
103 | 0 | return -1; |
104 | 0 | } |
105 | 0 | } |
106 | 0 | #ifdef SHM_EXPORT_ENABLE |
107 | 0 | else if (NULL != host && |
108 | 0 | 0 == strcmp(host, GPSD_SHARED_MEMORY)) { |
109 | 0 | status = gps_shm_open(gpsdata); |
110 | 0 | if (0 != status) { |
111 | 0 | if (-2 == status ) { |
112 | 0 | return SHM_NOATTACH; |
113 | 0 | } |
114 | 0 | if (-3 == status ) { |
115 | 0 | return SHM_CALLOC; |
116 | 0 | } |
117 | | // -1, or other error |
118 | 0 | return SHM_NOSHARED; |
119 | 0 | } |
120 | 0 | } |
121 | 0 | #define USES_HOST |
122 | 0 | #endif // SHM_EXPORT_ENABLE |
123 | | |
124 | | #ifdef DBUS_EXPORT_ENABLE |
125 | | else if (NULL != host && |
126 | | 0 == strcmp(host, GPSD_DBUS_EXPORT)) { |
127 | | status = gps_dbus_open(gpsdata); |
128 | | if (0 != status ) { |
129 | | return DBUS_FAILURE; |
130 | | } |
131 | | } |
132 | | #define USES_HOST |
133 | | #endif // DBUS_EXPORT_ENABLE |
134 | | |
135 | 0 | else { |
136 | | // last shot, try host:port |
137 | 0 | status = gps_sock_open(host, port, gpsdata); |
138 | 0 | } |
139 | 0 | #define USES_HOST |
140 | | |
141 | | #ifndef USES_HOST |
142 | | if (NULL == host) { |
143 | | // Should not happen, but this pacifies Codacy |
144 | | (void)fprintf(stderr, |
145 | | "No methods available for connecting to NULL == host!\n"); |
146 | | } else { |
147 | | (void)fprintf(stderr, |
148 | | "No methods available for connecting to %s!\n", host); |
149 | | } |
150 | | #endif // USES_HOST |
151 | 0 | #undef USES_HOST |
152 | | |
153 | 0 | gpsdata->set = 0; |
154 | 0 | gpsdata->satellites_used = 0; |
155 | 0 | gps_clear_att(&(gpsdata->attitude)); |
156 | 0 | gps_clear_dop(&(gpsdata->dop)); |
157 | 0 | gps_clear_fix(&(gpsdata->fix)); |
158 | 0 | gps_clear_gst(&(gpsdata->gst)); |
159 | 0 | gps_clear_log(&(gpsdata->log)); |
160 | |
|
161 | 0 | return status; |
162 | 0 | } |
163 | | |
164 | | // close a gpsd connection |
165 | | int gps_close(struct gps_data_t *gpsdata CONDITIONALLY_UNUSED) |
166 | 0 | { |
167 | 0 | int status = -1; |
168 | |
|
169 | 0 | libgps_debug_trace(DEBUG_CALLS, "%s", "libgps: gps_close()\n"); |
170 | |
|
171 | 0 | #ifdef SHM_EXPORT_ENABLE |
172 | 0 | if (BAD_SOCKET((intptr_t)(gpsdata->gps_fd))) { |
173 | 0 | gps_shm_close(gpsdata); |
174 | 0 | status = 0; |
175 | 0 | } |
176 | 0 | #endif // SHM_EXPORT_ENABLE |
177 | |
|
178 | 0 | if (-1 == status ) { |
179 | 0 | status = gps_sock_close(gpsdata); |
180 | 0 | } |
181 | |
|
182 | 0 | return status; |
183 | 0 | } |
184 | | |
185 | | /* wait for and read data from the daemon or file |
186 | | * |
187 | | * parameters: |
188 | | * gps_data_t *gpsdata -- structure for GPS data |
189 | | * char *message -- NULL, or optional buffer for received JSON |
190 | | * int message_len -- zero, or sizeof(message) |
191 | | * |
192 | | * Return: |
193 | | * -1 == error |
194 | | * -2 == EOF |
195 | | * zero OK |
196 | | */ |
197 | | int gps_read(struct gps_data_t *gpsdata, char *message, int message_len) |
198 | 0 | { |
199 | 0 | int status = -1; |
200 | |
|
201 | 0 | libgps_debug_trace(DEBUG_CALLS, "%s", "libgps: gps_read() begins\n"); |
202 | 0 | if ((NULL != message) && |
203 | 0 | (0 < message_len)) { |
204 | | // be sure message is zero length |
205 | | // we do not memset() as this is time critical input path |
206 | 0 | *message = '\0'; |
207 | 0 | } |
208 | 0 | if (NULL == PRIVATE(gpsdata)) { |
209 | 0 | char err[] = "gps_read() NULL == privdata"; |
210 | 0 | libgps_debug_trace(DEBUG_CALLS, "libgps: %s\n", err); |
211 | 0 | strlcpy(gpsdata->error, err, sizeof(gpsdata->error)); |
212 | 0 | gpsdata->set = ERROR_SET; |
213 | 0 | return -1; |
214 | 0 | } |
215 | | |
216 | 0 | if (NULL != gpsdata->source.server && |
217 | 0 | 0 == strcmp(gpsdata->source.server, GPSD_LOCAL_FILE)) { |
218 | | // local file read |
219 | 0 | char *eol, *eptr; |
220 | 0 | ssize_t read_ret, message_len; |
221 | |
|
222 | 0 | errno = 0; |
223 | | |
224 | | // scan to find end of message (\n), or end of buffer |
225 | 0 | eol = PRIVATE(gpsdata)->buffer; |
226 | | |
227 | | // fill the buffer |
228 | 0 | #if !defined(USE_QT) |
229 | | // Coverity takes the first branch, we want this checked. |
230 | 0 | eptr = eol + PRIVATE(gpsdata)->waiting; |
231 | 0 | read_ret = read(gpsdata->gps_fd, eptr, |
232 | 0 | sizeof(PRIVATE(gpsdata)->buffer) - |
233 | 0 | PRIVATE(gpsdata)->waiting - 1); |
234 | | #else |
235 | | read_ret = -1; // TBD |
236 | | #endif |
237 | 0 | if (0 >= read_ret) { |
238 | 0 | int ret; |
239 | | |
240 | | // EOL, or error |
241 | 0 | if ( 0 == read_ret) { |
242 | 0 | strlcpy(gpsdata->error, "EOF", sizeof(gpsdata->error)); |
243 | 0 | ret = -2; |
244 | 0 | } else { |
245 | 0 | strlcpy(gpsdata->error, "ERROR", sizeof(gpsdata->error)); |
246 | 0 | ret = -1; |
247 | 0 | } |
248 | 0 | gpsdata->set = ERROR_SET; |
249 | 0 | libgps_debug_trace(DEBUG_CALLS, "libgps: %s\n", gpsdata->error); |
250 | 0 | return ret; |
251 | 0 | } |
252 | 0 | gpsdata->set &= ~PACKET_SET; |
253 | 0 | PRIVATE(gpsdata)->waiting += read_ret; |
254 | 0 | eptr = eol + PRIVATE(gpsdata)->waiting; |
255 | |
|
256 | 0 | while ((eptr > eol) && |
257 | 0 | ('\n' != *eol)) { |
258 | 0 | eol++; |
259 | 0 | } |
260 | |
|
261 | 0 | if (eol >= eptr) { |
262 | | /* Buffer is full but still didn't get a message. |
263 | | * discard and try again. */ |
264 | 0 | libgps_debug_trace(DEBUG_CALLS, "%s", |
265 | 0 | "libgps: gps_read() buffer full, " |
266 | 0 | "but no message\n"); |
267 | 0 | PRIVATE(gpsdata)->buffer[0] = '\0'; |
268 | 0 | PRIVATE(gpsdata)->waiting = 0; |
269 | 0 | return -1; |
270 | 0 | } |
271 | | /* else have a full message in buffer |
272 | | * eol now points to trailing \n in a full message */ |
273 | 0 | *eol = '\0'; |
274 | | /* why the 1? We want the NUL. |
275 | | * |0|1|2|3|4|5| 6|7| |
276 | | * |1|2|3|4|5|6|\n|X| |
277 | | * buffer^ eol^ |
278 | | * buffer = 0 |
279 | | * eol = 6 |
280 | | * eol-buffer = 6-0 = 6, size of the line data is 7 bytes with \n |
281 | | * eol-buffer+1 = 6-0+1 = 7 |
282 | | */ |
283 | 0 | message_len = 1 + eol - PRIVATE(gpsdata)->buffer; |
284 | |
|
285 | 0 | if (NULL != message) { |
286 | | // user wants a copy, including NUL |
287 | 0 | memcpy(message, PRIVATE(gpsdata)->buffer, message_len); |
288 | 0 | } |
289 | 0 | (void)clock_gettime(CLOCK_REALTIME, &gpsdata->online); |
290 | | // unpack the JSON message |
291 | 0 | status = gps_unpack(PRIVATE(gpsdata)->buffer, gpsdata); |
292 | | |
293 | | // calculate length of good data still in buffer |
294 | 0 | PRIVATE(gpsdata)->waiting -= message_len; |
295 | |
|
296 | 0 | if (0 >= PRIVATE(gpsdata)->waiting) { |
297 | | // no waiting data, or overflow, clear the buffer, just in case |
298 | 0 | *PRIVATE(gpsdata)->buffer = '\0'; |
299 | 0 | PRIVATE(gpsdata)->waiting = 0; |
300 | 0 | } else { |
301 | | // shift the remaining data to the front. |
302 | 0 | memmove(PRIVATE(gpsdata)->buffer, |
303 | 0 | PRIVATE(gpsdata)->buffer + message_len, |
304 | 0 | PRIVATE(gpsdata)->waiting); |
305 | 0 | } |
306 | 0 | gpsdata->set |= PACKET_SET; |
307 | 0 | #ifdef SHM_EXPORT_ENABLE |
308 | 0 | } else if (BAD_SOCKET((intptr_t)(gpsdata->gps_fd))) { |
309 | 0 | status = gps_shm_read(gpsdata); |
310 | 0 | #endif // SHM_EXPORT_ENABLE |
311 | |
|
312 | 0 | } else if (-1 == status && |
313 | 0 | !BAD_SOCKET((intptr_t)(gpsdata->gps_fd))) { |
314 | 0 | status = gps_sock_read(gpsdata, message, message_len); |
315 | 0 | } |
316 | | |
317 | 0 | libgps_debug_trace(DEBUG_CALLS, "libgps: gps_read() -> %d (%s)\n", |
318 | 0 | status, gps_maskdump(gpsdata->set)); |
319 | |
|
320 | 0 | return status; |
321 | 0 | } |
322 | | |
323 | | /* send a command to the gpsd instance |
324 | | * |
325 | | * Return: 0 -- success |
326 | | * Return: negative -- fail |
327 | | */ |
328 | | int gps_send(struct gps_data_t *gpsdata CONDITIONALLY_UNUSED, |
329 | | const char *fmt CONDITIONALLY_UNUSED, ...) |
330 | 0 | { |
331 | 0 | int status = -1; |
332 | 0 | char buf[BUFSIZ]; |
333 | 0 | va_list ap; |
334 | |
|
335 | 0 | va_start(ap, fmt); |
336 | 0 | (void)vsnprintf(buf, sizeof(buf) - 2, fmt, ap); |
337 | 0 | va_end(ap); |
338 | | // codacy deos not like strlen() |
339 | 0 | if ('\n' != buf[strnlen(buf, sizeof(buf)) - 1]) { |
340 | 0 | (void)strlcat(buf, "\n", sizeof(buf)); |
341 | 0 | } |
342 | |
|
343 | 0 | status = gps_sock_send(gpsdata, buf); |
344 | |
|
345 | 0 | return status; |
346 | 0 | } |
347 | | |
348 | | /* setup a stream |
349 | | * |
350 | | * FIXME: works on socket streams, but not on shared memory stream. |
351 | | * |
352 | | * Return: 0 -- success |
353 | | * Return: negative -- fail |
354 | | */ |
355 | | int gps_stream(struct gps_data_t *gpsdata, watch_t flags, |
356 | | const char *d CONDITIONALLY_UNUSED) |
357 | 0 | { |
358 | 0 | int status = -1; |
359 | |
|
360 | 0 | if (NULL != gpsdata->source.server && |
361 | 0 | 0 == strcmp(gpsdata->source.server, GPSD_LOCAL_FILE)) { |
362 | | // lodal cile, read-only |
363 | 0 | flags |= WATCH_READONLY; |
364 | 0 | } |
365 | 0 | gpsdata->watch = flags; |
366 | 0 | if (WATCH_READONLY & flags) { |
367 | | // read only |
368 | 0 | return 0; |
369 | 0 | } |
370 | 0 | status = gps_sock_stream(gpsdata, flags, d); |
371 | |
|
372 | 0 | return status; |
373 | 0 | } |
374 | | |
375 | | // return the contents of the client data buffer |
376 | | const char *gps_data(const struct gps_data_t *gpsdata CONDITIONALLY_UNUSED) |
377 | 0 | { |
378 | 0 | const char *bufp = NULL; |
379 | |
|
380 | 0 | bufp = gps_sock_data(gpsdata); |
381 | |
|
382 | 0 | return bufp; |
383 | 0 | } |
384 | | |
385 | | /* is there input waiting from the GPS? |
386 | | * timeout is in uSec |
387 | | */ |
388 | | bool gps_waiting(const struct gps_data_t *gpsdata, |
389 | | int timeout CONDITIONALLY_UNUSED) |
390 | 0 | { |
391 | | // this is bogus, but I can't think of a better solution yet |
392 | 0 | bool waiting = true; |
393 | |
|
394 | 0 | if (NULL != gpsdata->source.server && |
395 | 0 | 0 == strcmp(gpsdata->source.server, GPSD_LOCAL_FILE)) { |
396 | | // always ready, until EOF |
397 | 0 | return true; |
398 | 0 | } |
399 | 0 | #ifdef SHM_EXPORT_ENABLE |
400 | 0 | if (SHM_PSEUDO_FD == (intptr_t)(gpsdata->gps_fd)) { |
401 | 0 | waiting = gps_shm_waiting(gpsdata, timeout); |
402 | 0 | return waiting; |
403 | 0 | } |
404 | 0 | #endif // SHM_EXPORT_ENABLE |
405 | | |
406 | 0 | if (0 <= (intptr_t)(gpsdata->gps_fd)) { |
407 | 0 | waiting = gps_sock_waiting(gpsdata, timeout); |
408 | 0 | } |
409 | |
|
410 | 0 | return waiting; |
411 | 0 | } |
412 | | |
413 | | /* run a main loop with a specified handler |
414 | | * |
415 | | * Returns: -1 on timeout or read error |
416 | | * -2 read error |
417 | | * FIXME: read error should return different than timeout |
418 | | */ |
419 | | int gps_mainloop(struct gps_data_t *gpsdata CONDITIONALLY_UNUSED, |
420 | | int timeout CONDITIONALLY_UNUSED, |
421 | | void (*hook)(struct gps_data_t *gpsdata) CONDITIONALLY_UNUSED) |
422 | 0 | { |
423 | 0 | int status = -1; |
424 | |
|
425 | 0 | libgps_debug_trace(DEBUG_CALLS, "%s", "libgps: gps_mainloop() begins\n"); |
426 | |
|
427 | 0 | #ifdef SHM_EXPORT_ENABLE |
428 | 0 | if (SHM_PSEUDO_FD == (intptr_t)(gpsdata->gps_fd)) { |
429 | 0 | libgps_debug_trace(DEBUG_CALLS, "%s", |
430 | 0 | "libgps: gps_shm_mainloop() begins\n"); |
431 | 0 | status = gps_shm_mainloop(gpsdata, timeout, hook); |
432 | 0 | } |
433 | 0 | #endif // SHM_EXPORT_ENABLE |
434 | | #ifdef DBUS_EXPORT_ENABLE |
435 | | if (DBUS_PSEUDO_FD == (intptr_t)(gpsdata->gps_fd)) { |
436 | | libgps_debug_trace(DEBUG_CALLS, "%s", |
437 | | "libgps: gps_dbus_mainloop() begins\n"); |
438 | | status = gps_dbus_mainloop(gpsdata, timeout, hook); |
439 | | } |
440 | | #endif // DBUS_EXPORT_ENABLE |
441 | 0 | if (0 <= (intptr_t)(gpsdata->gps_fd)) { |
442 | 0 | libgps_debug_trace(DEBUG_CALLS, "%s", |
443 | 0 | "libgps: gps_sock_mainloop() begins\n"); |
444 | 0 | status = gps_sock_mainloop(gpsdata, timeout, hook); |
445 | 0 | } |
446 | |
|
447 | 0 | libgps_debug_trace(DEBUG_CALLS, "libgps: gps_mainloop() -> %d (%s)\n", |
448 | 0 | status, gps_maskdump(gpsdata->set)); |
449 | |
|
450 | 0 | return status; |
451 | 0 | } |
452 | | |
453 | | extern const char *gps_errstr(const int err) |
454 | 0 | { |
455 | | /* |
456 | | * We might add our own error codes in the future, e.g for |
457 | | * protocol compatibility checks |
458 | | */ |
459 | | #ifdef USE_QT |
460 | | static char buf[32]; |
461 | | |
462 | | (void)snprintf(buf, sizeof(buf), "Qt error %d", err); |
463 | | return buf; |
464 | | #else // USE_QT |
465 | 0 | switch (err) { |
466 | 0 | case SHM_NOSHARED: |
467 | 0 | return "no shared-memory segment or daemon not running"; |
468 | 0 | case SHM_NOATTACH: |
469 | 0 | return "attach failed for unknown reason"; |
470 | 0 | case DBUS_FAILURE: |
471 | 0 | return "DBUS initialization failure"; |
472 | 0 | case FILE_FAIL: |
473 | 0 | return "failed to open file"; |
474 | 0 | case SHM_CALLOC: |
475 | 0 | return "calloc() failed"; |
476 | 0 | default: |
477 | 0 | return netlib_errstr(err); |
478 | 0 | } |
479 | 0 | #endif // USE_QT |
480 | 0 | } |
481 | | |
482 | | void libgps_dump_state(struct gps_data_t *collect) |
483 | 0 | { |
484 | 0 | char ts_buf[TIMESPEC_LEN]; |
485 | | |
486 | | // no need to dump the entire state, this is a sanity check |
487 | 0 | #ifndef USE_QT |
488 | 0 | (void)fprintf(debugfp, "flags: (0x%04x) %s\n", |
489 | 0 | (unsigned int)collect->set, gps_maskdump(collect->set)); |
490 | 0 | #endif |
491 | 0 | if (ONLINE_SET & collect->set) { |
492 | 0 | (void)fprintf(debugfp, "ONLINE: %s\n", |
493 | 0 | timespec_str(&collect->online, ts_buf, sizeof(ts_buf))); |
494 | 0 | } |
495 | 0 | if (TIME_SET & collect->set) { |
496 | 0 | (void)fprintf(debugfp, "TIME: %s\n", |
497 | 0 | timespec_str(&collect->fix.time, ts_buf, sizeof(ts_buf))); |
498 | 0 | } |
499 | | // NOTE: %.7f needed for cm level accurate GPS |
500 | 0 | if (LATLON_SET & collect->set) { |
501 | 0 | (void)fprintf(debugfp, "LATLON: lat/lon: %.7lf %.7lf\n", |
502 | 0 | collect->fix.latitude, collect->fix.longitude); |
503 | 0 | } |
504 | 0 | if (ALTITUDE_SET & collect->set) { |
505 | 0 | (void)fprintf(debugfp, "ALTITUDE: altHAE: %lf U: climb: %lf\n", |
506 | 0 | collect->fix.altHAE, collect->fix.climb); |
507 | 0 | } |
508 | 0 | if (SPEED_SET & collect->set) { |
509 | 0 | (void)fprintf(debugfp, "SPEED: %lf\n", collect->fix.speed); |
510 | 0 | } |
511 | 0 | if (TRACK_SET & collect->set) { |
512 | 0 | (void)fprintf(debugfp, "TRACK: track: %lf\n", collect->fix.track); |
513 | 0 | } |
514 | 0 | if (MAGNETIC_TRACK_SET & collect->set) { |
515 | 0 | (void)fprintf(debugfp, "MAGNETIC_TRACK: magtrack: %lf\n", |
516 | 0 | collect->fix.magnetic_track); |
517 | 0 | } |
518 | 0 | if (CLIMB_SET & collect->set) { |
519 | 0 | (void)fprintf(debugfp, "CLIMB: climb: %lf\n", collect->fix.climb); |
520 | 0 | } |
521 | 0 | if (STATUS_SET & collect->set) { |
522 | 0 | (void)fprintf(debugfp, "STATUS: status: %d (%s)\n", |
523 | 0 | collect->fix.status, |
524 | 0 | val2str(collect->fix.status, vstatus_str)); |
525 | 0 | } |
526 | 0 | if (MODE_SET & collect->set) { |
527 | 0 | (void)fprintf(debugfp, "MODE: mode: %d (%s)\n", |
528 | 0 | collect->fix.mode, |
529 | 0 | val2str(collect->fix.mode, vmode_str)); |
530 | 0 | } |
531 | 0 | if (DOP_SET & collect->set) { |
532 | 0 | (void)fprintf(debugfp, |
533 | 0 | "DOP: satellites %d gdop %f hdop %f pdop %f tdop %f " |
534 | 0 | "vdop %f xdop %f ydop %f\n", |
535 | 0 | collect->satellites_used, |
536 | 0 | collect->dop.gdop, |
537 | 0 | collect->dop.hdop, |
538 | 0 | collect->dop.pdop, |
539 | 0 | collect->dop.tdop, |
540 | 0 | collect->dop.vdop, |
541 | 0 | collect->dop.xdop, |
542 | 0 | collect->dop.ydop); |
543 | 0 | } |
544 | 0 | if (VERSION_SET & collect->set) { |
545 | 0 | (void)fprintf(debugfp, "VERSION: release=%s rev=%s proto=%d.%d\n", |
546 | 0 | collect->version.release, |
547 | 0 | collect->version.rev, |
548 | 0 | collect->version.proto_major, |
549 | 0 | collect->version.proto_minor); |
550 | 0 | } |
551 | 0 | if (POLICY_SET & collect->set) { |
552 | 0 | (void)fprintf(debugfp, |
553 | 0 | "POLICY: watcher=%s nmea=%s raw=%d scaled=%s timing=%s, " |
554 | 0 | "split24=%s pps=%s, devpath=%s\n", |
555 | 0 | collect->policy.watcher ? "true" : "false", |
556 | 0 | collect->policy.nmea ? "true" : "false", |
557 | 0 | collect->policy.raw, |
558 | 0 | collect->policy.scaled ? "true" : "false", |
559 | 0 | collect->policy.timing ? "true" : "false", |
560 | 0 | collect->policy.split24 ? "true" : "false", |
561 | 0 | collect->policy.pps ? "true" : "false", |
562 | 0 | collect->policy.devpath); |
563 | 0 | } |
564 | 0 | if (SATELLITE_SET & collect->set) { |
565 | 0 | struct satellite_t *sp; |
566 | |
|
567 | 0 | if (MAXCHANNELS < collect->satellites_visible) { |
568 | 0 | collect->satellites_visible = MAXCHANNELS; |
569 | 0 | } |
570 | 0 | (void)fprintf(debugfp, "SKY: satellites in view: %d\n", |
571 | 0 | collect->satellites_visible); |
572 | 0 | for (sp = collect->skyview; |
573 | 0 | sp < collect->skyview + collect->satellites_visible; |
574 | 0 | sp++) { |
575 | 0 | (void)fprintf(debugfp, " %2.2d: %4.1f %5.1f %3.0f %c\n", |
576 | 0 | sp->PRN, sp->elevation, |
577 | 0 | sp->azimuth, sp->ss, |
578 | 0 | sp->used ? 'Y' : 'N'); |
579 | 0 | } |
580 | 0 | } |
581 | 0 | if (RAW_SET & collect->set) { |
582 | 0 | (void)fprintf(debugfp, "RAW: got raw data\n"); |
583 | 0 | } |
584 | 0 | if (DEVICE_SET & collect->set) { |
585 | 0 | (void)fprintf(debugfp, "DEVICE: Device is '%s', driver is '%s'\n", |
586 | 0 | collect->dev.path, collect->dev.driver); |
587 | 0 | } |
588 | 0 | if (DEVICELIST_SET & collect->set) { |
589 | 0 | unsigned i; |
590 | 0 | (void)fprintf(debugfp, "DEVICELIST:%d devices:\n", |
591 | 0 | collect->devices.ndevices); |
592 | 0 | for (i = 0; i < collect->devices.ndevices; i++) { |
593 | 0 | (void)fprintf(debugfp, "%d: path='%s' driver='%s'\n", |
594 | 0 | collect->devices.ndevices, |
595 | 0 | collect->devices.list[i].path, |
596 | 0 | collect->devices.list[i].driver); |
597 | 0 | } |
598 | 0 | } |
599 | 0 | } |
600 | | |
601 | | // vim: set expandtab shiftwidth=4 |