Contents of /trunk/src/gps.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 156 - (hide annotations)
Tue Nov 3 13:15:35 2009 UTC (14 years, 6 months ago) by harbaum
File MIME type: text/plain
File size: 19104 byte(s)
GCVote gui
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of GPXView.
5     *
6     * GPXView is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * GPXView is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include <stdio.h>
21     #include <string.h>
22     #include <math.h>
23    
24     #include "gpxview.h"
25    
26    
27     #ifdef USE_MAEMO
28     #ifdef ENABLE_GPSBT
29     #include <gpsbt.h>
30     #include <gpsmgr.h>
31     #endif
32     #include <errno.h>
33     #endif
34    
35 harbaum 156 static void gps_unregister_all(appdata_t *appdata);
36    
37 harbaum 1 #ifndef ENABLE_LIBLOCATION
38    
39     /* maybe user configurable later on ... */
40     #define GPSD_HOST "127.0.0.1"
41     #define GPSD_PORT 2947
42    
43     gps_sat_t *gps_get_sats(appdata_t *appdata) {
44     gps_sat_t *retval = NULL;
45    
46     g_mutex_lock(appdata->gps_state->mutex);
47     if(appdata->gps_state->gpsdata.set & SATELLITE_SET) {
48     int i;
49     retval = malloc(sizeof(gps_sat_t));
50     retval->num = appdata->gps_state->gpsdata.satellites;
51    
52     retval->PRN = malloc(sizeof(int)*retval->num);
53     retval->used = malloc(sizeof(int)*retval->num);
54     retval->ss = malloc(sizeof(int)*retval->num);
55    
56     if(retval->num) {
57     for(i=0;i<retval->num;i++) {
58     retval->PRN[i] = appdata->gps_state->gpsdata.PRN[i];
59     retval->ss[i] = appdata->gps_state->gpsdata.ss[i];
60     retval->used[i] = appdata->gps_state->gpsdata.used[i];
61     }
62     }
63     }
64    
65     g_mutex_unlock(appdata->gps_state->mutex);
66    
67     return retval;
68     }
69    
70     pos_t *gps_get_pos(appdata_t *appdata) {
71     static pos_t retval;
72    
73     retval.lat = NAN;
74    
75     g_mutex_lock(appdata->gps_state->mutex);
76     if(appdata->gps_state->gpsdata.set & STATUS_SET)
77     if(appdata->gps_state->gpsdata.status != STATUS_NO_FIX)
78     if(appdata->gps_state->gpsdata.set & LATLON_SET)
79     retval = appdata->gps_state->gpsdata.fix.pos;
80    
81     g_mutex_unlock(appdata->gps_state->mutex);
82    
83     if(isnan(retval.lat))
84     return NULL;
85    
86     return &retval;
87     }
88    
89     float gps_get_heading(appdata_t *appdata) {
90     float retval = NAN;
91    
92     g_mutex_lock(appdata->gps_state->mutex);
93     if(appdata->gps_state->gpsdata.set & STATUS_SET)
94     if(appdata->gps_state->gpsdata.status != STATUS_NO_FIX)
95     if(appdata->gps_state->gpsdata.set & TRACK_SET)
96     retval = appdata->gps_state->gpsdata.fix.track;
97    
98     g_mutex_unlock(appdata->gps_state->mutex);
99     return retval;
100     }
101    
102 harbaum 53 float gps_get_eph(appdata_t *appdata) {
103 harbaum 1 float retval = NAN;
104    
105     g_mutex_lock(appdata->gps_state->mutex);
106     if(appdata->gps_state->gpsdata.set & STATUS_SET)
107     if(appdata->gps_state->gpsdata.status != STATUS_NO_FIX)
108     retval = appdata->gps_state->gpsdata.fix.eph;
109    
110     g_mutex_unlock(appdata->gps_state->mutex);
111     return retval;
112     }
113    
114     static int gps_connect(gps_state_t *gps_state) {
115     GnomeVFSResult vfs_result;
116     #ifdef USE_MAEMO
117     char errstr[256] = "";
118    
119     /* We need to start gpsd (via gpsbt) first. */
120     memset(&gps_state->context, 0, sizeof(gpsbt_t));
121     errno = 0;
122    
123     if(gpsbt_start(NULL, 0, 0, 0, errstr, sizeof(errstr),
124     0, &gps_state->context) < 0) {
125 harbaum 156 printf("gps: Error connecting to GPS receiver: (%d) %s (%s)\n",
126 harbaum 1 errno, strerror(errno), errstr);
127     }
128     #endif
129    
130     /************** from here down pure gnome/gtk/gpsd ********************/
131    
132     /* try to connect to gpsd */
133     /* Create a socket to interact with GPSD. */
134    
135     int retries = 5;
136     while(retries &&
137     (GNOME_VFS_OK != (vfs_result = gnome_vfs_inet_connection_create(
138     &gps_state->iconn, GPSD_HOST, GPSD_PORT, NULL)))) {
139 harbaum 156 printf("gps: Error creating connection to GPSD, retrying ...\n");
140 harbaum 1
141     retries--;
142     sleep(1);
143     }
144    
145     if(!retries) {
146 harbaum 156 printf("gps: Finally failed ...\n");
147 harbaum 1 return -1;
148     }
149    
150     retries = 5;
151     while(retries && ((gps_state->socket =
152     gnome_vfs_inet_connection_to_socket(gps_state->iconn)) == NULL)) {
153 harbaum 156 printf("gps: Error creating connecting GPSD socket, retrying ...\n");
154 harbaum 1
155     retries--;
156     sleep(1);
157     }
158    
159     if(!retries) {
160 harbaum 156 printf("gps: Finally failed ...\n");
161 harbaum 1 return -1;
162     }
163    
164     GTimeVal timeout = { 10, 0 };
165     if(GNOME_VFS_OK != (vfs_result = gnome_vfs_socket_set_timeout(
166     gps_state->socket, &timeout, NULL))) {
167 harbaum 156 printf("gps: Error setting GPSD timeout\n");
168 harbaum 1 return -1;
169     }
170    
171 harbaum 156 printf("gps: GPSD connected ...\n");
172 harbaum 1
173     return 0;
174     }
175    
176     void gps_clear_fix(struct gps_fix_t *fixp) {
177     fixp->mode = MODE_NOT_SEEN;
178     fixp->pos.lat = fixp->pos.lon = NAN;
179     fixp->track = NAN;
180     fixp->speed = NAN;
181     fixp->climb = NAN;
182     fixp->altitude = NAN;
183     fixp->ept = NAN;
184     fixp->eph = NAN;
185     fixp->epd = NAN;
186     fixp->eps = NAN;
187     fixp->epc = NAN;
188     }
189    
190     /* unpack a daemon response into a status structure */
191     static void gps_unpack(char *buf, struct gps_data_t *gpsdata) {
192     char *ns, *sp, *tp;
193    
194     for(ns = buf; ns; ns = strstr(ns+1, "GPSD")) {
195     if(strncmp(ns, "GPSD", 4) == 0) {
196     /* the following should execute each time we have a good next sp */
197     for (sp = ns + 5; *sp != '\0'; sp = tp+1) {
198     tp = sp + strcspn(sp, ",\r\n");
199     if (*tp == '\0') tp--;
200     else *tp = '\0';
201    
202     switch (*sp) {
203     case 'A':
204     if (sp[2] == '?') {
205     gpsdata->fix.altitude = NAN;
206     } else {
207     (void)sscanf(sp, "A=%lf", &gpsdata->fix.altitude);
208     gpsdata->set |= ALTITUDE_SET;
209     }
210     break;
211     /* B - baudrate isn't supported by gpxview */
212     /* C - cycle isn't supported by gpxview */
213     /* D - utc time isn't supported by gpxview */
214     case 'E':
215 harbaum 53 gpsdata->fix.eph = NAN;
216 harbaum 1 /* epe should always be present if eph or epv is */
217     if (sp[2] != '?') {
218     char epe[20], eph[20], epv[20];
219     (void)sscanf(sp, "E=%s %s %s", epe, eph, epv);
220     #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)
221     gpsdata->fix.eph = DEFAULT(eph);
222     #undef DEFAULT
223     }
224     break;
225     /* F - device name isn't supported by gpxview */
226     /* I - gps id isn't supported by gpxview */
227     /* K - known devices list isn't supported by gpxview */
228     case 'M':
229     if (sp[2] == '?') {
230     gpsdata->fix.mode = MODE_NOT_SEEN;
231     } else {
232     gpsdata->fix.mode = atoi(sp+2);
233     gpsdata->set |= MODE_SET;
234     }
235     break;
236     /* N - driver mode reporting isn't supported by gpxview */
237     case 'O':
238     if (sp[2] == '?') {
239     gpsdata->set =
240     (gpsdata->set & SATELLITE_SET) | // fix for below
241     MODE_SET | STATUS_SET; // this clears sat info??
242     gpsdata->status = STATUS_NO_FIX;
243     gps_clear_fix(&gpsdata->fix);
244     } else {
245     struct gps_fix_t nf;
246     char tag[MAXTAGLEN+1], alt[20];
247     char eph[20], epv[20], track[20],speed[20], climb[20];
248     char epd[20], eps[20], epc[20], mode[2];
249     char timestr[20], ept[20], lat[20], lon[20];
250     int st = sscanf(sp+2,
251     "%8s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %1s",
252     tag, timestr, ept, lat, lon,
253     alt, eph, epv, track, speed, climb,
254     epd, eps, epc, mode);
255     if (st >= 14) {
256     #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)
257     nf.pos.lat = DEFAULT(lat);
258     nf.pos.lon = DEFAULT(lon);
259     nf.ept = DEFAULT(ept);
260     nf.altitude = DEFAULT(alt);
261     nf.eph = DEFAULT(eph);
262     nf.track = DEFAULT(track);
263     nf.speed = DEFAULT(speed);
264     nf.climb = DEFAULT(climb);
265     nf.epd = DEFAULT(epd);
266     nf.eps = DEFAULT(eps);
267     nf.epc = DEFAULT(epc);
268     #undef DEFAULT
269     if (st >= 15)
270     nf.mode = (mode[0] == '?') ? MODE_NOT_SEEN : atoi(mode);
271     else
272     nf.mode = (alt[0] == '?') ? MODE_2D : MODE_3D;
273     if (alt[0] != '?')
274     gpsdata->set |= ALTITUDE_SET | CLIMB_SET;
275     if (isnan(nf.eph)==0)
276     gpsdata->set |= HERR_SET;
277     if (isnan(nf.track)==0)
278     gpsdata->set |= TRACK_SET | SPEED_SET;
279     if (isnan(nf.eps)==0)
280     gpsdata->set |= SPEEDERR_SET;
281     if (isnan(nf.epc)==0)
282     gpsdata->set |= CLIMBERR_SET;
283     gpsdata->fix = nf;
284     gpsdata->set |= TIME_SET|TIMERR_SET|LATLON_SET|MODE_SET;
285     gpsdata->status = STATUS_FIX;
286     gpsdata->set |= STATUS_SET;
287     }
288     }
289     break;
290     case 'P':
291     if (sp[2] == '?') {
292     gpsdata->fix.pos.lat = NAN;
293     gpsdata->fix.pos.lon = NAN;
294     } else {
295     char lat[20], lon[20];
296     (void)sscanf(sp, "P=%19s %19s", lat, lon);
297     gpsdata->fix.pos.lat = g_ascii_strtod(lat, NULL);
298     gpsdata->fix.pos.lon = g_ascii_strtod(lon, NULL);
299     gpsdata->set |= LATLON_SET;
300     }
301     break;
302     case 'Q':
303     if (sp[2] == '?') {
304     gpsdata->satellites_used = 0;
305     gpsdata->pdop = 0;
306     gpsdata->hdop = 0;
307     gpsdata->vdop = 0;
308     } else {
309     (void)sscanf(sp, "Q=%d %lf %lf %lf %lf %lf",
310     &gpsdata->satellites_used,
311     &gpsdata->pdop,
312     &gpsdata->hdop,
313     &gpsdata->vdop,
314     &gpsdata->tdop,
315     &gpsdata->gdop);
316     gpsdata->set |= HDOP_SET | VDOP_SET | PDOP_SET;
317     }
318     break;
319     case 'S':
320     if (sp[2] == '?') {
321     gpsdata->status = -1;
322     } else {
323     gpsdata->status = atoi(sp+2);
324     gpsdata->set |= STATUS_SET;
325     }
326     break;
327     case 'T':
328     if (sp[2] == '?') {
329     gpsdata->fix.track = NAN;
330     } else {
331     (void)sscanf(sp, "T=%lf", &gpsdata->fix.track);
332     gpsdata->set |= TRACK_SET;
333     }
334     break;
335     case 'U':
336     if (sp[2] == '?') {
337     gpsdata->fix.climb = NAN;
338     } else {
339     (void)sscanf(sp, "U=%lf", &gpsdata->fix.climb);
340     gpsdata->set |= CLIMB_SET;
341     }
342     break;
343     case 'V':
344     if (sp[2] == '?') {
345     gpsdata->fix.speed = NAN;
346     } else {
347     (void)sscanf(sp, "V=%lf", &gpsdata->fix.speed);
348     /* V reply is in kt, fix.speed is in metres/sec */
349     gpsdata->fix.speed = gpsdata->fix.speed / MPS_TO_KNOTS;
350     gpsdata->set |= SPEED_SET;
351     }
352     break;
353     case 'X':
354     if (sp[2] == '?')
355     gpsdata->online = -1;
356     else {
357     (void)sscanf(sp, "X=%lf", &gpsdata->online);
358     gpsdata->set |= ONLINE_SET;
359     }
360     break;
361     case 'Y':
362     if (sp[2] == '?') {
363     gpsdata->satellites = 0;
364     } else {
365     int j, i1, i2, i3, i4, i5;
366     int PRN[MAXCHANNELS];
367     int elevation[MAXCHANNELS], azimuth[MAXCHANNELS];
368     int ss[MAXCHANNELS], used[MAXCHANNELS];
369     char tag[MAXTAGLEN+1], timestamp[21];
370    
371     (void)sscanf(sp, "Y=%8s %20s %d ",
372     tag, timestamp, &gpsdata->satellites);
373     for (j = 0; j < gpsdata->satellites; j++) {
374     PRN[j]=elevation[j]=azimuth[j]=ss[j]=used[j]=0;
375     }
376 harbaum 156 // printf("gps: sats = %d\n", gpsdata->satellites);
377 harbaum 1 for (j = 0, gpsdata->satellites_used = 0; j < gpsdata->satellites; j++) {
378     if ((sp != NULL) && ((sp = strchr(sp, ':')) != NULL)) {
379     sp++;
380     (void)sscanf(sp, "%d %d %d %d %d", &i1, &i2, &i3, &i4, &i5);
381     PRN[j] = i1;
382     elevation[j] = i2; azimuth[j] = i3;
383     ss[j] = i4; used[j] = i5;
384     if (i5 == 1)
385     gpsdata->satellites_used++;
386     }
387     }
388     memcpy(gpsdata->PRN, PRN, sizeof(PRN));
389     memcpy(gpsdata->elevation, elevation, sizeof(elevation));
390     memcpy(gpsdata->azimuth, azimuth,sizeof(azimuth));
391     memcpy(gpsdata->ss, ss, sizeof(ss));
392     memcpy(gpsdata->used, used, sizeof(used));
393     /*@ +compdef @*/
394     }
395     gpsdata->set |= SATELLITE_SET;
396     break;
397     /* Z and $ - profiling isn't supported by gpxview */
398     }
399     }
400     }
401     }
402     }
403    
404 harbaum 156 /* call one of the application provided gps callbacks */
405     static void do_app_cb(gpointer data, gpointer user_data) {
406     appdata_t *appdata = (appdata_t*)user_data;
407     gps_cb_t *cb = (gps_cb_t*)data;
408     cb->cb(appdata->gps_state, cb->data);
409     }
410    
411     /* walk though list of all application provided callbacks */
412     static gboolean gps_idle_cb(gpointer data) {
413     appdata_t *appdata = (appdata_t*)data;
414     printf("gps: idle callback, calling app callbacks\n");
415    
416     g_slist_foreach(appdata->gps_state->cb, do_app_cb, appdata);
417    
418     return FALSE;
419     }
420    
421 harbaum 1 gpointer gps_thread(gpointer data) {
422     GnomeVFSFileSize bytes_read;
423     GnomeVFSResult vfs_result;
424     char str[512];
425     appdata_t *appdata = (appdata_t*)data;
426     int cnt=1000;
427    
428     const char *msg_pos = "o\r\n"; /* pos request */
429     const char *msg_sat = "y\r\n"; /* sat request */
430    
431     appdata->gps_state->gpsdata.set = 0;
432    
433     gboolean connected = FALSE;
434    
435     while(1) {
436     if(appdata->use_gps) {
437     if(!connected) {
438 harbaum 156 printf("gps: trying to connect\n");
439 harbaum 1
440     if(gps_connect(appdata->gps_state) < 0)
441     sleep(10);
442     else
443     connected = TRUE;
444     } else {
445     const char *msg;
446     if(!cnt) msg = msg_sat;
447     else msg = msg_pos;
448    
449     if(GNOME_VFS_OK ==
450     (vfs_result = gnome_vfs_socket_write(appdata->gps_state->socket,
451     msg, strlen(msg)+1, &bytes_read, NULL))) {
452    
453     /* update every second, wait here to make sure a complete */
454     /* reply is received */
455     if(cnt <= 1) usleep(500000);
456     else sleep(1);
457    
458     if(bytes_read == (strlen(msg)+1)) {
459     vfs_result = gnome_vfs_socket_read(appdata->gps_state->socket,
460     str, sizeof(str)-1, &bytes_read, NULL);
461     if(vfs_result == GNOME_VFS_OK) {
462     str[bytes_read] = 0;
463    
464 harbaum 156 // printf("gps: msg: %s (%d)\n", str, strlen(str));
465 harbaum 1
466     g_mutex_lock(appdata->gps_state->mutex);
467    
468     if(!cnt) appdata->gps_state->gpsdata.set &= ~SATELLITE_SET;
469     else appdata->gps_state->gpsdata.set &=
470     ~(TIME_SET|TIMERR_SET|LATLON_SET|MODE_SET|STATUS_SET);
471    
472     gps_unpack(str, &appdata->gps_state->gpsdata);
473     g_mutex_unlock(appdata->gps_state->mutex);
474 harbaum 156 g_idle_add(gps_idle_cb, appdata);
475 harbaum 1 }
476     }
477     }
478     if(cnt++ >= 5) cnt = 0;
479     }
480     } else {
481     if(connected) {
482 harbaum 156 printf("gps: stopping GPS connection due to user request\n");
483 harbaum 1 gnome_vfs_inet_connection_destroy(appdata->gps_state->iconn, NULL);
484    
485     #ifdef USE_MAEMO
486     gpsbt_stop(&appdata->gps_state->context);
487     #endif
488     connected = FALSE;
489     } else
490     sleep(1);
491     }
492     }
493    
494 harbaum 156 printf("gps: thread ended???\n");
495 harbaum 1 return NULL;
496     }
497    
498     void gps_init(appdata_t *appdata) {
499 harbaum 8 appdata->gps_state = g_new0(gps_state_t, 1);
500 harbaum 1
501     /* start a new thread to listen to gpsd */
502     appdata->gps_state->mutex = g_mutex_new();
503     appdata->gps_state->thread_p =
504     g_thread_create(gps_thread, appdata, FALSE, NULL);
505     }
506    
507     void gps_release(appdata_t *appdata) {
508 harbaum 156 gps_unregister_all(appdata);
509 harbaum 1 #ifdef USE_MAEMO
510     gpsbt_stop(&appdata->gps_state->context);
511     #endif
512 harbaum 8 g_free(appdata->gps_state);
513 harbaum 1 }
514    
515     #else
516    
517     static void
518     location_changed(LocationGPSDevice *device, gps_state_t *gps_state) {
519    
520 harbaum 8 gps_state->fields = device->fix->fields;
521    
522     if(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET) {
523 harbaum 1 gps_state->latitude = device->fix->latitude;
524     gps_state->longitude = device->fix->longitude;
525 harbaum 53 gps_state->eph = device->fix->eph/100.0; // we want eph in meters
526 harbaum 8 }
527 harbaum 7
528 harbaum 8 if(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET)
529     gps_state->heading = device->fix->track;
530    
531     /* update list of sattelites */
532 harbaum 7
533 harbaum 8 /* free old list */
534     if(gps_state->sats.num) {
535     g_free(gps_state->sats.PRN);
536     g_free(gps_state->sats.used);
537     g_free(gps_state->sats.ss);
538     gps_state->sats.num = 0;
539 harbaum 1 }
540 harbaum 8
541     /* build new one */
542     if(device->satellites_in_view) {
543     gps_state->sats.PRN = g_new0(int, device->satellites_in_view);
544     gps_state->sats.used = g_new0(int, device->satellites_in_view);
545     gps_state->sats.ss = g_new0(int, device->satellites_in_view);
546    
547     int i;
548     for(i=0;i<device->satellites_in_view;i++) {
549     LocationGPSDeviceSatellite *sat =
550     g_ptr_array_index(device->satellites, i);
551    
552     gps_state->sats.PRN[i] = sat->prn;
553     gps_state->sats.used[i] = sat->in_use;
554     gps_state->sats.ss[i] = sat->signal_strength;
555     }
556    
557     gps_state->sats.num = device->satellites_in_view;
558     }
559 harbaum 1 }
560    
561     void gps_init(appdata_t *appdata) {
562     gps_state_t *gps_state = appdata->gps_state = g_new0(gps_state_t, 1);
563    
564 harbaum 156 printf("gps: init: Using liblocation\n");
565 harbaum 1
566     gps_state->device = g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
567     if(!gps_state->device) {
568 harbaum 156 printf("gps: Unable to connect to liblocation\n");
569 harbaum 1 return;
570     }
571    
572     gps_state->idd_changed =
573     g_signal_connect(gps_state->device, "changed",
574     G_CALLBACK(location_changed), gps_state);
575    
576 harbaum 11 gps_state->control = location_gpsd_control_get_default();
577    
578 harbaum 36 if(gps_state->control
579     #if MAEMO_VERSION_MAJOR < 5
580     && gps_state->control->can_control
581     #endif
582     ) {
583    
584 harbaum 156 printf("gps: Having control over GPSD and GPS is to be enabled, starting it\n");
585 harbaum 11 location_gpsd_control_start(gps_state->control);
586     }
587 harbaum 1 }
588    
589     void gps_release(appdata_t *appdata) {
590     gps_state_t *gps_state = appdata->gps_state;
591 harbaum 156 gps_unregister_all(appdata);
592 harbaum 1
593     if(!gps_state->device) return;
594 harbaum 11
595 harbaum 36 if(gps_state->control
596 harbaum 11 #if MAEMO_VERSION_MAJOR < 5
597 harbaum 36 && gps_state->control->can_control
598     #endif
599     ) {
600 harbaum 156 printf("gps: Having control over GPSD, stopping it\n");
601 harbaum 11 location_gpsd_control_stop(gps_state->control);
602     }
603 harbaum 1
604     /* Disconnect signal */
605     g_signal_handler_disconnect(gps_state->device, gps_state->idd_changed);
606    
607     g_free(appdata->gps_state);
608     appdata->gps_state = NULL;
609     }
610    
611     pos_t *gps_get_pos(appdata_t *appdata) {
612     static pos_t pos;
613    
614     if(!appdata->use_gps)
615     return NULL;
616    
617     gps_state_t *gps_state = appdata->gps_state;
618    
619 harbaum 8 if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))
620 harbaum 1 return NULL;
621    
622     pos.lat = gps_state->latitude;
623     pos.lon = gps_state->longitude;
624    
625     return &pos;
626     }
627    
628 harbaum 7 float gps_get_heading(appdata_t *appdata) {
629     gps_state_t *gps_state = appdata->gps_state;
630    
631 harbaum 8 if(!(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET))
632 harbaum 7 return NAN;
633 harbaum 1
634 harbaum 7 return gps_state->heading;
635     }
636 harbaum 1
637 harbaum 53 float gps_get_eph(appdata_t *appdata) {
638 harbaum 7 gps_state_t *gps_state = appdata->gps_state;
639    
640 harbaum 8 if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))
641 harbaum 7 return NAN;
642    
643 harbaum 53 return gps_state->eph;
644 harbaum 7 }
645    
646 harbaum 8 gps_sat_t *gps_get_sats(appdata_t *appdata) {
647     gps_sat_t *retval = NULL;
648     gps_state_t *gps_state = appdata->gps_state;
649 harbaum 1
650 harbaum 8 if(gps_state->sats.num) {
651     retval = g_new0(gps_sat_t, 1);
652     retval->num = gps_state->sats.num;
653    
654     retval->PRN = g_memdup(gps_state->sats.PRN,
655     sizeof(int)*gps_state->sats.num);
656     retval->used = g_memdup(gps_state->sats.used,
657     sizeof(int)*gps_state->sats.num);
658     retval->ss = g_memdup(gps_state->sats.ss,
659     sizeof(int)*gps_state->sats.num);
660     }
661 harbaum 1
662 harbaum 8 return retval;
663     }
664    
665    
666 harbaum 1 #endif
667 harbaum 149
668     void *gps_register_callback(appdata_t *appdata, gps_cb cb, gpointer data) {
669 harbaum 156 printf("gps: register gps callback\n");
670    
671     if(!appdata->gps_state)
672     return NULL;
673    
674     /* allocate callback info strcuture */
675     gps_cb_t *cb_info = g_new0(gps_cb_t, 1);
676     cb_info->cb = cb;
677     cb_info->data = data;
678    
679     /* and insert it into list of callbacks */
680     appdata->gps_state->cb = g_slist_append(appdata->gps_state->cb, cb_info);
681    
682     return cb_info;
683 harbaum 149 }
684    
685    
686     void gps_unregister_callback(appdata_t *appdata, void *cb) {
687 harbaum 156 printf("gps: unregister gps callback\n");
688    
689     if(!appdata->gps_state)
690     return;
691    
692     /* the item must be in the list */
693     g_assert(g_slist_find(appdata->gps_state->cb, cb));
694    
695     g_free(cb);
696     appdata->gps_state->cb = g_slist_remove(appdata->gps_state->cb, cb);
697 harbaum 149 }
698 harbaum 156
699     static void gps_unregister_all(appdata_t *appdata) {
700     printf("gps: unregister all callbacks: ");
701    
702     while(appdata->gps_state->cb) {
703     printf(".");
704     g_free(appdata->gps_state->cb->data);
705     appdata->gps_state->cb = g_slist_remove(appdata->gps_state->cb,
706     appdata->gps_state->cb->data);
707     }
708     printf("\n");
709     }