Upgrade ofono to 1.2
[profile/ivi/ofono.git] / src / dbus.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program 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 this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <glib.h>
27 #include <gdbus.h>
28
29 #include "ofono.h"
30
31 #define OFONO_ERROR_INTERFACE "org.ofono.Error"
32
33 static DBusConnection *g_connection;
34
35 struct error_mapping_entry {
36         int error;
37         DBusMessage *(*ofono_error_func)(DBusMessage *);
38 };
39
40 struct error_mapping_entry cme_errors_mapping[] = {
41         { 3,    __ofono_error_not_allowed },
42         { 4,    __ofono_error_not_supported },
43         { 16,   __ofono_error_incorrect_password },
44         { 30,   __ofono_error_not_registered },
45         { 31,   __ofono_error_timed_out },
46         { 32,   __ofono_error_access_denied },
47         { 50,   __ofono_error_invalid_args },
48 };
49
50 static void append_variant(DBusMessageIter *iter,
51                                 int type, void *value)
52 {
53         char sig[2];
54         DBusMessageIter valueiter;
55
56         sig[0] = type;
57         sig[1] = 0;
58
59         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
60                                                 sig, &valueiter);
61
62         dbus_message_iter_append_basic(&valueiter, type, value);
63
64         dbus_message_iter_close_container(iter, &valueiter);
65 }
66
67 void ofono_dbus_dict_append(DBusMessageIter *dict,
68                         const char *key, int type, void *value)
69 {
70         DBusMessageIter keyiter;
71
72         if (type == DBUS_TYPE_STRING) {
73                 const char *str = *((const char **) value);
74                 if (str == NULL)
75                         return;
76         }
77
78         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
79                                                         NULL, &keyiter);
80
81         dbus_message_iter_append_basic(&keyiter, DBUS_TYPE_STRING, &key);
82
83         append_variant(&keyiter, type, value);
84
85         dbus_message_iter_close_container(dict, &keyiter);
86 }
87
88 static void append_array_variant(DBusMessageIter *iter, int type, void *val)
89 {
90         DBusMessageIter variant, array;
91         char typesig[2];
92         char arraysig[3];
93         const char **str_array = *(const char ***) val;
94         int i;
95
96         arraysig[0] = DBUS_TYPE_ARRAY;
97         arraysig[1] = typesig[0] = type;
98         arraysig[2] = typesig[1] = '\0';
99
100         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
101                                                 arraysig, &variant);
102
103         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
104                                                 typesig, &array);
105
106         for (i = 0; str_array[i]; i++)
107                 dbus_message_iter_append_basic(&array, type,
108                                                 &(str_array[i]));
109
110         dbus_message_iter_close_container(&variant, &array);
111
112         dbus_message_iter_close_container(iter, &variant);
113 }
114
115 void ofono_dbus_dict_append_array(DBusMessageIter *dict, const char *key,
116                                 int type, void *val)
117 {
118         DBusMessageIter entry;
119
120         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
121                                                 NULL, &entry);
122
123         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
124
125         append_array_variant(&entry, type, val);
126
127         dbus_message_iter_close_container(dict, &entry);
128 }
129
130 static void append_dict_variant(DBusMessageIter *iter, int type, void *val)
131 {
132         DBusMessageIter variant, array, entry;
133         char typesig[5];
134         char arraysig[6];
135         const void **val_array = *(const void ***) val;
136         int i;
137
138         arraysig[0] = DBUS_TYPE_ARRAY;
139         arraysig[1] = typesig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR;
140         arraysig[2] = typesig[1] = DBUS_TYPE_STRING;
141         arraysig[3] = typesig[2] = type;
142         arraysig[4] = typesig[3] = DBUS_DICT_ENTRY_END_CHAR;
143         arraysig[5] = typesig[4] = '\0';
144
145         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
146                                                 arraysig, &variant);
147
148         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
149                                                 typesig, &array);
150
151         for (i = 0; val_array[i]; i += 2) {
152                 dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY,
153                                                         NULL, &entry);
154
155                 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
156                                                 &(val_array[i + 0]));
157
158                 /*
159                  * D-Bus expects a char** or uint8* depending on the type
160                  * given. Since we are dealing with an array through a void**
161                  * (and thus val_array[i] is a pointer) we need to
162                  * differentiate DBUS_TYPE_STRING from the others. The other
163                  * option would be the user to pass the exact type to this
164                  * function, instead of a pointer to it. However in this case
165                  * a cast from type to void* would be needed, which is not
166                  * good.
167                  */
168                 if (type == DBUS_TYPE_STRING) {
169                         dbus_message_iter_append_basic(&entry, type,
170                                                         &(val_array[i + 1]));
171                 } else {
172                         dbus_message_iter_append_basic(&entry, type,
173                                                         val_array[i + 1]);
174                 }
175
176                 dbus_message_iter_close_container(&array, &entry);
177         }
178
179         dbus_message_iter_close_container(&variant, &array);
180
181         dbus_message_iter_close_container(iter, &variant);
182 }
183
184 void ofono_dbus_dict_append_dict(DBusMessageIter *dict, const char *key,
185                                 int type, void *val)
186 {
187         DBusMessageIter entry;
188
189         dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
190                                                 NULL, &entry);
191
192         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
193
194         append_dict_variant(&entry, type, val);
195
196         dbus_message_iter_close_container(dict, &entry);
197 }
198
199 int ofono_dbus_signal_property_changed(DBusConnection *conn,
200                                         const char *path,
201                                         const char *interface,
202                                         const char *name,
203                                         int type, void *value)
204 {
205         DBusMessage *signal;
206         DBusMessageIter iter;
207
208         signal = dbus_message_new_signal(path, interface, "PropertyChanged");
209         if (signal == NULL) {
210                 ofono_error("Unable to allocate new %s.PropertyChanged signal",
211                                 interface);
212                 return -1;
213         }
214
215         dbus_message_iter_init_append(signal, &iter);
216
217         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
218
219         append_variant(&iter, type, value);
220
221         return g_dbus_send_message(conn, signal);
222 }
223
224 int ofono_dbus_signal_array_property_changed(DBusConnection *conn,
225                                                 const char *path,
226                                                 const char *interface,
227                                                 const char *name,
228                                                 int type, void *value)
229
230 {
231         DBusMessage *signal;
232         DBusMessageIter iter;
233
234         signal = dbus_message_new_signal(path, interface, "PropertyChanged");
235         if (signal == NULL) {
236                 ofono_error("Unable to allocate new %s.PropertyChanged signal",
237                                 interface);
238                 return -1;
239         }
240
241         dbus_message_iter_init_append(signal, &iter);
242
243         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
244
245         append_array_variant(&iter, type, value);
246
247         return g_dbus_send_message(conn, signal);
248 }
249
250 int ofono_dbus_signal_dict_property_changed(DBusConnection *conn,
251                                                 const char *path,
252                                                 const char *interface,
253                                                 const char *name,
254                                                 int type, void *value)
255
256 {
257         DBusMessage *signal;
258         DBusMessageIter iter;
259
260         signal = dbus_message_new_signal(path, interface, "PropertyChanged");
261         if (signal == NULL) {
262                 ofono_error("Unable to allocate new %s.PropertyChanged signal",
263                                 interface);
264                 return -1;
265         }
266
267         dbus_message_iter_init_append(signal, &iter);
268
269         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
270
271         append_dict_variant(&iter, type, value);
272
273         return g_dbus_send_message(conn, signal);
274 }
275
276 DBusMessage *__ofono_error_invalid_args(DBusMessage *msg)
277 {
278         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE
279                                         ".InvalidArguments",
280                                         "Invalid arguments in method call");
281 }
282
283 DBusMessage *__ofono_error_invalid_format(DBusMessage *msg)
284 {
285         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE
286                                         ".InvalidFormat",
287                                         "Argument format is not recognized");
288 }
289
290 DBusMessage *__ofono_error_not_implemented(DBusMessage *msg)
291 {
292         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE
293                                         ".NotImplemented",
294                                         "Implementation not provided");
295 }
296
297 DBusMessage *__ofono_error_failed(DBusMessage *msg)
298 {
299         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".Failed",
300                                         "Operation failed");
301 }
302
303 DBusMessage *__ofono_error_busy(DBusMessage *msg)
304 {
305         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".InProgress",
306                                         "Operation already in progress");
307 }
308
309 DBusMessage *__ofono_error_not_found(DBusMessage *msg)
310 {
311         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".NotFound",
312                         "Object is not found or not valid for this operation");
313 }
314
315 DBusMessage *__ofono_error_not_active(DBusMessage *msg)
316 {
317         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".NotActive",
318                         "Operation is not active or in progress");
319 }
320
321 DBusMessage *__ofono_error_not_supported(DBusMessage *msg)
322 {
323         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE
324                                         ".NotSupported",
325                                         "Operation is not supported by the"
326                                         " network / modem");
327 }
328
329 DBusMessage *__ofono_error_not_available(DBusMessage *msg)
330 {
331         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE
332                                         ".NotAvailable",
333                                         "Operation currently not available");
334 }
335
336 DBusMessage *__ofono_error_timed_out(DBusMessage *msg)
337 {
338         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".Timedout",
339                         "Operation failure due to timeout");
340 }
341
342 DBusMessage *__ofono_error_sim_not_ready(DBusMessage *msg)
343 {
344         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".SimNotReady",
345                         "SIM is not ready or not inserted");
346 }
347
348 DBusMessage *__ofono_error_in_use(DBusMessage *msg)
349 {
350         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".InUse",
351                         "The resource is currently in use");
352 }
353
354 DBusMessage *__ofono_error_not_attached(DBusMessage *msg)
355 {
356         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".NotAttached",
357                         "GPRS is not attached");
358 }
359
360 DBusMessage *__ofono_error_attach_in_progress(DBusMessage *msg)
361 {
362         return g_dbus_create_error(msg,
363                                 OFONO_ERROR_INTERFACE ".AttachInProgress",
364                                 "GPRS Attach is in progress");
365 }
366
367 DBusMessage *__ofono_error_not_registered(DBusMessage *msg)
368 {
369         return g_dbus_create_error(msg,
370                                 OFONO_ERROR_INTERFACE ".NotRegistered",
371                                 "Modem is not registered to the network");
372 }
373
374 DBusMessage *__ofono_error_canceled(DBusMessage *msg)
375 {
376         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".Canceled",
377                                         "Operation has been canceled");
378 }
379
380 DBusMessage *__ofono_error_access_denied(DBusMessage *msg)
381 {
382         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".AccessDenied",
383                                         "Operation not permitted");
384 }
385
386 DBusMessage *__ofono_error_emergency_active(DBusMessage *msg)
387 {
388         return g_dbus_create_error(msg,
389                                 OFONO_ERROR_INTERFACE ".EmergencyActive",
390                                 "Emergency mode active");
391 }
392
393 DBusMessage *__ofono_error_incorrect_password(DBusMessage *msg)
394 {
395         return g_dbus_create_error(msg,
396                                 OFONO_ERROR_INTERFACE ".IncorrectPassword",
397                                 "Password is incorrect");
398 }
399
400 DBusMessage *__ofono_error_not_allowed(DBusMessage *msg)
401 {
402         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".NotAllowed",
403                                         "Operation is not allowed");
404 }
405
406 DBusMessage *__ofono_error_not_recognized(DBusMessage *msg)
407 {
408         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE ".NotRecognized",
409                                         "String not recognized as USSD/SS");
410 }
411
412 DBusMessage *__ofono_error_network_terminated(DBusMessage *msg)
413 {
414         return g_dbus_create_error(msg, OFONO_ERROR_INTERFACE
415                                         ".Terminated",
416                                         "Operation was terminated by the"
417                                         " network");
418 }
419
420 DBusMessage *__ofono_error_from_error(const struct ofono_error *error,
421                                                 DBusMessage *msg)
422 {
423         struct error_mapping_entry *e;
424         int maxentries;
425         int i;
426
427         switch (error->type) {
428         case OFONO_ERROR_TYPE_CME:
429                 e = cme_errors_mapping;
430                 maxentries = sizeof(cme_errors_mapping) /
431                                         sizeof(struct error_mapping_entry);
432                 for (i = 0; i < maxentries; i++)
433                         if (e[i].error == error->error)
434                                 return e[i].ofono_error_func(msg);
435                 break;
436         case OFONO_ERROR_TYPE_CMS:
437                 return __ofono_error_failed(msg);
438         case OFONO_ERROR_TYPE_CEER:
439                 return __ofono_error_failed(msg);
440         default:
441                 return __ofono_error_failed(msg);
442         }
443
444         return __ofono_error_failed(msg);
445 }
446
447 void __ofono_dbus_pending_reply(DBusMessage **msg, DBusMessage *reply)
448 {
449         DBusConnection *conn = ofono_dbus_get_connection();
450
451         g_dbus_send_message(conn, reply);
452
453         dbus_message_unref(*msg);
454         *msg = NULL;
455 }
456
457 gboolean __ofono_dbus_valid_object_path(const char *path)
458 {
459         unsigned int i;
460         char c = '\0';
461
462         if (path == NULL)
463                 return FALSE;
464
465         if (path[0] == '\0')
466                 return FALSE;
467
468         if (path[0] && !path[1] && path[0] == '/')
469                 return TRUE;
470
471         if (path[0] != '/')
472                 return FALSE;
473
474         for (i = 0; path[i]; i++) {
475                 if (path[i] == '/' && c == '/')
476                         return FALSE;
477
478                 c = path[i];
479
480                 if (path[i] >= 'a' && path[i] <= 'z')
481                         continue;
482
483                 if (path[i] >= 'A' && path[i] <= 'Z')
484                         continue;
485
486                 if (path[i] >= '0' && path[i] <= '9')
487                         continue;
488
489                 if (path[i] == '_' || path[i] == '/')
490                         continue;
491
492                 return FALSE;
493         }
494
495         if (path[i-1] == '/')
496                 return FALSE;
497
498         return TRUE;
499 }
500
501 DBusConnection *ofono_dbus_get_connection(void)
502 {
503         return g_connection;
504 }
505
506 static void dbus_gsm_set_connection(DBusConnection *conn)
507 {
508         if (conn && g_connection != NULL)
509                 ofono_error("Setting a connection when it is not NULL");
510
511         g_connection = conn;
512 }
513
514 int __ofono_dbus_init(DBusConnection *conn)
515 {
516         dbus_gsm_set_connection(conn);
517
518         return 0;
519 }
520
521 void __ofono_dbus_cleanup(void)
522 {
523         DBusConnection *conn = ofono_dbus_get_connection();
524
525         if (conn == NULL || !dbus_connection_get_is_connected(conn))
526                 return;
527
528         dbus_gsm_set_connection(NULL);
529 }