]> err.no Git - mapper/blob - src/gps-bluetooth-hildon.c
Start to rewrite the GPS system to support location information from multiple sources.
[mapper] / src / gps-bluetooth-hildon.c
1 /*
2  * This file is part of mapper
3  *
4  * Copyright (C) 2007 Kaj-Michael Lang
5  * Copyright (C) 2006-2007 John Costigan.
6  *
7  * POI and GPS-Info code originally written by Cezary Jackiewicz.
8  *
9  * Default map data provided by http://www.openstreetmap.org/
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include <config.h>
27
28 #include <fcntl.h>
29
30 /* Let this header handle all ifdefs */
31 #include "hildon-mapper.h"
32
33 #include "mapper.h"
34 #include "bt-maemo-marshal.h"
35 #include "bt.h"
36 #include "gps.h"
37 #include "settings.h"
38 #include "ui-common.h"
39
40 #include "gps-conn.h"
41
42 static guint errors;
43 static gint fd;
44
45 void 
46 rcvr_connect_fd(gchar *fdpath)
47 {
48 /* If file descriptor creation failed, try again later. */
49 if (-1 == (fd = open(fdpath, O_RDONLY))) {
50         rcvr_disconnect();
51         rcvr_connect_later();
52 } else {
53         /* Reset GPS read buffer */
54         _gps_read_buf_curr = _gps_read_buf;
55         *_gps_read_buf_curr = '\0';
56
57         /* Create channel and add watches. */
58         _channel = g_io_channel_unix_new(fd);
59         g_io_channel_set_flags(_channel, G_IO_FLAG_NONBLOCK, NULL);
60         _error_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE, G_IO_ERR | G_IO_HUP, channel_cb_error, NULL, NULL);
61         _connect_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE, G_IO_OUT, channel_cb_connect, NULL, NULL);
62 }
63 g_free(fdpath);
64 }
65
66 void 
67 rcvr_connect_response(DBusGProxy * proxy, DBusGProxyCall * call_id)
68 {
69 GError *error = NULL;
70 gchar *fdpath = NULL;
71
72 if (_conn_state == RCVR_DOWN && _rcvr_mac) {
73         if (!dbus_g_proxy_end_call(_rfcomm_req_proxy, call_id, &error, G_TYPE_STRING, &fdpath, G_TYPE_INVALID)) {
74                 if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
75                         /* If we're already connected, it's not an error, unless
76                          * they don't give us the file descriptor path, in which
77                          * case we re-connect.*/
78                         if (!strcmp(BTCOND_ERROR_CONNECTED, dbus_g_error_get_name(error)) || !fdpath) {
79                                 GtkWidget *confirm;
80                                 printf("Caught remote method exception %s: %s", dbus_g_error_get_name(error), error->message);
81                                 rcvr_disconnect();
82
83                                 /* Ask user to re-connect. */
84                                 confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), _("Failed to connect to GPS receiver. Retry?"));
85
86                                 if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
87                                         rcvr_connect_later();   /* Try again later. */
88                                 else {
89                                         gps_conn_set_state(RCVR_OFF);
90                                         _enable_gps=FALSE;
91                                         set_action_activate("gps_enable", !_enable_gps);
92                                 }
93
94                                 gtk_widget_destroy(confirm);
95                                 return;
96                         }
97                 } else {
98                         /* Unknown error. */
99                         g_printerr("Error: %s\n", error->message);
100                         rcvr_disconnect();
101                         rcvr_connect_later();   /* Try again later. */
102                         return;
103                 }
104         }
105         rcvr_connect_fd(fdpath);
106 }
107 /* else { Looks like the middle of a disconnect.  Do nothing. } */
108 }
109
110 /**
111  * Connect to the receiver.
112  * This method assumes that fd is -1 and _channel is NULL.  If unsure, call
113  * rcvr_disconnect() first.
114  * Since this is an idle function, this function returns whether or not it
115  * should be called again, which is always FALSE.
116  */
117 gboolean 
118 rcvr_connect_now()
119 {
120 if (_conn_state == RCVR_DOWN && _rcvr_mac) {
121 #ifndef DEBUG_GPS
122         if (*_rcvr_mac != '/') {
123                 if (_rfcomm_req_proxy) {
124                         gint mybool = TRUE;
125                         dbus_g_proxy_begin_call(_rfcomm_req_proxy,
126                                                 BTCOND_RFCOMM_CONNECT_REQ,
127                                                 (DBusGProxyCallNotify)
128                                                 rcvr_connect_response,
129                                                 NULL, NULL,
130                                                 G_TYPE_STRING,
131                                                 _rcvr_mac,
132                                                 G_TYPE_STRING, "SPP",
133                                                 G_TYPE_BOOLEAN, &mybool,
134                                                 G_TYPE_INVALID);
135                 }
136         } else {
137                 rcvr_connect_fd(g_strdup(_rcvr_mac));
138         }
139 #else
140         /* We're in DEBUG mode, so instead of connecting, skip to FIXED. */
141         printf("FIXED!\n");
142         gps_conn_set_state(RCVR_FIXED);
143 #endif
144 }
145
146 _clater_sid = 0;
147 return FALSE;
148 }
149
150 /**
151  * Bluetooth device scanning functions below
152  */
153 static void
154 scan_cb_dev_found(DBusGProxy *sig_proxy, const gchar *bda, const gchar *name, gpointer *class, guchar rssi, gint coff, ScanInfo *scan_info)
155 {
156 GtkTreeIter iter;
157 gtk_list_store_append(scan_info->store, &iter);
158 gtk_list_store_set(scan_info->store, &iter, 0, g_strdup(bda), 1, g_strdup(name), -1);
159 }
160
161 static void 
162 scan_cb_search_complete(DBusGProxy * sig_proxy, ScanInfo * scan_info)
163 {
164 gtk_widget_destroy(scan_info->banner);
165 dbus_g_proxy_disconnect_signal(sig_proxy, BTSEARCH_DEV_FOUND_SIG, G_CALLBACK(scan_cb_dev_found), scan_info);
166 dbus_g_proxy_disconnect_signal(sig_proxy, BTSEARCH_SEARCH_COMPLETE_SIG, G_CALLBACK(scan_cb_search_complete), scan_info);
167 }
168
169 gint 
170 scan_start_search(ScanInfo * scan_info)
171 {
172 GError *error = NULL;
173
174 if (NULL == (scan_info->req_proxy = dbus_g_proxy_new_for_name(dbus_conn, BTSEARCH_SERVICE, BTSEARCH_REQ_PATH, BTSEARCH_REQ_INTERFACE))) {
175         g_printerr("Failed to create D-Bus request proxy for btsearch.");
176         return 2;
177 }
178
179 if (NULL == (scan_info->sig_proxy = dbus_g_proxy_new_for_name(dbus_conn, BTSEARCH_SERVICE, BTSEARCH_SIG_PATH, BTSEARCH_SIG_INTERFACE))) {
180         g_printerr("Failed to create D-Bus signal proxy for btsearch.");
181         return 2;
182 }
183
184 dbus_g_object_register_marshaller(_bt_maemo_VOID__STRING_STRING_POINTER_UCHAR_UINT, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UCHAR, G_TYPE_UINT, G_TYPE_INVALID);
185
186 dbus_g_proxy_add_signal(scan_info->sig_proxy, BTSEARCH_DEV_FOUND_SIG, G_TYPE_STRING, G_TYPE_STRING, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UCHAR, G_TYPE_UINT, G_TYPE_INVALID);
187 dbus_g_proxy_connect_signal(scan_info->sig_proxy, BTSEARCH_DEV_FOUND_SIG, G_CALLBACK(scan_cb_dev_found), scan_info, NULL);
188
189 dbus_g_proxy_add_signal(scan_info->sig_proxy, BTSEARCH_SEARCH_COMPLETE_SIG, G_TYPE_INVALID);
190 dbus_g_proxy_connect_signal(scan_info->sig_proxy, BTSEARCH_SEARCH_COMPLETE_SIG, G_CALLBACK(scan_cb_search_complete), scan_info, NULL);
191
192 error = NULL;
193 if (!dbus_g_proxy_call(scan_info->req_proxy, BTSEARCH_START_SEARCH_REQ, &error, G_TYPE_INVALID, G_TYPE_INVALID)) {
194         if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) {
195                 g_printerr("Caught remote method exception %s: %s", dbus_g_error_get_name(error), error->message);
196         } else {
197                 g_printerr("Error: %s\n", error->message);
198         }
199         return 3;
200 }
201
202 return 0;
203 }
204