Contents of /trunk/src/gps.c

Parent Directory Parent Directory | Revision Log Revision Log


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