1 /* fso-gpsd - a gpsd compatibility daemon for the FSO frameworkd
3 * Copyright (C) 2008 Sascha Wessel <wessel@nefkom.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <sys/types.h>
33 #include <dbus/dbus-glib.h>
34 #include <glib-object.h>
37 #define KNOTS_TO_KPH (1.852)
38 #define KNOTS_TO_MPS (0.51444444)
40 /******************************************************************************/
42 #define NAME "fso-gpsd"
44 #define OUSAGED "org.freesmartphone.ousaged"
45 #define OGPSD "org.freesmartphone.ogpsd"
46 #define USAGE "/org/freesmartphone/Usage"
47 #define GYPSY "/org/freedesktop/Gypsy"
49 /******************************************************************************/
53 g_log(NULL, G_LOG_LEVEL_ERROR, __VA_ARGS__); \
57 #define CRITICAL(...) \
59 if (log_level & G_LOG_LEVEL_CRITICAL) { \
60 g_log(NULL, G_LOG_LEVEL_CRITICAL, __VA_ARGS__); \
64 #define WARNING(...) \
66 if (log_level & G_LOG_LEVEL_WARNING) { \
67 g_log(NULL, G_LOG_LEVEL_WARNING, __VA_ARGS__); \
71 #define MESSAGE(...) \
73 if (log_level & G_LOG_LEVEL_MESSAGE) { \
74 g_log(NULL, G_LOG_LEVEL_MESSAGE, __VA_ARGS__); \
80 if (log_level & G_LOG_LEVEL_INFO) { \
81 g_log(NULL, G_LOG_LEVEL_INFO, __VA_ARGS__); \
87 if (log_level & G_LOG_LEVEL_DEBUG) { \
88 g_log(NULL, G_LOG_LEVEL_DEBUG, __VA_ARGS__); \
92 /******************************************************************************/
94 #define POSITION_LATITUDE_IS_VALID() (position_fields & (1 << 0))
95 #define POSITION_LONGITUDE_IS_VALID() (position_fields & (1 << 1))
96 #define POSITION_ALTITUDE_IS_VALID() (position_fields & (1 << 2))
98 #define ACCURACY_PDOP_IS_VALID() (accuracy_fields & (1 << 0))
99 #define ACCURACY_HDOP_IS_VALID() (accuracy_fields & (1 << 1))
100 #define ACCURACY_VDOP_IS_VALID() (accuracy_fields & (1 << 2))
102 #define COURSE_SPEED_IS_VALID() (course_fields & (1 << 0))
103 #define COURSE_DIRECTION_IS_VALID() (course_fields & (1 << 1))
104 #define COURSE_CLIMB_IS_VALID() (course_fields & (1 << 2))
106 /******************************************************************************/
122 /******************************************************************************/
124 static int log_level
= G_LOG_LEVEL_ERROR
125 | G_LOG_LEVEL_CRITICAL
126 | G_LOG_LEVEL_WARNING
;
128 static gboolean background
= TRUE
;
129 static gboolean nowait
= FALSE
;
131 /******************************************************************************/
133 static gboolean info_queued
= FALSE
;
134 static gboolean sats_queued
= FALSE
;
135 static gboolean nmea_queued
= FALSE
;
137 /******************************************************************************/
139 static GList
*client_list
= NULL
;
141 /******************************************************************************/
143 static DBusGConnection
*connection
;
144 static DBusGProxy
*proxy_usage
;
145 static DBusGProxy
*proxy_device
;
146 static DBusGProxy
*proxy_position
;
147 static DBusGProxy
*proxy_accuracy
;
148 static DBusGProxy
*proxy_course
;
149 static DBusGProxy
*proxy_satellite
;
150 static DBusGProxy
*proxy_time
;
152 /******************************************************************************/
154 static gboolean device_connectionstatus
;
155 static int device_fixstatus
; /* 0=INVALID, 1=NONE, 2=2D, 3=3D */
157 static int position_fields
;
158 static int position_timestamp
;
159 static double position_latitude
;
160 static double position_longitude
;
161 static double position_altitude
;
163 static int accuracy_fields
;
164 static double accuracy_pdop
;
165 static double accuracy_hdop
;
166 static double accuracy_vdop
;
168 static int course_fields
;
169 static int course_timestamp
;
170 static double course_speed
;
171 static double course_direction
;
172 static double course_climb
;
174 #define SATELLITEC_MAX 32
175 static struct satellite satellite_satellitev
[SATELLITEC_MAX
];
176 static unsigned satellite_satellitec
;
178 static int time_seconds
;
180 /******************************************************************************/
182 static GString
*nmea_gga
;
183 static GString
*nmea_gsa
;
184 static GString
*nmea_gsv
[3];
185 static GString
*nmea_rmc
;
186 static GString
*nmea_gll
;
187 static GString
*nmea_vtg
;
189 /******************************************************************************/
194 if (POSITION_LATITUDE_IS_VALID() && POSITION_LONGITUDE_IS_VALID()) {
195 if (POSITION_ALTITUDE_IS_VALID()) {
196 return MIN(device_fixstatus
, 3);
198 return MIN(device_fixstatus
, 2);
201 return MIN(device_fixstatus
, 1);
206 check_period(const GTimeVal
*tv1
, const GTimeVal
*tv2
, glong sec
)
208 glong tv1_sec
= tv1
->tv_sec
+ sec
;
209 glong tv1_usec
= tv1
->tv_usec
;
210 glong tv2_sec
= tv2
->tv_sec
;
211 glong tv2_usec
= tv2
->tv_usec
;
213 if (tv1_sec
== tv2_sec
) {
214 return (tv1_usec
> tv2_usec
);
216 return (tv1_sec
> tv2_sec
);
220 /******************************************************************************/
223 shutdown_client(struct client
*client
)
225 if (client
->channel
) {
226 MESSAGE("Shutdown client");
228 g_io_channel_shutdown(client
->channel
, FALSE
, NULL
);
231 client
->channel
= NULL
;
232 client
->watcher
= FALSE
;
237 send_to_client(struct client
*client
, const char *string
, gsize len
)
242 if (!client
->channel
) {
246 status
= g_io_channel_write_chars(client
->channel
, string
,
247 len
, &bytes_written
, NULL
);
249 if ((bytes_written
!= len
) || (status
!= G_IO_STATUS_NORMAL
)) {
250 shutdown_client(client
);
254 /******************************************************************************/
257 add_nmea_checksum(GString
*nmea
)
269 checksum
^= (int) *p
;
273 g_string_append_printf(nmea
, "*%02x", checksum
);
277 add_nmea_time(GString
*nmea
)
279 if (time_seconds
<= 0) {
280 g_string_append_c(nmea
, ',');
285 seconds
= time_seconds
;
286 tm
= gmtime(&seconds
);
288 g_string_append_printf(nmea
, ",%02d%02d%02d.00",
289 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
294 add_nmea_latitude(GString
*nmea
)
296 if (!POSITION_LATITUDE_IS_VALID()) {
297 g_string_append_c(nmea
, ',');
298 g_string_append_c(nmea
, ',');
302 a
= fabs(position_latitude
);
305 g_string_append_printf(nmea
, ",%010.5f,%c",
306 (d
* 100.0) + ((a
- d
) * 60.0),
307 (position_latitude
> 0) ? 'N' : 'S');
312 add_nmea_longitude(GString
*nmea
)
314 if (!POSITION_LONGITUDE_IS_VALID()) {
315 g_string_append_c(nmea
, ',');
316 g_string_append_c(nmea
, ',');
320 a
= fabs(position_longitude
);
323 g_string_append_printf(nmea
, ",%011.5f,%c",
324 (d
* 100.0) + ((a
- d
) * 60.0),
325 (position_longitude
> 0) ? 'E' : 'W');
329 /******************************************************************************/
332 update_nmea_gga(void)
336 g_string_assign(nmea_gga
, "$GPGGA");
338 add_nmea_time(nmea_gga
);
340 add_nmea_latitude(nmea_gga
);
342 add_nmea_longitude(nmea_gga
);
344 g_string_append_printf(nmea_gga
, ",%1d", MAX(get_fixstatus() - 1, 0));
346 for (i
= 0, used
= 0; i
< satellite_satellitec
; i
++) {
347 if (satellite_satellitev
[i
].used
) {
352 g_string_append_printf(nmea_gga
, ",%02d", used
);
354 if (!ACCURACY_HDOP_IS_VALID()) {
355 g_string_append_c(nmea_gga
, ',');
357 g_string_append_printf(nmea_gga
, ",%04.2f", accuracy_hdop
);
360 if (!POSITION_ALTITUDE_IS_VALID()) {
361 g_string_append_c(nmea_gga
, ',');
362 g_string_append_c(nmea_gga
, ',');
364 g_string_append_printf(nmea_gga
, ",%03.1f,M",
368 g_string_append_c(nmea_gga
, ','); /* FIXME */
369 g_string_append_c(nmea_gga
, ',');
370 g_string_append_c(nmea_gga
, ',');
371 g_string_append_c(nmea_gga
, ',');
373 add_nmea_checksum(nmea_gga
);
377 update_nmea_gsa(void)
381 g_string_assign(nmea_gsa
, "$GPGSA");
383 g_string_append_c(nmea_gsa
, ',');
384 g_string_append_c(nmea_gsa
, 'A');
386 g_string_append_printf(nmea_gsa
, ",%1d", MAX(get_fixstatus() - 1, 0));
388 for (i
= 0; i
< 12; i
++) {
389 if (i
< satellite_satellitec
) {
390 g_string_append_printf(nmea_gsa
, ",%02d",
391 satellite_satellitev
[i
].prn
);
393 g_string_append_c(nmea_gsa
, ',');
397 if (!ACCURACY_PDOP_IS_VALID()) {
398 g_string_append_c(nmea_gsa
, ',');
400 g_string_append_printf(nmea_gsa
, ",%04.2f", accuracy_pdop
);
403 if (!ACCURACY_HDOP_IS_VALID()) {
404 g_string_append_c(nmea_gsa
, ',');
406 g_string_append_printf(nmea_gsa
, ",%04.2f", accuracy_hdop
);
409 if (!ACCURACY_VDOP_IS_VALID()) {
410 g_string_append_c(nmea_gsa
, ',');
412 g_string_append_printf(nmea_gsa
, ",%04.2f", accuracy_vdop
);
415 add_nmea_checksum(nmea_gsa
);
419 update_nmea_gsv(void)
423 unsigned sentence_count
;
425 g_string_truncate(nmea_gsv
[0], 0);
426 g_string_truncate(nmea_gsv
[1], 0);
427 g_string_truncate(nmea_gsv
[2], 0);
429 if (satellite_satellitec
== 0) {
430 g_string_assign(nmea_gsv
[0], "$GPGSV,1,1,00*79");
434 sat_count
= MIN(satellite_satellitec
, 12);
435 sentence_count
= ((sat_count
- 1) / 4) + 1;
437 for (i
= 0; i
< sat_count
; i
++) {
438 int index_div
, index_mod
;
443 if (index_mod
== 0) {
444 g_string_append_printf(nmea_gsv
[index_div
],
445 "$GPGSV,%1d,%1d,%02d",
451 g_string_append_printf(nmea_gsv
[index_div
],
452 ",%02u,%02u,%03u,%02u",
453 satellite_satellitev
[i
].prn
,
454 satellite_satellitev
[i
].elevation
,
455 satellite_satellitev
[i
].azimuth
,
456 satellite_satellitev
[i
].snr
);
459 for (i
= 0; i
< 3; i
++) {
460 if (nmea_gsv
[i
]->len
> 0) {
461 add_nmea_checksum(nmea_gsv
[i
]);
467 update_nmea_rmc(void)
469 g_string_assign(nmea_rmc
, "$GPRMC");
471 add_nmea_time(nmea_rmc
);
473 if (get_fixstatus() > 1) {
474 g_string_append_c(nmea_rmc
, ',');
475 g_string_append_c(nmea_rmc
, 'A');
477 g_string_append_c(nmea_rmc
, ',');
478 g_string_append_c(nmea_rmc
, 'V');
481 add_nmea_latitude(nmea_rmc
);
483 add_nmea_longitude(nmea_rmc
);
485 if (!COURSE_SPEED_IS_VALID()) {
486 g_string_append_c(nmea_rmc
, ',');
488 g_string_append_printf(nmea_rmc
, ",%07.3f",
492 if (!COURSE_DIRECTION_IS_VALID()) {
493 g_string_append_c(nmea_rmc
, ',');
495 g_string_append_printf(nmea_rmc
, ",%06.2f",
499 if (time_seconds
<= 0) {
500 g_string_append_c(nmea_rmc
, ',');
505 seconds
= time_seconds
;
506 tm
= gmtime(&seconds
);
508 g_string_append_printf(nmea_rmc
, ",%02d%02d%02d",
509 tm
->tm_mday
, tm
->tm_mon
+ 1, tm
->tm_year
% 100);
512 g_string_append_c(nmea_rmc
, ',');
513 g_string_append_c(nmea_rmc
, ',');
515 add_nmea_checksum(nmea_rmc
);
519 update_nmea_gll(void)
521 g_string_assign(nmea_gll
, "$GPGLL");
523 add_nmea_latitude(nmea_gll
);
525 add_nmea_longitude(nmea_gll
);
527 add_nmea_time(nmea_gll
);
529 if (get_fixstatus() > 1) {
530 g_string_append_c(nmea_gll
, ',');
531 g_string_append_c(nmea_gll
, 'A');
533 g_string_append_c(nmea_gll
, ',');
534 g_string_append_c(nmea_gll
, 'V');
537 add_nmea_checksum(nmea_gll
);
541 update_nmea_vtg(void)
543 g_string_assign(nmea_vtg
, "$GPVTG");
545 if (!COURSE_DIRECTION_IS_VALID()) {
546 g_string_append_c(nmea_vtg
, ',');
547 g_string_append_c(nmea_vtg
, ',');
549 g_string_append_printf(nmea_vtg
, ",%04.2f,T", course_direction
);
552 g_string_append_c(nmea_vtg
, ','); /* FIXME */
553 g_string_append_c(nmea_vtg
, ',');
555 if (!COURSE_SPEED_IS_VALID()) {
556 g_string_append_c(nmea_vtg
, ',');
557 g_string_append_c(nmea_vtg
, ',');
558 g_string_append_c(nmea_vtg
, ',');
559 g_string_append_c(nmea_vtg
, ',');
561 g_string_append_printf(nmea_vtg
, ",%05.3f,N,%05.3f,K",
562 course_speed
, course_speed
* KNOTS_TO_KPH
);
565 add_nmea_checksum(nmea_vtg
);
568 /******************************************************************************/
571 send_nmea_to_clients(gpointer data
)
576 for (string
= NULL
, l
= client_list
; l
; l
= l
->next
) {
577 struct client
*client
= l
->data
;
581 static GTimeVal timestamp
= { 0, 0 };
583 if (data
&& check_period(×tamp
, data
, 1)) {
587 g_get_current_time(×tamp
);
589 string
= g_string_sized_new(1024);
591 if (!nmea_gga
->len
) {
594 if (!nmea_gsa
->len
) {
597 if (!nmea_gsv
[0]->len
) {
600 if (!nmea_rmc
->len
) {
603 if (!nmea_gll
->len
) {
606 if (!nmea_vtg
->len
) {
611 DEBUG("Sending nmea: %s",
613 g_string_append_len(string
,
616 g_string_append_c(string
, '\r');
617 g_string_append_c(string
, '\n');
620 DEBUG("Sending nmea: %s",
622 g_string_append_len(string
,
625 g_string_append_c(string
, '\r');
626 g_string_append_c(string
, '\n');
628 if (nmea_gsv
[0]->len
) {
629 DEBUG("Sending nmea: %s",
631 g_string_append_len(string
,
634 g_string_append_c(string
, '\r');
635 g_string_append_c(string
, '\n');
637 if (nmea_gsv
[1]->len
) {
638 DEBUG("Sending nmea: %s",
640 g_string_append_len(string
,
643 g_string_append_c(string
, '\r');
644 g_string_append_c(string
, '\n');
646 if (nmea_gsv
[2]->len
) {
647 DEBUG("Sending nmea: %s",
649 g_string_append_len(string
,
652 g_string_append_c(string
, '\r');
653 g_string_append_c(string
, '\n');
656 DEBUG("Sending nmea: %s",
658 g_string_append_len(string
,
661 g_string_append_c(string
, '\r');
662 g_string_append_c(string
, '\n');
665 DEBUG("Sending nmea: %s",
667 g_string_append_len(string
,
670 g_string_append_c(string
, '\r');
671 g_string_append_c(string
, '\n');
674 DEBUG("Sending nmea: %s",
676 g_string_append_len(string
,
679 g_string_append_c(string
, '\r');
680 g_string_append_c(string
, '\n');
684 send_to_client(client
, string
->str
, string
->len
);
689 g_string_free(string
, TRUE
);
698 queue_send_nmea_to_clients(void)
706 g_idle_add(send_nmea_to_clients
, NULL
);
709 /******************************************************************************/
712 add_sats(GString
*string
)
716 if (satellite_satellitec
== 0) {
717 g_string_append(string
, ",Y=?");
721 g_string_append(string
, ",Y=-");
723 if (time_seconds
<= 0) {
724 g_string_append(string
, " ? ");
726 g_string_append_printf(string
, " %d.000 ", time_seconds
);
729 count
= MIN(satellite_satellitec
, 12);
731 g_string_append_printf(string
, "%d:", count
);
733 for (i
= 0; i
< count
; i
++) {
734 g_string_append_printf(string
, "%d %d %d %d %d:",
735 satellite_satellitev
[i
].prn
,
736 satellite_satellitev
[i
].elevation
,
737 satellite_satellitev
[i
].azimuth
,
738 satellite_satellitev
[i
].snr
,
739 satellite_satellitev
[i
].used
);
743 /******************************************************************************/
746 send_sats_to_clients(gpointer data
)
751 for (string
= NULL
, l
= client_list
; l
; l
= l
->next
) {
752 struct client
*client
= l
->data
;
754 if (client
->watcher
) {
756 static GTimeVal timestamp
= { 0, 0 };
758 if (data
&& check_period(×tamp
, data
, 1)) {
762 g_get_current_time(×tamp
);
764 string
= g_string_sized_new(1024);
766 g_string_append(string
, "GPSD");
770 DEBUG("Sending sats: %s", string
->str
);
772 g_string_append_c(string
, '\r');
773 g_string_append_c(string
, '\n');
776 send_to_client(client
, string
->str
, string
->len
);
781 g_string_free(string
, TRUE
);
790 queue_send_sats_to_clients(void)
798 g_idle_add(send_sats_to_clients
, NULL
);
801 /******************************************************************************/
804 add_info(GString
*string
)
806 if (!device_connectionstatus
|| get_fixstatus() <= 1) {
807 g_string_append(string
, ",O=?");
811 g_string_append(string
, ",O=-");
813 if (time_seconds
<= 0) {
814 g_string_append_c(string
, ' ');
815 g_string_append_c(string
, '?');
817 g_string_append_printf(string
, " %d.000", time_seconds
);
820 g_string_append_c(string
, ' '); /* FIXME */
821 g_string_append_c(string
, '?');
823 if (!POSITION_LATITUDE_IS_VALID()) {
824 g_string_append_c(string
, ' ');
825 g_string_append_c(string
, '?');
827 g_string_append_printf(string
, " %.6f", position_latitude
);
829 if (!POSITION_LONGITUDE_IS_VALID()) {
830 g_string_append_c(string
, ' ');
831 g_string_append_c(string
, '?');
833 g_string_append_printf(string
, " %.6f", position_longitude
);
835 if (!POSITION_ALTITUDE_IS_VALID()) {
836 g_string_append_c(string
, ' ');
837 g_string_append_c(string
, '?');
839 g_string_append_printf(string
, " %.2f", position_altitude
);
841 if (!ACCURACY_HDOP_IS_VALID()) {
842 g_string_append_c(string
, ' ');
843 g_string_append_c(string
, '?');
845 g_string_append_printf(string
, " %.2f", accuracy_hdop
);
847 if (!ACCURACY_VDOP_IS_VALID()) {
848 g_string_append_c(string
, ' ');
849 g_string_append_c(string
, '?');
851 g_string_append_printf(string
, " %.2f", accuracy_vdop
);
853 if (!COURSE_DIRECTION_IS_VALID()) {
854 g_string_append_c(string
, ' ');
855 g_string_append_c(string
, '?');
857 g_string_append_printf(string
, " %.4f", course_direction
);
859 if (!COURSE_SPEED_IS_VALID()) {
860 g_string_append_c(string
, ' ');
861 g_string_append_c(string
, '?');
863 g_string_append_printf(string
, " %.3f",
864 course_speed
* KNOTS_TO_MPS
);
866 if (!COURSE_CLIMB_IS_VALID()) {
867 g_string_append_c(string
, ' ');
868 g_string_append_c(string
, '?');
870 g_string_append_printf(string
, " %.3f", course_climb
);
873 g_string_append(string
, " ? ? ?"); /* FIXME */
875 g_string_append_printf(string
, " %d", get_fixstatus());
878 /******************************************************************************/
881 send_info_to_clients(gpointer data
)
886 for (string
= NULL
, l
= client_list
; l
; l
= l
->next
) {
887 struct client
*client
= l
->data
;
889 if (client
->watcher
) {
891 static GTimeVal timestamp
= { 0, 0 };
893 if (data
&& check_period(×tamp
, data
, 1)) {
897 g_get_current_time(×tamp
);
899 string
= g_string_sized_new(1024);
901 g_string_append(string
, "GPSD");
905 DEBUG("Sending info: %s", string
->str
);
907 g_string_append_c(string
, '\r');
908 g_string_append_c(string
, '\n');
911 send_to_client(client
, string
->str
, string
->len
);
916 g_string_free(string
, TRUE
);
925 queue_send_info_to_clients(void)
933 g_idle_add(send_info_to_clients
, NULL
);
936 /******************************************************************************/
939 timeout_handler(gpointer data
)
943 if (!client_list
&& !nowait
) {
947 g_get_current_time(&tv
);
949 send_info_to_clients(&tv
);
950 send_sats_to_clients(&tv
);
951 send_nmea_to_clients(&tv
);
953 if (!device_connectionstatus
) {
954 dbus_g_proxy_call_no_reply(proxy_usage
, "RequestResource",
955 G_TYPE_STRING
, "GPS",
963 /******************************************************************************/
966 marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE(
968 GValue
*return_value G_GNUC_UNUSED
,
969 guint n_param_values
,
970 const GValue
*param_values
,
971 gpointer invocation_hint G_GNUC_UNUSED
,
972 gpointer marshal_data
975 typedef void (*GMarshalFunc_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE
)(
984 GMarshalFunc_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE callback
;
985 GCClosure
*cc
= (GCClosure
*) closure
;
986 gpointer data1
, data2
;
988 g_return_if_fail(n_param_values
== 6);
990 if (G_CCLOSURE_SWAP_DATA(closure
)) {
991 data1
= closure
->data
;
992 data2
= g_value_peek_pointer(param_values
+ 0);
994 data1
= g_value_peek_pointer(param_values
+ 0);
995 data2
= closure
->data
;
998 callback
= (GMarshalFunc_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE
) (
999 marshal_data
? marshal_data
: cc
->callback
);
1002 g_value_get_int(param_values
+ 1),
1003 g_value_get_int(param_values
+ 2),
1004 g_value_get_double(param_values
+ 3),
1005 g_value_get_double(param_values
+ 4),
1006 g_value_get_double(param_values
+ 5),
1011 marshal_VOID__INT_DOUBLE_DOUBLE_DOUBLE(
1013 GValue
*return_value G_GNUC_UNUSED
,
1014 guint n_param_values
,
1015 const GValue
*param_values
,
1016 gpointer invocation_hint G_GNUC_UNUSED
,
1017 gpointer marshal_data
1020 typedef void (*GMarshalFunc_VOID__INT_DOUBLE_DOUBLE_DOUBLE
)(
1028 GMarshalFunc_VOID__INT_DOUBLE_DOUBLE_DOUBLE callback
;
1029 GCClosure
*cc
= (GCClosure
*) closure
;
1030 gpointer data1
, data2
;
1032 g_return_if_fail(n_param_values
== 5);
1034 if (G_CCLOSURE_SWAP_DATA(closure
)) {
1035 data1
= closure
->data
;
1036 data2
= g_value_peek_pointer(param_values
+ 0);
1038 data1
= g_value_peek_pointer(param_values
+ 0);
1039 data2
= closure
->data
;
1042 callback
= (GMarshalFunc_VOID__INT_DOUBLE_DOUBLE_DOUBLE
) (
1043 marshal_data
? marshal_data
: cc
->callback
);
1046 g_value_get_int(param_values
+ 1),
1047 g_value_get_double(param_values
+ 2),
1048 g_value_get_double(param_values
+ 3),
1049 g_value_get_double(param_values
+ 4),
1053 /******************************************************************************/
1056 connection_status_changed(
1058 gboolean connectionstatus
,
1062 device_connectionstatus
= connectionstatus
;
1064 INFO("ConnectionStatusChanged(connectionstatus=%s)",
1065 device_connectionstatus
? "TRUE" : "FALSE");
1077 device_fixstatus
= fixstatus
;
1079 switch (device_fixstatus
) {
1094 INFO("FixStatusChanged(fixstatus=%s)", str
);
1096 g_string_truncate(nmea_gga
, 0);
1097 g_string_truncate(nmea_gsa
, 0);
1098 g_string_truncate(nmea_rmc
, 0);
1099 g_string_truncate(nmea_gll
, 0);
1101 queue_send_nmea_to_clients();
1102 queue_send_info_to_clients();
1116 position_fields
= fields
;
1117 position_timestamp
= timestamp
;
1118 position_latitude
= latitude
;
1119 position_longitude
= longitude
;
1120 position_altitude
= altitude
;
1122 INFO("PositionChanged(timestamp=%d, latitude=%f, longitude=%f, altitude=%f)",
1124 POSITION_LATITUDE_IS_VALID() ? position_latitude
: NAN
,
1125 POSITION_LONGITUDE_IS_VALID() ? position_longitude
: NAN
,
1126 POSITION_ALTITUDE_IS_VALID() ? position_altitude
: NAN
);
1128 g_string_truncate(nmea_gga
, 0);
1129 g_string_truncate(nmea_rmc
, 0);
1130 g_string_truncate(nmea_gll
, 0);
1132 queue_send_nmea_to_clients();
1133 queue_send_info_to_clients();
1146 accuracy_fields
= fields
;
1147 accuracy_pdop
= pdop
;
1148 accuracy_hdop
= hdop
;
1149 accuracy_vdop
= vdop
;
1151 INFO("AccuracyChanged(pdop=%f, hdop=%f, vdop=%f)",
1152 ACCURACY_PDOP_IS_VALID() ? accuracy_pdop
: NAN
,
1153 ACCURACY_HDOP_IS_VALID() ? accuracy_hdop
: NAN
,
1154 ACCURACY_VDOP_IS_VALID() ? accuracy_vdop
: NAN
);
1156 g_string_truncate(nmea_gga
, 0);
1157 g_string_truncate(nmea_gsa
, 0);
1159 queue_send_nmea_to_clients();
1160 queue_send_info_to_clients();
1174 course_fields
= fields
;
1175 course_timestamp
= timestamp
;
1176 course_speed
= speed
;
1177 course_direction
= direction
;
1178 course_climb
= climb
;
1180 INFO("CourseChanged(timestamp=%d, speed=%f, direction=%f, climb=%f)",
1182 COURSE_SPEED_IS_VALID() ? course_speed
: NAN
,
1183 COURSE_DIRECTION_IS_VALID() ? course_direction
: NAN
,
1184 COURSE_CLIMB_IS_VALID() ? course_climb
: NAN
);
1186 g_string_truncate(nmea_rmc
, 0);
1187 g_string_truncate(nmea_vtg
, 0);
1189 queue_send_nmea_to_clients();
1190 queue_send_info_to_clients();
1196 GPtrArray
*satellites
,
1203 satellite_satellitec
= 0;
1205 satellite_satellitec
= MIN(SATELLITEC_MAX
, satellites
->len
);
1208 for (i
= 0; i
< satellite_satellitec
; i
++) {
1209 struct satellite
*sat
;
1212 sat
= satellite_satellitev
+ i
;
1213 val
= satellites
->pdata
[i
];
1215 sat
->prn
= g_value_get_uint(g_value_array_get_nth(val
, 0));
1216 sat
->used
= g_value_get_boolean(g_value_array_get_nth(val
, 1));
1217 sat
->elevation
= g_value_get_uint(g_value_array_get_nth(val
, 2));
1218 sat
->azimuth
= g_value_get_uint(g_value_array_get_nth(val
, 3));
1219 sat
->snr
= g_value_get_uint(g_value_array_get_nth(val
, 4));
1221 INFO("SatellitesChanged(index=%d, prn=%u, used=%s, elevation=%u, azimuth=%u, snr=%u)",
1224 sat
->used
? "TRUE" : "FALSE",
1230 g_string_truncate(nmea_gga
, 0);
1231 g_string_truncate(nmea_gsa
, 0);
1232 g_string_truncate(nmea_gsv
[0], 0);
1233 g_string_truncate(nmea_gsv
[1], 0);
1234 g_string_truncate(nmea_gsv
[2], 0);
1236 queue_send_nmea_to_clients();
1237 queue_send_sats_to_clients();
1247 time_seconds
= seconds
;
1249 INFO("TimeChanged(seconds=%d)", time_seconds
);
1251 g_string_truncate(nmea_gga
, 0);
1252 g_string_truncate(nmea_rmc
, 0);
1253 g_string_truncate(nmea_gll
, 0);
1255 queue_send_nmea_to_clients();
1256 queue_send_info_to_clients();
1259 /******************************************************************************/
1264 dbus_g_proxy_connect_signal(proxy_device
, "ConnectionStatusChanged",
1265 G_CALLBACK(connection_status_changed
), NULL
, NULL
);
1266 dbus_g_proxy_connect_signal(proxy_device
, "FixStatusChanged",
1267 G_CALLBACK(fix_status_changed
), NULL
, NULL
);
1268 dbus_g_proxy_connect_signal(proxy_position
, "PositionChanged",
1269 G_CALLBACK(position_changed
), NULL
, NULL
);
1270 dbus_g_proxy_connect_signal(proxy_accuracy
, "AccuracyChanged",
1271 G_CALLBACK(accuracy_changed
), NULL
, NULL
);
1272 dbus_g_proxy_connect_signal(proxy_course
, "CourseChanged",
1273 G_CALLBACK(course_changed
), NULL
, NULL
);
1274 dbus_g_proxy_connect_signal(proxy_satellite
, "SatellitesChanged",
1275 G_CALLBACK(satellites_changed
), NULL
, NULL
);
1276 dbus_g_proxy_connect_signal(proxy_time
, "TimeChanged",
1277 G_CALLBACK(time_changed
), NULL
, NULL
);
1279 dbus_g_proxy_call_no_reply(proxy_usage
, "RequestResource",
1280 G_TYPE_STRING
, "GPS",
1285 gboolean connectionstatus
= FALSE
;
1287 dbus_g_proxy_call(proxy_device
, "GetConnectionStatus", NULL
,
1289 G_TYPE_BOOLEAN
, &connectionstatus
,
1291 connection_status_changed(NULL
, connectionstatus
, NULL
);
1296 dbus_g_proxy_call(proxy_device
, "GetFixStatus", NULL
,
1298 G_TYPE_INT
, &fixstatus
,
1300 fix_status_changed(NULL
, fixstatus
, NULL
);
1303 int fields
= 0, timestamp
= 0;
1304 double latitude
= NAN
, longitude
= NAN
, altitude
= NAN
;
1306 dbus_g_proxy_call(proxy_position
, "GetPosition", NULL
,
1308 G_TYPE_INT
, &fields
,
1309 G_TYPE_INT
, ×tamp
,
1310 G_TYPE_DOUBLE
, &latitude
,
1311 G_TYPE_DOUBLE
, &longitude
,
1312 G_TYPE_DOUBLE
, &altitude
,
1314 position_changed(NULL
, fields
, timestamp
, latitude
, longitude
,
1319 double pdop
= NAN
, hdop
= NAN
, vdop
= NAN
;
1321 dbus_g_proxy_call(proxy_accuracy
, "GetAccuracy", NULL
,
1323 G_TYPE_INT
, &fields
,
1324 G_TYPE_DOUBLE
, &pdop
,
1325 G_TYPE_DOUBLE
, &hdop
,
1326 G_TYPE_DOUBLE
, &vdop
,
1328 accuracy_changed(NULL
, fields
, pdop
, hdop
, vdop
, NULL
);
1331 int fields
= 0, timestamp
= 0;
1332 double speed
= NAN
, direction
= NAN
, climb
= NAN
;
1334 dbus_g_proxy_call(proxy_course
, "GetCourse", NULL
,
1336 G_TYPE_INT
, &fields
,
1337 G_TYPE_INT
, ×tamp
,
1338 G_TYPE_DOUBLE
, &speed
,
1339 G_TYPE_DOUBLE
, &direction
,
1340 G_TYPE_DOUBLE
, &climb
,
1342 course_changed(NULL
, fields
, timestamp
, speed
, direction
,
1346 GPtrArray
*satellites
= NULL
;
1348 dbus_g_proxy_call(proxy_satellite
, "GetSatellites", NULL
,
1350 dbus_g_type_get_collection("GPtrArray",
1351 dbus_g_type_get_struct("GValueArray",
1360 satellites_changed(NULL
, satellites
, NULL
);
1365 dbus_g_proxy_call(proxy_time
, "GetTime", NULL
,
1367 G_TYPE_INT
, &seconds
,
1369 time_changed(NULL
, seconds
, NULL
);
1372 g_timeout_add(1000, timeout_handler
, NULL
);
1378 dbus_g_proxy_call_no_reply(proxy_usage
, "ReleaseResource",
1379 G_TYPE_STRING
, "GPS",
1383 dbus_g_proxy_disconnect_signal(proxy_device
, "ConnectionStatusChanged",
1384 G_CALLBACK(connection_status_changed
), NULL
);
1385 dbus_g_proxy_disconnect_signal(proxy_device
, "FixStatusChanged",
1386 G_CALLBACK(fix_status_changed
), NULL
);
1387 dbus_g_proxy_disconnect_signal(proxy_position
, "PositionChanged",
1388 G_CALLBACK(position_changed
), NULL
);
1389 dbus_g_proxy_disconnect_signal(proxy_accuracy
, "AccuracyChanged",
1390 G_CALLBACK(accuracy_changed
), NULL
);
1391 dbus_g_proxy_disconnect_signal(proxy_course
, "CourseChanged",
1392 G_CALLBACK(course_changed
), NULL
);
1393 dbus_g_proxy_disconnect_signal(proxy_satellite
, "SatellitesChanged",
1394 G_CALLBACK(satellites_changed
), NULL
);
1395 dbus_g_proxy_disconnect_signal(proxy_time
, "TimeChanged",
1396 G_CALLBACK(time_changed
), NULL
);
1399 /******************************************************************************/
1404 GError
*error
= NULL
;
1406 connection
= dbus_g_bus_get(DBUS_BUS_SYSTEM
, &error
);
1409 ERROR("Failed to open connection to system bus: %s\n",
1413 dbus_g_object_register_marshaller(
1414 marshal_VOID__INT_DOUBLE_DOUBLE_DOUBLE
,
1421 dbus_g_object_register_marshaller(
1422 marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE
,
1431 proxy_usage
= dbus_g_proxy_new_for_name(connection
, OUSAGED
, USAGE
,
1432 "org.freesmartphone.Usage");
1433 proxy_device
= dbus_g_proxy_new_for_name(connection
, OGPSD
, GYPSY
,
1434 "org.freedesktop.Gypsy.Device");
1435 proxy_position
= dbus_g_proxy_new_for_name(connection
, OGPSD
, GYPSY
,
1436 "org.freedesktop.Gypsy.Position");
1437 proxy_accuracy
= dbus_g_proxy_new_for_name(connection
, OGPSD
, GYPSY
,
1438 "org.freedesktop.Gypsy.Accuracy");
1439 proxy_course
= dbus_g_proxy_new_for_name(connection
, OGPSD
, GYPSY
,
1440 "org.freedesktop.Gypsy.Course");
1441 proxy_satellite
= dbus_g_proxy_new_for_name(connection
, OGPSD
, GYPSY
,
1442 "org.freedesktop.Gypsy.Satellite");
1443 proxy_time
= dbus_g_proxy_new_for_name(connection
, OGPSD
, GYPSY
,
1444 "org.freedesktop.Gypsy.Time");
1446 dbus_g_proxy_add_signal(proxy_device
, "ConnectionStatusChanged",
1449 dbus_g_proxy_add_signal(proxy_device
, "FixStatusChanged",
1452 dbus_g_proxy_add_signal(proxy_position
, "PositionChanged",
1459 dbus_g_proxy_add_signal(proxy_accuracy
, "AccuracyChanged",
1465 dbus_g_proxy_add_signal(proxy_course
, "CourseChanged",
1472 dbus_g_proxy_add_signal(proxy_satellite
, "SatellitesChanged",
1473 dbus_g_type_get_collection("GPtrArray",
1474 dbus_g_type_get_struct("GValueArray",
1482 dbus_g_proxy_add_signal(proxy_time
, "TimeChanged",
1487 /******************************************************************************/
1490 read_from_client(GIOChannel
*source
, GIOCondition condition
, gpointer data
)
1492 struct client
*client
;
1494 gsize len
= sizeof(buf
);
1501 if (condition
!= G_IO_IN
) {
1502 shutdown_client(client
);
1505 if (!client
->channel
) {
1506 MESSAGE("Removing client");
1508 client_list
= g_list_remove(client_list
, client
);
1510 g_io_channel_unref(source
);
1512 if (!client_list
&& !nowait
) {
1519 status
= g_io_channel_read_chars(source
, buf
, len
- 2, &len
, NULL
);
1521 if ((status
!= G_IO_STATUS_NORMAL
) || (len
< 1)) {
1522 shutdown_client(client
);
1526 if (buf
[len
- 1] != '\n') {
1533 reply
= g_string_sized_new(128);
1534 g_string_assign(reply
, "GPSD");
1539 switch (toupper(*p
++)) {
1541 if (!POSITION_ALTITUDE_IS_VALID()) {
1542 g_string_append(reply
, ",A=?");
1544 g_string_append_printf(reply
, ",A=%.3f",
1549 g_string_append(reply
, ",B=?");
1552 g_string_append(reply
, ",C=1.00"); /* FIXME */
1555 if (time_seconds
<= 0) {
1556 g_string_append(reply
, ",D=?");
1561 seconds
= time_seconds
;
1562 tm
= gmtime(&seconds
);
1564 g_string_append_printf(reply
,
1565 ",D=%04d-%02d-%02dT%02d:%02d:%02d.00Z",
1566 tm
->tm_year
+ 1900, tm
->tm_mon
+ 1,
1567 tm
->tm_mday
, tm
->tm_hour
, tm
->tm_min
,
1572 g_string_append(reply
, ",E=");
1574 if (!ACCURACY_PDOP_IS_VALID()) {
1575 g_string_append(reply
, "?");
1577 g_string_append_printf(reply
, "%.2f",
1580 if (!ACCURACY_HDOP_IS_VALID()) {
1581 g_string_append(reply
, " ?");
1583 g_string_append_printf(reply
, " %.2f",
1586 if (!ACCURACY_VDOP_IS_VALID()) {
1587 g_string_append(reply
, " ?");
1589 g_string_append_printf(reply
, " %.2f",
1595 while (isprint(*p
) && !isspace(*p
)) {
1599 g_string_append(reply
, ",F=gypsy");
1603 p
+= strcspn(p
, ",\r\n");
1605 g_string_append(reply
, ",G=GPS");
1608 g_string_append(reply
, ",I=gypsy");
1614 if (*p
== '1' || *p
== '+') {
1616 g_string_append(reply
, ",J=1");
1618 if (*p
== '0' || *p
== '-') {
1621 g_string_append(reply
, ",J=0");
1625 g_string_append(reply
, ",K=1 gypsy");
1628 g_string_append(reply
, ",L=3 " VERSION
1629 " abcdefgijklmnopqrstuvwxyz");
1632 g_string_append_printf(reply
, ",M=%d",
1636 g_string_append(reply
, ",N=0");
1642 if (!POSITION_LATITUDE_IS_VALID()
1643 || !POSITION_LONGITUDE_IS_VALID()) {
1644 g_string_append(reply
, ",P=?");
1646 g_string_append_printf(reply
, ",P=%.6f %.6f",
1647 position_latitude
, position_longitude
);
1651 if (!ACCURACY_PDOP_IS_VALID()
1652 && !ACCURACY_HDOP_IS_VALID()
1653 && !ACCURACY_VDOP_IS_VALID()) {
1654 g_string_append(reply
, ",Q=?");
1658 for (i
= 0, used
= 0; i
< satellite_satellitec
; i
++) {
1659 if (satellite_satellitev
[i
].used
) {
1664 g_string_append_printf(reply
,
1665 ",Q=%d %.2f %.2f %.2f %.2f %.2f", used
,
1666 ACCURACY_PDOP_IS_VALID() ? accuracy_pdop
: 0.0,
1667 ACCURACY_HDOP_IS_VALID() ? accuracy_hdop
: 0.0,
1668 ACCURACY_VDOP_IS_VALID() ? accuracy_vdop
: 0.0,
1676 if (*p
== '2' || *p
== '1' || *p
== '+') {
1679 } else if (*p
== '0' || *p
== '-') {
1680 client
->raw
= FALSE
;
1683 client
->raw
= !client
->raw
;
1686 queue_send_nmea_to_clients();
1688 g_string_append_printf(reply
, ",R=%1d", client
->raw
);
1691 g_string_append_printf(reply
, ",S=%d",
1692 MAX(get_fixstatus() - 1, 0));
1695 if (!COURSE_DIRECTION_IS_VALID()) {
1696 g_string_append(reply
, ",T=?");
1698 g_string_append_printf(reply
, ",T=%.4f",
1703 if (!COURSE_CLIMB_IS_VALID()) {
1704 g_string_append(reply
, ",U=?");
1706 g_string_append_printf(reply
, ",U=%.3f",
1711 if (!COURSE_SPEED_IS_VALID()) {
1712 g_string_append(reply
, ",V=?");
1714 g_string_append_printf(reply
, ",V=%.3f",
1715 course_speed
* KNOTS_TO_MPS
);
1722 if (*p
== '1' || *p
== '+') {
1723 client
->watcher
= TRUE
;
1725 } else if (*p
== '0' || *p
== '-') {
1726 client
->watcher
= FALSE
;
1729 client
->watcher
= !client
->watcher
;
1731 if (client
->watcher
) {
1732 queue_send_sats_to_clients();
1733 queue_send_info_to_clients();
1735 g_string_append_printf(reply
, ",W=%1d", client
->watcher
);
1738 if (time_seconds
<= 0) {
1739 g_string_append(reply
, ",X=?");
1741 g_string_append_printf(reply
, ",X=%d.000000",
1749 g_string_append(reply
, ",Z=?"); /* FIXME */
1752 g_string_append(reply
, ",$=?"); /* FIXME */
1763 g_string_append(reply
, "\r\n");
1764 send_to_client(client
, reply
->str
, reply
->len
);
1765 g_string_free(reply
, TRUE
);
1770 accept_new_client(GIOChannel
*source
, GIOCondition condition
, gpointer data
)
1772 struct sockaddr_in addr
;
1773 socklen_t len
= sizeof(addr
);
1774 struct client
*client
;
1777 MESSAGE("New client request");
1779 fd
= accept(g_io_channel_unix_get_fd(source
),
1780 (struct sockaddr
*) &addr
, &len
);
1783 ERROR("Cannot accept new connection: %s", strerror(errno
));
1786 client
= g_new0(struct client
, 1);
1789 ERROR("Cannot allocate memory");
1792 if (!client_list
&& !nowait
) {
1796 client_list
= g_list_prepend(client_list
, client
);
1798 client
->channel
= g_io_channel_unix_new(fd
);
1800 g_io_channel_set_flags(client
->channel
, G_IO_FLAG_NONBLOCK
, NULL
);
1801 g_io_channel_set_encoding(client
->channel
, NULL
, NULL
);
1802 g_io_channel_set_buffered(client
->channel
, FALSE
);
1804 g_io_add_watch(client
->channel
,
1805 G_IO_IN
| G_IO_PRI
| G_IO_ERR
| G_IO_HUP
| G_IO_NVAL
,
1806 read_from_client
, client
);
1812 init_service(const char *service
)
1814 struct servent
*pse
;
1815 struct sockaddr_in addr
;
1816 GIOChannel
*channel
;
1819 memset(&addr
, 0, sizeof(addr
));
1821 addr
.sin_family
= AF_INET
;
1822 addr
.sin_addr
.s_addr
= INADDR_ANY
;
1825 service
= getservbyname("gpsd", "tcp") ? "gpsd" : PORT
;
1828 pse
= getservbyname(service
, "tcp");
1831 addr
.sin_port
= pse
->s_port
;
1833 addr
.sin_port
= htons(atoi(service
));
1836 if (!addr
.sin_port
) {
1837 ERROR("Cannot get service entry: %s", service
);
1840 fd
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
1843 ERROR("Cannot create socket: %s", strerror(errno
));
1846 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, (char *) & one
, sizeof(one
));
1848 if (bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
1849 ERROR("Cannot bind to port %s: %s", service
, strerror(errno
));
1852 if (listen(fd
, 4) < 0) {
1853 ERROR("Cannot listen on port %s: %s",
1854 service
, strerror(errno
));
1857 channel
= g_io_channel_unix_new(fd
);
1859 g_io_channel_set_encoding(channel
, NULL
, NULL
);
1860 g_io_channel_set_buffered(channel
, FALSE
);
1862 g_io_add_watch(channel
, G_IO_IN
| G_IO_PRI
| G_IO_HUP
| G_IO_ERR
,
1863 accept_new_client
, NULL
);
1866 /******************************************************************************/
1869 printerr_handler(const char *message
)
1872 syslog(LOG_USER
| LOG_INFO
, "%s", message
);
1874 fputs(message
, stderr
);
1881 GLogLevelFlags level
,
1882 const char *message
,
1886 const char *level_string
;
1888 switch (level
& G_LOG_LEVEL_MASK
) {
1889 case G_LOG_LEVEL_ERROR
:
1890 level_string
= "ERROR: ";
1892 case G_LOG_LEVEL_CRITICAL
:
1893 level_string
= "CRITICAL: ";
1895 case G_LOG_LEVEL_WARNING
:
1896 level_string
= "WARNING: ";
1898 case G_LOG_LEVEL_MESSAGE
:
1899 level_string
= "MESSAGE: ";
1901 case G_LOG_LEVEL_INFO
:
1902 level_string
= "INFO: ";
1904 case G_LOG_LEVEL_DEBUG
:
1905 level_string
= "DEBUG: ";
1914 syslog(LOG_USER
| LOG_INFO
, "%s: %s%s", domain
,
1915 level_string
, message
);
1917 syslog(LOG_USER
| LOG_INFO
, "%s%s",
1918 level_string
, message
);
1921 struct timeval tv
= { 0, 0 };
1923 gettimeofday(&tv
, NULL
);
1926 fprintf(stderr
, "%li.%06li %s: %s%s\n",
1927 (long) tv
.tv_sec
, (long) tv
.tv_usec
,
1928 domain
, level_string
, message
);
1930 fprintf(stderr
, "%li.%06li %s%s\n",
1931 (long) tv
.tv_sec
, (long) tv
.tv_usec
,
1932 level_string
, message
);
1937 /******************************************************************************/
1942 printf("usage: "NAME
" [-n] [-N] [-D n] [-P pidfile] [-S port] [-h]\n\
1944 -n = don't wait for client connects to poll GPS\n\
1945 -N = don't go into background\n\
1946 -P pidfile = set file to record process ID\n\
1947 -D integer (default 0) = set debug level\n\
1948 -S integer (default "PORT
") = set port for daemon\n\
1949 -h = help message\n\
1950 -V = emit version and exit.\n");
1953 /******************************************************************************/
1956 main(int argc
, char **argv
)
1958 GMainLoop
*loop
= NULL
;
1959 char *service
= NULL
;
1960 char *pid_file
= NULL
;
1962 g_set_prgname(NAME
);
1963 g_set_printerr_handler(printerr_handler
);
1964 g_log_set_default_handler(log_handler
, NULL
);
1970 option
= getopt(argc
, argv
, "F:D:S:bhNnP:VR:");
1980 WARNING("Not implemented: -%c", option
);
1983 switch (atoi(optarg
)) {
1985 log_level
= G_LOG_LEVEL_ERROR
1986 | G_LOG_LEVEL_CRITICAL
1987 | G_LOG_LEVEL_WARNING
;
1990 log_level
= G_LOG_LEVEL_ERROR
1991 | G_LOG_LEVEL_CRITICAL
1992 | G_LOG_LEVEL_WARNING
1993 | G_LOG_LEVEL_MESSAGE
;
1996 log_level
= G_LOG_LEVEL_ERROR
1997 | G_LOG_LEVEL_CRITICAL
1998 | G_LOG_LEVEL_WARNING
1999 | G_LOG_LEVEL_MESSAGE
2003 log_level
= G_LOG_LEVEL_ERROR
2004 | G_LOG_LEVEL_CRITICAL
2005 | G_LOG_LEVEL_WARNING
2006 | G_LOG_LEVEL_MESSAGE
2008 | G_LOG_LEVEL_DEBUG
;
2025 printf(NAME
" "VERSION
"\n");
2041 openlog(NAME
, LOG_PID
, LOG_USER
);
2046 ERROR("fork() failed");
2047 } else if (pid
> 0) {
2052 ERROR("setsid() failed");
2057 fd
= open("/dev/null", O_RDWR
, 0);
2060 ERROR("Cannot open /dev/null");
2063 dup2(fd
, STDIN_FILENO
);
2064 dup2(fd
, STDOUT_FILENO
);
2065 dup2(fd
, STDERR_FILENO
);
2073 fp
= fopen(pid_file
, "w");
2076 ERROR("Cannot create PID file: %s", pid_file
);
2079 fprintf(fp
, "%u\n", (unsigned) getpid());
2085 loop
= g_main_loop_new(NULL
, FALSE
);
2087 nmea_gga
= g_string_new(NULL
);
2088 nmea_gsa
= g_string_new(NULL
);
2089 nmea_gsv
[0] = g_string_new(NULL
);
2090 nmea_gsv
[1] = g_string_new(NULL
);
2091 nmea_gsv
[2] = g_string_new(NULL
);
2092 nmea_rmc
= g_string_new(NULL
);
2093 nmea_gll
= g_string_new(NULL
);
2094 nmea_vtg
= g_string_new(NULL
);
2096 init_service(service
);
2104 g_main_loop_run(loop
);