callscreen: volume, mute, speaker and contacts.
[profile/ivi/lemolo.git] / dialer / ofono.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include <Elementary.h>
5
6 #include "ofono.h"
7 #include "log.h"
8
9 typedef struct _OFono_Modem OFono_Modem;
10 typedef struct _OFono_Bus_Object OFono_Bus_Object;
11
12 static const char bus_name[] = "org.ofono";
13
14 static E_DBus_Connection *bus_conn = NULL;
15 static char *bus_id = NULL;
16 static Eina_Hash *modems = NULL;
17 static OFono_Modem *modem_selected = NULL;
18 static const char *modem_path_wanted = NULL;
19 static unsigned int modem_api_mask = (OFONO_API_SIM |
20                                         OFONO_API_VOICE |
21                                         OFONO_API_MSG |
22                                         OFONO_API_STK |
23                                         OFONO_API_CALL_FW);
24 static E_DBus_Signal_Handler *sig_modem_added = NULL;
25 static E_DBus_Signal_Handler *sig_modem_removed = NULL;
26 static E_DBus_Signal_Handler *sig_modem_prop_changed = NULL;
27 static DBusPendingCall *pc_get_modems = NULL;
28
29 static void (*connected_cb)(void *) = NULL;
30 static const void *connected_cb_data = NULL;
31
32 static void (*disconnected_cb)(void *) = NULL;
33 static const void *disconnected_cb_data = NULL;
34
35 static void (*changed_cb)(void *) = NULL;
36 static const void *changed_cb_data = NULL;
37
38 static void (*call_added_cb)(void *, OFono_Call *) = NULL;
39 static const void *call_added_cb_data = NULL;
40
41 static void (*call_removed_cb)(void *, OFono_Call *) = NULL;
42 static const void *call_removed_cb_data = NULL;
43
44 static void (*call_changed_cb)(void *, OFono_Call *) = NULL;
45 static const void *call_changed_cb_data = NULL;
46
47 static void (*call_disconnected_cb)(void *, OFono_Call *, const char *) = NULL;
48 static const void *call_disconnected_cb_data = NULL;
49
50 static void _ofono_call_volume_properties_get(OFono_Modem *m);
51
52 #define OFONO_SERVICE                   "org.ofono"
53
54 #define OFONO_PREFIX                    OFONO_SERVICE "."
55 #define OFONO_MODEM_IFACE               "Modem"
56 #define OFONO_MANAGER_IFACE             "Manager"
57 #define OFONO_SIM_IFACE                 "SimManager"
58 #define OFONO_NETREG_IFACE              "NetworkRegistration"
59 #define OFONO_VOICE_IFACE               "VoiceCallManager"
60 #define OFONO_MSG_IFACE                 "MessageManager"
61 #define OFONO_MSG_WAITING_IFACE         "MessageWaiting"
62 #define OFONO_SMART_MSG_IFACE           "SmartMessaging"
63 #define OFONO_STK_IFACE                 "SimToolkit"
64
65 #define OFONO_CALL_FW_IFACE             "CallForwarding"
66 #define OFONO_CALL_VOL_IFACE            "CallVolume"
67 #define OFONO_CALL_METER_IFACE          "CallMeter"
68 #define OFONO_CALL_SET_IFACE            "CallSettings"
69 #define OFONO_CALL_BAR_IFACE            "CallBarring"
70 #define OFONO_SUPPL_SERV_IFACE          "SupplementaryServices"
71 #define OFONO_TXT_TEL_IFACE             "TextTelephony"
72 #define OFONO_CELL_BROAD_IFACE          "CellBroadcast"
73 #define OFONO_CONNMAN_IFACE             "ConnectionManager"
74 #define OFONO_PUSH_NOTIF_IFACE          "PushNotification"
75 #define OFONO_PHONEBOOK_IFACE           "Phonebook"
76 #define OFONO_ASN_IFACE                 "AssistedSatelliteNavigation"
77
78 static const struct API_Interface_Map {
79         unsigned int bit;
80         const char *name;
81         size_t namelen;
82 } api_iface_map[] = {
83 #define MAP(bit, name) {bit, name, sizeof(name) - 1}
84         MAP(OFONO_API_SIM, OFONO_SIM_IFACE),
85         MAP(OFONO_API_NETREG, OFONO_NETREG_IFACE),
86         MAP(OFONO_API_VOICE, OFONO_VOICE_IFACE),
87         MAP(OFONO_API_MSG, OFONO_MSG_IFACE),
88         MAP(OFONO_API_MSG_WAITING, OFONO_MSG_WAITING_IFACE),
89         MAP(OFONO_API_SMART_MSG, OFONO_SMART_MSG_IFACE),
90         MAP(OFONO_API_STK, OFONO_STK_IFACE),
91         MAP(OFONO_API_CALL_FW, OFONO_CALL_FW_IFACE),
92         MAP(OFONO_API_CALL_VOL, OFONO_CALL_VOL_IFACE),
93         MAP(OFONO_API_CALL_METER, OFONO_CALL_METER_IFACE),
94         MAP(OFONO_API_CALL_SET, OFONO_CALL_SET_IFACE),
95         MAP(OFONO_API_CALL_BAR, OFONO_CALL_BAR_IFACE),
96         MAP(OFONO_API_SUPPL_SERV, OFONO_SUPPL_SERV_IFACE),
97         MAP(OFONO_API_TXT_TEL, OFONO_TXT_TEL_IFACE),
98         MAP(OFONO_API_CELL_BROAD, OFONO_CELL_BROAD_IFACE),
99         MAP(OFONO_API_CONNMAN, OFONO_CONNMAN_IFACE),
100         MAP(OFONO_API_PUSH_NOTIF, OFONO_PUSH_NOTIF_IFACE),
101         MAP(OFONO_API_PHONEBOOK, OFONO_PHONEBOOK_IFACE),
102         MAP(OFONO_API_ASN, OFONO_ASN_IFACE),
103 #undef MAP
104         {0, NULL, 0}
105 };
106
107 static Eina_Bool _dbus_bool_get(DBusMessageIter *itr)
108 {
109         dbus_bool_t val;
110         dbus_message_iter_get_basic(itr, &val);
111         return val;
112 }
113
114 static const struct Error_Map {
115         OFono_Error id;
116         const char *name;
117         size_t namelen;
118 } error_map[] = {
119 #define MAP(id, name) {id, name, sizeof(name) - 1}
120         MAP(OFONO_ERROR_FAILED, "Failed"),
121         MAP(OFONO_ERROR_DOES_NOT_EXIST, "DoesNotExist"),
122         MAP(OFONO_ERROR_IN_PROGRESS, "InProgress"),
123         MAP(OFONO_ERROR_IN_USE, "InUse"),
124         MAP(OFONO_ERROR_INVALID_ARGS, "InvalidArguments"),
125         MAP(OFONO_ERROR_INVALID_FORMAT, "InvalidFormat"),
126         MAP(OFONO_ERROR_ACCESS_DENIED, "AccessDenied"),
127         MAP(OFONO_ERROR_ATTACH_IN_PROGRESS, "AttachInProgress"),
128         MAP(OFONO_ERROR_INCORRECT_PASSWORD, "IncorrectPassword"),
129         MAP(OFONO_ERROR_NOT_ACTIVE, "NotActive"),
130         MAP(OFONO_ERROR_NOT_ALLOWED, "NotAllowed"),
131         MAP(OFONO_ERROR_NOT_ATTACHED, "NotAttached"),
132         MAP(OFONO_ERROR_NOT_AVAILABLE, "NotAvailable"),
133         MAP(OFONO_ERROR_NOT_FOUND, "NotFound"),
134         MAP(OFONO_ERROR_NOT_IMPLEMENTED, "NotImplemented"),
135         MAP(OFONO_ERROR_NOT_RECOGNIZED, "NotRecognized"),
136         MAP(OFONO_ERROR_NOT_REGISTERED, "NotRegistered"),
137         MAP(OFONO_ERROR_NOT_SUPPORTED, "NotSupported"),
138         MAP(OFONO_ERROR_SIM_NOT_READY, "SimNotReady"),
139         MAP(OFONO_ERROR_STK, "SimToolkit"),
140         MAP(OFONO_ERROR_TIMEDOUT, "Timedout"),
141 #undef MAP
142         {0, NULL, 0}
143 };
144
145 static OFono_Error _ofono_error_parse(const char *name)
146 {
147         size_t namelen, prefixlen = sizeof(OFONO_PREFIX) - 1;
148         const struct Error_Map *itr;
149
150         /* whenever interfaces are not there due modem being offline */
151         if (strcmp(name, "org.freedesktop.DBus.Error.UnknownMethod") == 0)
152                 return OFONO_ERROR_OFFLINE;
153
154         if (strncmp(name, OFONO_PREFIX, prefixlen) != 0)
155                 return OFONO_ERROR_FAILED;
156
157         name += prefixlen;
158         namelen = strlen(name);
159         for (itr = error_map; itr->name != NULL; itr++)
160                 if ((itr->namelen == namelen) &&
161                         (memcmp(name, itr->name, namelen) == 0))
162                         return itr->id;
163
164         return OFONO_ERROR_FAILED;
165 }
166
167 typedef struct _OFono_Simple_Cb_Context
168 {
169         OFono_Simple_Cb cb;
170         const void *data;
171 } OFono_Simple_Cb_Context;
172
173 static void _ofono_simple_reply(void *data, DBusMessage *msg __UNUSED__,
174                                 DBusError *err)
175 {
176         OFono_Simple_Cb_Context *ctx = data;
177         OFono_Error e = OFONO_ERROR_NONE;
178
179         if (dbus_error_is_set(err)) {
180                 DBG("%s: %s", err->name, err->message);
181                 e = _ofono_error_parse(err->name);
182         }
183
184         if (ctx)
185                 ctx->cb((void *)ctx->data, e);
186 }
187
188 typedef struct _OFono_String_Cb_Context
189 {
190         OFono_String_Cb cb;
191         const void *data;
192         const char *name;
193         char *(*convert)(DBusMessage *msg);
194 } OFono_String_Cb_Context;
195
196 static void _ofono_string_reply(void *data, DBusMessage *msg, DBusError *err)
197 {
198         OFono_String_Cb_Context *ctx = data;
199         OFono_Error e = OFONO_ERROR_NONE;
200         char *str = NULL;
201
202         if (dbus_error_is_set(err)) {
203                 DBG("%s: %s", err->name, err->message);
204                 e = _ofono_error_parse(err->name);
205         } else {
206                 str = ctx->convert(msg);
207                 if (!str)
208                         e = OFONO_ERROR_NOT_SUPPORTED;
209         }
210
211         if (ctx->cb)
212                 ctx->cb((void *)ctx->data, e, str);
213         else
214                 DBG("%s %s", ctx->name, str);
215
216         free(str);
217 }
218
219 struct _OFono_Pending
220 {
221         EINA_INLIST;
222         DBusPendingCall *pending;
223         E_DBus_Method_Return_Cb cb;
224         void *data;
225         void *owner;
226 };
227
228 struct _OFono_Bus_Object
229 {
230         const char *path;
231         Eina_Inlist *dbus_pending; /* of OFono_Pending */
232         Eina_List *dbus_signals; /* of E_DBus_Signal_Handler */
233 };
234
235 static void _bus_object_free(OFono_Bus_Object *o)
236 {
237         E_DBus_Signal_Handler *sh;
238
239         eina_stringshare_del(o->path);
240
241         while (o->dbus_pending) {
242                 ofono_pending_cancel(
243                         EINA_INLIST_CONTAINER_GET(o->dbus_pending,
244                                                         OFono_Pending));
245         }
246
247         EINA_LIST_FREE(o->dbus_signals, sh)
248                 e_dbus_signal_handler_del(bus_conn, sh);
249
250         free(o);
251 }
252
253 static void _bus_object_message_send_reply(void *data, DBusMessage *reply,
254                                                 DBusError *err)
255 {
256         OFono_Pending *p = data;
257         OFono_Bus_Object *o = p->owner;
258
259         if (p->cb)
260                 p->cb(p->data, reply, err);
261
262         o->dbus_pending = eina_inlist_remove(o->dbus_pending,
263                                                 EINA_INLIST_GET(p));
264         free(p);
265 }
266
267 static OFono_Pending *_bus_object_message_send(OFono_Bus_Object *o,
268                                                 DBusMessage *msg,
269                                                 E_DBus_Method_Return_Cb cb,
270                                                 void *data)
271 {
272         OFono_Pending *p;
273         EINA_SAFETY_ON_NULL_GOTO(o, error);
274         EINA_SAFETY_ON_NULL_GOTO(msg, error);
275
276         p = calloc(1, sizeof(OFono_Pending));
277         EINA_SAFETY_ON_NULL_GOTO(p, error);
278
279         p->owner = o;
280         p->cb = cb;
281         p->data = data;
282
283         p->pending = e_dbus_message_send(
284                 bus_conn, msg, _bus_object_message_send_reply, -1, p);
285         EINA_SAFETY_ON_NULL_GOTO(p->pending, error_send);
286
287         o->dbus_pending = eina_inlist_append(o->dbus_pending,
288                                                 EINA_INLIST_GET(p));
289         dbus_message_unref(msg);
290         return p;
291
292 error_send:
293         free(p);
294 error:
295         if (cb) {
296                 DBusError err;
297                 dbus_error_init(&err);
298                 dbus_set_error(&err, "Failed", "call setup failed.");
299                 cb(data, NULL, &err);
300         }
301         dbus_message_unref(msg);
302         return NULL;
303 }
304
305 void ofono_pending_cancel(OFono_Pending *p)
306 {
307         OFono_Bus_Object *o;
308
309         EINA_SAFETY_ON_NULL_RETURN(p);
310
311         o = p->owner;
312         o->dbus_pending = eina_inlist_remove(o->dbus_pending,
313                                                 EINA_INLIST_GET(p));
314
315         if (p->cb) {
316                 DBusError err;
317
318                 dbus_error_init(&err);
319                 dbus_set_error(&err, "Canceled",
320                                 "Pending method call was canceled.");
321                 p->cb(p->data, NULL, &err);
322         }
323         dbus_pending_call_cancel(p->pending);
324         free(p);
325 }
326
327 static void _bus_object_signal_listen(OFono_Bus_Object *o, const char *iface,
328                                         const char *name, E_DBus_Signal_Cb cb,
329                                         void *data)
330 {
331         E_DBus_Signal_Handler *sh = e_dbus_signal_handler_add(
332                 bus_conn, bus_id, o->path, iface, name, cb, data);
333         EINA_SAFETY_ON_NULL_RETURN(sh);
334
335         o->dbus_signals = eina_list_append(o->dbus_signals, sh);
336 }
337
338 struct _OFono_Call
339 {
340         OFono_Bus_Object base;
341         const char *line_id;
342         const char *incoming_line;
343         const char *name;
344         OFono_Call_State state;
345         Eina_Bool multiparty : 1;
346         Eina_Bool emergency : 1;
347 };
348
349 struct _OFono_Modem
350 {
351         OFono_Bus_Object base;
352         const char *name;
353         const char *serial;
354         Eina_Hash *calls;
355         unsigned int interfaces;
356         unsigned char strength;
357         unsigned char data_strength;
358         unsigned char speaker_volume;
359         unsigned char microphone_volume;
360         Eina_Bool ignored : 1;
361         Eina_Bool powered : 1;
362         Eina_Bool online : 1;
363         Eina_Bool roaming : 1;
364         Eina_Bool muted : 1;
365 };
366
367 static OFono_Call *_call_new(const char *path)
368 {
369         OFono_Call *c = calloc(1, sizeof(OFono_Call));
370         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
371
372         c->base.path = eina_stringshare_add(path);
373         EINA_SAFETY_ON_NULL_GOTO(c->base.path, error_path);
374
375         return c;
376
377 error_path:
378         free(c);
379         return NULL;
380 }
381
382 static void _call_free(OFono_Call *c)
383 {
384         DBG("c=%p %s", c, c->base.path);
385
386         if (call_removed_cb)
387                 call_removed_cb((void *)call_removed_cb_data, c);
388
389         eina_stringshare_del(c->line_id);
390         eina_stringshare_del(c->incoming_line);
391         eina_stringshare_del(c->name);
392
393         _bus_object_free(&c->base);
394 }
395
396 static OFono_Call_State _call_state_parse(const char *str)
397 {
398         if (strcmp(str, "active") == 0)
399                 return OFONO_CALL_STATE_ACTIVE;
400         else if (strcmp(str, "held") == 0)
401                 return OFONO_CALL_STATE_HELD;
402         else if (strcmp(str, "dialing") == 0)
403                 return OFONO_CALL_STATE_DIALING;
404         else if (strcmp(str, "alerting") == 0)
405                 return OFONO_CALL_STATE_ALERTING;
406         else if (strcmp(str, "incoming") == 0)
407                 return OFONO_CALL_STATE_INCOMING;
408         else if (strcmp(str, "waiting") == 0)
409                 return OFONO_CALL_STATE_WAITING;
410         else if (strcmp(str, "disconnected") == 0)
411                 return OFONO_CALL_STATE_DISCONNECTED;
412
413         ERR("unknown call state: %s", str);
414         return OFONO_CALL_STATE_DISCONNECTED;
415 }
416
417 static void _call_property_update(OFono_Call *c, const char *key,
418                                         DBusMessageIter *value)
419 {
420         if (strcmp(key, "LineIdentification") == 0) {
421                 const char *str;
422                 dbus_message_iter_get_basic(value, &str);
423                 DBG("%s LineIdentification %s", c->base.path, str);
424                 eina_stringshare_replace(&c->line_id, str);
425         } else if (strcmp(key, "IncomingLine") == 0) {
426                 const char *str;
427                 dbus_message_iter_get_basic(value, &str);
428                 DBG("%s IncomingLine %s", c->base.path, str);
429                 eina_stringshare_replace(&c->incoming_line, str);
430         } else if (strcmp(key, "State") == 0) {
431                 const char *str;
432                 OFono_Call_State state;
433                 dbus_message_iter_get_basic(value, &str);
434                 state = _call_state_parse(str);
435                 DBG("%s State %s (%d)", c->base.path, str, state);
436                 c->state = state;
437         } else if (strcmp(key, "Name") == 0) {
438                 const char *str;
439                 dbus_message_iter_get_basic(value, &str);
440                 DBG("%s Name %s", c->base.path, str);
441                 eina_stringshare_replace(&c->name, str);
442         } else if (strcmp(key, "Multiparty") == 0) {
443                 dbus_bool_t v;
444                 dbus_message_iter_get_basic(value, &v);
445                 DBG("%s Multiparty %d", c->base.path, v);
446                 c->multiparty = v;
447         } else if (strcmp(key, "Emergency") == 0) {
448                 dbus_bool_t v;
449                 dbus_message_iter_get_basic(value, &v);
450                 DBG("%s Emergency %d", c->base.path, v);
451                 c->emergency = v;
452         } else
453                 DBG("%s %s (unused property)", c->base.path, key);
454 }
455
456 static void _call_property_changed(void *data, DBusMessage *msg)
457 {
458         OFono_Call *c = data;
459         DBusMessageIter iter, value;
460         const char *key;
461
462         if (!msg || !dbus_message_iter_init(msg, &iter)) {
463                 ERR("Could not handle message %p", msg);
464                 return;
465         }
466
467         DBG("path=%s", c->base.path);
468
469         dbus_message_iter_get_basic(&iter, &key);
470         dbus_message_iter_next(&iter);
471         dbus_message_iter_recurse(&iter, &value);
472         _call_property_update(c, key, &value);
473
474         if (call_changed_cb)
475                 call_changed_cb((void *)call_changed_cb_data, c);
476 }
477
478 static void _call_disconnect_reason(void *data, DBusMessage *msg)
479 {
480         OFono_Call *c = data;
481         DBusError err;
482         const char *reason;
483
484         if (!msg) {
485                 ERR("No message");
486                 return;
487         }
488
489         DBG("path=%s", c->base.path);
490
491         dbus_error_init(&err);
492         if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &reason,
493                                         DBUS_TYPE_INVALID)) {
494                 ERR("Could not get DisconnectReason arguments: %s: %s",
495                         err.name, err.message);
496                 dbus_error_free(&err);
497                 return;
498         }
499
500         if (call_disconnected_cb)
501                 call_disconnected_cb((void *)call_disconnected_cb_data, c,
502                         reason);
503 }
504
505 static void _call_add(OFono_Modem *m, const char *path, DBusMessageIter *prop)
506 {
507         OFono_Call *c;
508
509         DBG("path=%s", path);
510
511         c = eina_hash_find(m->calls, path);
512         if (c) {
513                 DBG("Call already exists %p (%s)", c, path);
514                 goto update_properties;
515         }
516
517         c = _call_new(path);
518         EINA_SAFETY_ON_NULL_RETURN(c);
519         eina_hash_add(m->calls, c->base.path, c);
520
521         _bus_object_signal_listen(&c->base,
522                                         OFONO_PREFIX "VoiceCall",
523                                         "DisconnectReason",
524                                         _call_disconnect_reason, c);
525         _bus_object_signal_listen(&c->base,
526                                         OFONO_PREFIX "VoiceCall",
527                                         "PropertyChanged",
528                                         _call_property_changed, c);
529
530         if (call_added_cb)
531                 call_added_cb((void *)call_added_cb_data, c);
532
533 update_properties:
534         if (!prop)
535                 return;
536         for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
537                         dbus_message_iter_next(prop)) {
538                 DBusMessageIter entry, value;
539                 const char *key;
540
541                 dbus_message_iter_recurse(prop, &entry);
542                 dbus_message_iter_get_basic(&entry, &key);
543
544                 dbus_message_iter_next(&entry);
545                 dbus_message_iter_recurse(&entry, &value);
546
547                 _call_property_update(c, key, &value);
548         }
549
550         if (call_changed_cb)
551                 call_changed_cb((void *)call_changed_cb_data, c);
552 }
553
554 static void _call_remove(OFono_Modem *m, const char *path)
555 {
556         DBG("path=%s", path);
557         eina_hash_del_by_key(m->calls, path);
558 }
559
560 static void _call_added(void *data, DBusMessage *msg)
561 {
562         OFono_Modem *m = data;
563         DBusMessageIter iter, properties;
564         const char *path;
565
566         if (!msg || !dbus_message_iter_init(msg, &iter)) {
567                 ERR("Could not handle message %p", msg);
568                 return;
569         }
570
571         dbus_message_iter_get_basic(&iter, &path);
572
573         dbus_message_iter_next(&iter);
574         dbus_message_iter_recurse(&iter, &properties);
575
576         _call_add(m, path, &properties);
577 }
578
579 static void _call_removed(void *data, DBusMessage *msg)
580 {
581         OFono_Modem *m = data;
582         DBusError err;
583         const char *path;
584
585         if (!msg) {
586                 ERR("Could not handle message %p", msg);
587                 return;
588         }
589
590         dbus_error_init(&err);
591         if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
592                                         &path, NULL)) {
593                 ERR("Could not get CallRemoved arguments: %s: %s",
594                         err.name, err.message);
595                 dbus_error_free(&err);
596                 return;
597         }
598
599         _call_remove(m, path);
600 }
601
602 static OFono_Modem *_modem_selected_get(void)
603 {
604         OFono_Modem *found_path = NULL, *found_api = NULL, *m;
605         unsigned int online = 0, powered = 0;
606         Eina_Iterator *itr;
607
608         if (modem_selected)
609                 return modem_selected;
610
611         itr = eina_hash_iterator_data_new(modems);
612         EINA_ITERATOR_FOREACH(itr, m) {
613                 if (m->ignored)
614                         continue;
615
616                 if (m->online)
617                         online++;
618                 if (m->powered)
619                         powered++;
620
621                 if ((modem_path_wanted) && (!found_path)) {
622                         DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
623                         if (m->base.path == modem_path_wanted) {
624                                 found_path = m;
625                                 break;
626                         }
627                 }
628
629                 if (!found_api) {
630                         DBG("m=%#x, mask=%#x", m->interfaces, modem_api_mask);
631                         if ((m->interfaces & modem_api_mask) == modem_api_mask)
632                                 found_api = m;
633                 }
634         }
635         eina_iterator_free(itr);
636
637         INF("found_path=%s, found_api=%s, wanted_path=%s, api_mask=%#x",
638                 found_path ? found_path->base.path : "",
639                 found_api ? found_api->base.path: "",
640                 modem_path_wanted ? modem_path_wanted : "",
641                 modem_api_mask);
642
643         if (!powered)
644                 ERR("No modems powered! Run connman or test/enable-modem");
645         if (!online)
646                 WRN("No modems online! Run connman or test/online-modem");
647
648         modem_selected = found_path ? found_path : found_api;
649         return modem_selected;
650 }
651
652 static OFono_Pending *_ofono_multiparty(const char *method,
653                                         E_DBus_Method_Return_Cb dbus_cb,
654                                         OFono_Simple_Cb cb, const void *data)
655 {
656
657         OFono_Pending *p;
658         DBusMessage *msg;
659         OFono_Simple_Cb_Context *ctx = NULL;
660         OFono_Modem *m = _modem_selected_get();
661
662         EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
663
664         if (cb) {
665                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
666                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
667                 ctx->cb = cb;
668                 ctx->data = data;
669         }
670
671         msg = dbus_message_new_method_call(
672                                 bus_id, m->base.path,
673                                 OFONO_PREFIX OFONO_VOICE_IFACE,
674                                 method);
675
676         if (!msg)
677                 goto error_no_message;
678
679         if (!dbus_message_append_args(msg, DBUS_TYPE_INVALID))
680                 goto error_message_append;
681
682         INF("Calling - %s - multiparty method.", method);
683         p = _bus_object_message_send(&m->base, msg, dbus_cb, ctx);
684
685         return p;
686
687 error_message_append:
688         dbus_message_unref(msg);
689 error_no_message:
690         if (cb)
691                 cb((void *)data, OFONO_ERROR_FAILED);
692         free(ctx);
693         return NULL;
694 }
695
696 static OFono_Pending *_ofono_multiparty_hangup(OFono_Simple_Cb cb,
697                                                 const void *data)
698 {
699         return _ofono_multiparty("HangupMultiparty",_ofono_simple_reply, cb,
700                                         data);
701 }
702
703 OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb,
704                                         const void *data)
705 {
706         OFono_Simple_Cb_Context *ctx = NULL;
707         OFono_Pending *p;
708         DBusMessage *msg;
709
710         /* It looks like we are in a conference */
711         if (c->multiparty)
712                 return _ofono_multiparty_hangup(cb, data);
713
714         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
715
716         if (cb) {
717                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
718                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
719                 ctx->cb = cb;
720                 ctx->data = data;
721         }
722
723         msg = dbus_message_new_method_call(
724                 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Hangup");
725         if (!msg)
726                 goto error;
727
728         INF("Hangup(%s)", c->base.path);
729         p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
730         return p;
731
732 error:
733         if (cb)
734                 cb((void *)data, OFONO_ERROR_FAILED);
735         free(ctx);
736         return NULL;
737 }
738
739 OFono_Pending *ofono_call_answer(OFono_Call *c, OFono_Simple_Cb cb,
740                                         const void *data)
741 {
742         OFono_Simple_Cb_Context *ctx = NULL;
743         OFono_Pending *p;
744         DBusMessage *msg;
745
746         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
747
748         if (cb) {
749                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
750                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
751                 ctx->cb = cb;
752                 ctx->data = data;
753         }
754
755         msg = dbus_message_new_method_call(
756                 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Answer");
757         if (!msg)
758                 goto error;
759
760         INF("Answer(%s)", c->base.path);
761         p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
762         return p;
763
764 error:
765         if (cb)
766                 cb((void *)data, OFONO_ERROR_FAILED);
767         free(ctx);
768         return NULL;
769 }
770
771 OFono_Call_State ofono_call_state_get(const OFono_Call *c)
772 {
773         EINA_SAFETY_ON_NULL_RETURN_VAL(c, OFONO_CALL_STATE_DISCONNECTED);
774         return c->state;
775 }
776
777 const char *ofono_call_name_get(const OFono_Call *c)
778 {
779         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
780         return c->name;
781 }
782
783 const char *ofono_call_line_id_get(const OFono_Call *c)
784 {
785         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
786         return c->line_id;
787 }
788
789 static void _ofono_calls_get_reply(void *data, DBusMessage *msg,
790                                         DBusError *err)
791 {
792         OFono_Modem *m = data;
793         DBusMessageIter array, dict;
794
795         if (!msg) {
796                 if (err)
797                         ERR("%s: %s", err->name, err->message);
798                 else
799                         ERR("No message");
800                 return;
801         }
802
803         eina_hash_free_buckets(m->calls);
804
805         if (!dbus_message_iter_init(msg, &array)) {
806                 ERR("Could not get calls");
807                 return;
808         }
809
810         dbus_message_iter_recurse(&array, &dict);
811         for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
812                         dbus_message_iter_next(&dict)) {
813                 DBusMessageIter value, properties;
814                 const char *path;
815
816                 dbus_message_iter_recurse(&dict, &value);
817                 dbus_message_iter_get_basic(&value, &path);
818
819                 dbus_message_iter_next(&value);
820                 dbus_message_iter_recurse(&value, &properties);
821
822                 _call_add(m, path, &properties);
823         }
824 }
825
826 static void _modem_calls_load(OFono_Modem *m)
827 {
828         DBusMessage *msg = dbus_message_new_method_call(
829                 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE,
830                 "GetCalls");
831
832         DBG("Get calls of %s", m->base.path);
833         _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m);
834 }
835
836 static OFono_Modem *_modem_new(const char *path)
837 {
838         OFono_Modem *m = calloc(1, sizeof(OFono_Modem));
839         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
840
841         m->base.path = eina_stringshare_add(path);
842         EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
843
844         m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free));
845         EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls);
846
847         return m;
848
849 error_calls:
850         eina_stringshare_del(m->base.path);
851 error_path:
852         free(m);
853         return NULL;
854 }
855
856 static void _modem_free(OFono_Modem *m)
857 {
858         DBG("m=%p %s", m, m->base.path);
859
860         if (modem_selected == m)
861                 modem_selected = NULL;
862
863         eina_stringshare_del(m->name);
864         eina_stringshare_del(m->serial);
865
866         eina_hash_free(m->calls);
867
868         _bus_object_free(&m->base);
869 }
870
871
872 static void _call_volume_property_update(OFono_Modem *m, const char *prop_name,
873                                                 DBusMessageIter *iter)
874 {
875
876         if (strcmp(prop_name, "Muted") == 0) {
877                 m->muted = _dbus_bool_get(iter);
878                 DBG("%s Muted %d", m->base.path, m->muted);
879         } else if (strcmp(prop_name, "SpeakerVolume") == 0) {
880                 dbus_message_iter_get_basic(iter, &m->speaker_volume);
881                 DBG("%s Speaker Volume %hhu", m->base.path, m->speaker_volume);
882         } else if (strcmp(prop_name, "MicrophoneVolume") == 0) {
883                 dbus_message_iter_get_basic(iter, &m->microphone_volume);
884                 DBG("%s Microphone Volume %hhu", m->base.path, m->speaker_volume);
885         }
886 }
887
888 static void _call_volume_property_changed(void *data, DBusMessage *msg)
889 {
890         OFono_Modem *m = data;
891         DBusMessageIter iter, variant_iter;
892         const char *prop_name;
893
894         if (!msg || !dbus_message_iter_init(msg, &iter)) {
895                 ERR("Could not handle message %p", msg);
896                 return;
897         }
898
899         dbus_message_iter_get_basic(&iter, &prop_name);
900         dbus_message_iter_next(&iter);
901         dbus_message_iter_recurse(&iter, &variant_iter);
902         _call_volume_property_update(m, prop_name, &variant_iter);
903
904         if (changed_cb)
905                 changed_cb((void *)changed_cb_data);
906 }
907
908 static unsigned int _modem_interfaces_extract(DBusMessageIter *array)
909 {
910         DBusMessageIter entry;
911         unsigned int interfaces = 0;
912
913         dbus_message_iter_recurse(array, &entry);
914         for (; dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING;
915                         dbus_message_iter_next(&entry)) {
916                 const struct API_Interface_Map *itr;
917                 const char *name;
918                 size_t namelen;
919
920                 dbus_message_iter_get_basic(&entry, &name);
921
922                 if (strncmp(name, OFONO_PREFIX, strlen(OFONO_PREFIX)) != 0)
923                         continue;
924
925                 name += strlen(OFONO_PREFIX);
926                 namelen = strlen(name);
927
928                 DBG("interface: %s", name);
929                 for (itr = api_iface_map; itr->name != NULL; itr++) {
930                         if ((itr->namelen == namelen) &&
931                                 (memcmp(itr->name, name, namelen) == 0)) {
932                                 interfaces |= itr->bit;
933                                 break;
934                         }
935                 }
936                 if (itr->name == NULL)
937                         WRN("ignored %s", name);
938         }
939
940         return interfaces;
941 }
942
943 static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces)
944 {
945
946         if (((m->interfaces & OFONO_API_CALL_VOL) == 0) &&
947                 (ifaces & OFONO_API_CALL_VOL) == OFONO_API_CALL_VOL)
948                 _ofono_call_volume_properties_get(m);
949 }
950
951 static void _modem_property_update(OFono_Modem *m, const char *key,
952                                         DBusMessageIter *value)
953 {
954         if (strcmp(key, "Powered") == 0) {
955                 m->powered = _dbus_bool_get(value);
956                 DBG("%s Powered %d", m->base.path, m->powered);
957         } else if (strcmp(key, "Online") == 0) {
958                 m->online = _dbus_bool_get(value);
959                 DBG("%s Online %d", m->base.path, m->online);
960         } else if (strcmp(key, "Interfaces") == 0) {
961                 unsigned int ifaces = _modem_interfaces_extract(value);
962                 DBG("%s Interfaces 0x%02x", m->base.path, ifaces);
963                 if (m->interfaces != ifaces) {
964                         _modem_update_interfaces(m, ifaces);
965                         m->interfaces = ifaces;
966
967                         if (modem_selected && modem_path_wanted &&
968                                 modem_selected->base.path != modem_path_wanted)
969                                 modem_selected = NULL;
970                 }
971         } else if (strcmp(key, "Serial") == 0) {
972                 const char *serial;
973                 dbus_message_iter_get_basic(value, &serial);
974                 DBG("%s Serial %s", m->base.path, serial);
975                 eina_stringshare_replace(&m->serial, serial);
976         } else if (strcmp(key, "Type") == 0) {
977                 const char *type;
978                 dbus_message_iter_get_basic(value, &type);
979                 DBG("%s Type %s", m->base.path, type);
980                 m->ignored = strcmp(type, "hardware") != 0;
981         } else
982                 DBG("%s %s (unused property)", m->base.path, key);
983
984         if (changed_cb)
985                 changed_cb((void *)changed_cb_data);
986 }
987
988 static void _ofono_call_volume_properties_get_reply(void *data,
989                                                         DBusMessage *msg,
990                                                         DBusError *err)
991 {
992         OFono_Modem *m = data;
993         DBusMessageIter iter, prop;
994
995         if (dbus_error_is_set(err)) {
996                 DBG("%s: %s", err->name, err->message);
997                 return;
998         }
999
1000         dbus_message_iter_init(msg, &iter);
1001         dbus_message_iter_recurse(&iter, &prop);
1002
1003         for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1004              dbus_message_iter_next(&prop)) {
1005                 DBusMessageIter entry, value;
1006                 const char *key;
1007
1008                 dbus_message_iter_recurse(&prop, &entry);
1009                 dbus_message_iter_get_basic(&entry, &key);
1010
1011                 dbus_message_iter_next(&entry);
1012                 dbus_message_iter_recurse(&entry, &value);
1013                 _call_volume_property_update(m, key, &value);
1014         }
1015 }
1016
1017 static void _ofono_call_volume_properties_get(OFono_Modem *m)
1018 {
1019         DBusMessage *msg;
1020         msg = dbus_message_new_method_call(bus_id, m->base.path,
1021                                                 OFONO_PREFIX
1022                                                 OFONO_CALL_VOL_IFACE,
1023                                                 "GetProperties");
1024         if (!msg)
1025                 return;
1026
1027         _bus_object_message_send(&m->base, msg,
1028                                         _ofono_call_volume_properties_get_reply, m);
1029 }
1030
1031 static void _modem_add(const char *path, DBusMessageIter *prop)
1032 {
1033         OFono_Modem *m;
1034
1035         DBG("path=%s", path);
1036
1037         m = eina_hash_find(modems, path);
1038         if (m) {
1039                 DBG("Modem already exists %p (%s)", m, path);
1040                 goto update_properties;
1041         }
1042
1043         m = _modem_new(path);
1044         EINA_SAFETY_ON_NULL_RETURN(m);
1045         eina_hash_add(modems, m->base.path, m);
1046
1047         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1048                                         "CallAdded", _call_added, m);
1049         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1050                                         "CallRemoved", _call_removed, m);
1051         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1052                                         "PropertyChanged",
1053                                         _call_volume_property_changed, m);
1054
1055         /* TODO: do we need to listen to BarringActive or Forwarded? */
1056
1057         if (modem_selected && modem_path_wanted &&
1058                 modem_selected->base.path != modem_path_wanted)
1059                 modem_selected = NULL;
1060
1061 update_properties:
1062         if (!prop)
1063                 return;
1064         for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
1065                         dbus_message_iter_next(prop)) {
1066                 DBusMessageIter entry, value;
1067                 const char *key;
1068
1069                 dbus_message_iter_recurse(prop, &entry);
1070                 dbus_message_iter_get_basic(&entry, &key);
1071
1072                 dbus_message_iter_next(&entry);
1073                 dbus_message_iter_recurse(&entry, &value);
1074
1075                 _modem_property_update(m, key, &value);
1076         }
1077
1078         if (m->interfaces & OFONO_API_VOICE)
1079                 _modem_calls_load(m);
1080 }
1081
1082 static void _modem_remove(const char *path)
1083 {
1084         DBG("path=%s", path);
1085         eina_hash_del_by_key(modems, path);
1086 }
1087
1088 static void _ofono_modems_get_reply(void *data __UNUSED__, DBusMessage *msg,
1089                                         DBusError *err)
1090 {
1091         DBusMessageIter array, dict;
1092
1093         pc_get_modems = NULL;
1094
1095         if (!msg) {
1096                 if (err)
1097                         ERR("%s: %s", err->name, err->message);
1098                 else
1099                         ERR("No message");
1100                 return;
1101         }
1102
1103         EINA_SAFETY_ON_NULL_RETURN(modems);
1104         eina_hash_free_buckets(modems);
1105
1106         if (!dbus_message_iter_init(msg, &array)) {
1107                 ERR("Could not get modems");
1108                 return;
1109         }
1110
1111         dbus_message_iter_recurse(&array, &dict);
1112         for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
1113                         dbus_message_iter_next(&dict)) {
1114                 DBusMessageIter value, properties;
1115                 const char *path;
1116
1117                 dbus_message_iter_recurse(&dict, &value);
1118                 dbus_message_iter_get_basic(&value, &path);
1119
1120                 dbus_message_iter_next(&value);
1121                 dbus_message_iter_recurse(&value, &properties);
1122
1123                 _modem_add(path, &properties);
1124         }
1125 }
1126
1127 static void _modem_added(void *data __UNUSED__, DBusMessage *msg)
1128 {
1129         DBusMessageIter iter, properties;
1130         const char *path;
1131
1132         if (!msg || !dbus_message_iter_init(msg, &iter)) {
1133                 ERR("Could not handle message %p", msg);
1134                 return;
1135         }
1136
1137         dbus_message_iter_get_basic(&iter, &path);
1138
1139         dbus_message_iter_next(&iter);
1140         dbus_message_iter_recurse(&iter, &properties);
1141
1142         _modem_add(path, &properties);
1143 }
1144
1145 static void _modem_removed(void *data __UNUSED__, DBusMessage *msg)
1146 {
1147         DBusError err;
1148         const char *path;
1149
1150         if (!msg) {
1151                 ERR("Could not handle message %p", msg);
1152                 return;
1153         }
1154
1155         dbus_error_init(&err);
1156         if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
1157                                         &path, NULL)) {
1158                 ERR("Could not get ModemRemoved arguments: %s: %s",
1159                         err.name, err.message);
1160                 dbus_error_free(&err);
1161                 return;
1162         }
1163
1164         _modem_remove(path);
1165 }
1166
1167 static void _modem_property_changed(void *data __UNUSED__, DBusMessage *msg)
1168 {
1169         const char *path;
1170         OFono_Modem *m;
1171         DBusMessageIter iter, value;
1172         const char *key;
1173
1174         if (!msg || !dbus_message_iter_init(msg, &iter)) {
1175                 ERR("Could not handle message %p", msg);
1176                 return;
1177         }
1178
1179         path = dbus_message_get_path(msg);
1180         DBG("path=%s", path);
1181
1182         m = eina_hash_find(modems, path);
1183         if (!m) {
1184                 DBG("Modem is unknown (%s)", path);
1185                 return;
1186         }
1187
1188         dbus_message_iter_get_basic(&iter, &key);
1189         dbus_message_iter_next(&iter);
1190         dbus_message_iter_recurse(&iter, &value);
1191         _modem_property_update(m, key, &value);
1192 }
1193
1194 static void _modems_load(void)
1195 {
1196         DBusMessage *msg = dbus_message_new_method_call(
1197                 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
1198
1199         if (pc_get_modems)
1200                 dbus_pending_call_cancel(pc_get_modems);
1201
1202         DBG("Get modems");
1203         pc_get_modems = e_dbus_message_send(
1204                 bus_conn, msg, _ofono_modems_get_reply, -1, NULL);
1205         dbus_message_unref(msg);
1206 }
1207
1208 static void _ofono_connected(const char *id)
1209 {
1210         free(bus_id);
1211         bus_id = strdup(id);
1212
1213         sig_modem_added = e_dbus_signal_handler_add(
1214                 bus_conn, bus_id, "/",
1215                 OFONO_PREFIX OFONO_MANAGER_IFACE,
1216                 "ModemAdded",
1217                 _modem_added, NULL);
1218
1219         sig_modem_removed = e_dbus_signal_handler_add(
1220                 bus_conn, bus_id, "/",
1221                 OFONO_PREFIX OFONO_MANAGER_IFACE,
1222                 "ModemRemoved",
1223                 _modem_removed, NULL);
1224
1225         sig_modem_prop_changed = e_dbus_signal_handler_add(
1226                 bus_conn, bus_id, NULL,
1227                 OFONO_PREFIX OFONO_MODEM_IFACE,
1228                 "PropertyChanged",
1229                 _modem_property_changed, NULL);
1230
1231         _modems_load();
1232
1233         if (connected_cb)
1234                 connected_cb((void *)connected_cb_data);
1235 }
1236
1237 static void _ofono_disconnected(void)
1238 {
1239         eina_hash_free_buckets(modems);
1240
1241         if (sig_modem_added) {
1242                 e_dbus_signal_handler_del(bus_conn, sig_modem_added);
1243                 sig_modem_added = NULL;
1244         }
1245
1246         if (sig_modem_removed) {
1247                 e_dbus_signal_handler_del(bus_conn, sig_modem_removed);
1248                 sig_modem_removed = NULL;
1249         }
1250
1251         if (sig_modem_prop_changed) {
1252                 e_dbus_signal_handler_del(bus_conn, sig_modem_prop_changed);
1253                 sig_modem_prop_changed = NULL;
1254         }
1255
1256         if (bus_id) {
1257                 if (disconnected_cb)
1258                         disconnected_cb((void *)disconnected_cb_data);
1259
1260                 free(bus_id);
1261                 bus_id = NULL;
1262         }
1263 }
1264
1265 static void _name_owner_changed(void *data __UNUSED__, DBusMessage *msg)
1266 {
1267         DBusError err;
1268         const char *name, *from, *to;
1269
1270         dbus_error_init(&err);
1271         if (!dbus_message_get_args(msg, &err,
1272                                         DBUS_TYPE_STRING, &name,
1273                                         DBUS_TYPE_STRING, &from,
1274                                         DBUS_TYPE_STRING, &to,
1275                                         DBUS_TYPE_INVALID)) {
1276                 ERR("Could not get NameOwnerChanged arguments: %s: %s",
1277                         err.name, err.message);
1278                 dbus_error_free(&err);
1279                 return;
1280         }
1281
1282         if (strcmp(name, bus_name) != 0)
1283                 return;
1284
1285         DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
1286
1287         if (from[0] == '\0' && to[0] != '\0') {
1288                 INF("oFono appeared as %s", to);
1289                 _ofono_connected(to);
1290         } else if (from[0] != '\0' && to[0] == '\0') {
1291                 INF("oFono disappeared from %s", from);
1292                 _ofono_disconnected();
1293         }
1294 }
1295
1296 static void _ofono_get_name_owner(void *data __UNUSED__, DBusMessage *msg, DBusError *err)
1297 {
1298         DBusMessageIter itr;
1299         const char *id;
1300
1301         if (!msg) {
1302                 if (err)
1303                         ERR("%s: %s", err->name, err->message);
1304                 else
1305                         ERR("No message");
1306                 return;
1307         }
1308
1309         dbus_message_iter_init(msg, &itr);
1310         dbus_message_iter_get_basic(&itr, &id);
1311         if (!id || id[0] == '\0') {
1312                 ERR("No name owner fo %s!", bus_name);
1313                 return;
1314         }
1315
1316         INF("oFono bus id: %s", id);
1317         _ofono_connected(id);
1318 }
1319
1320 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
1321                                         const char *new, OFono_Simple_Cb cb,
1322                                         const void *data)
1323 {
1324         OFono_Simple_Cb_Context *ctx = NULL;
1325         OFono_Error err = OFONO_ERROR_OFFLINE;
1326         OFono_Pending *p;
1327         DBusMessage *msg;
1328         OFono_Modem *m = _modem_selected_get();
1329         EINA_SAFETY_ON_NULL_GOTO(m, error);
1330         EINA_SAFETY_ON_NULL_GOTO(what, error);
1331         EINA_SAFETY_ON_NULL_GOTO(old, error);
1332         EINA_SAFETY_ON_NULL_GOTO(new, error);
1333
1334         if ((m->interfaces & OFONO_API_SIM) == 0)
1335                 goto error;
1336         err = OFONO_ERROR_FAILED;
1337
1338         if (cb) {
1339                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1340                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1341                 ctx->cb = cb;
1342                 ctx->data = data;
1343         }
1344
1345         msg = dbus_message_new_method_call(
1346                 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
1347                 "ChangePin");
1348         if (!msg)
1349                 goto error;
1350
1351         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1352                                         DBUS_TYPE_STRING, &old,
1353                                         DBUS_TYPE_STRING, &new,
1354                                         DBUS_TYPE_INVALID))
1355                 goto error_message;
1356
1357         INF("ChangePin(%s, %s, %s)", what, old, new);
1358         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1359         return p;
1360
1361 error_message:
1362         dbus_message_unref(msg);
1363 error:
1364         if (cb)
1365                 cb((void *)data, err);
1366         free(ctx);
1367         return NULL;
1368 }
1369
1370 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
1371                                         const char *new, OFono_Simple_Cb cb,
1372                                         const void *data)
1373 {
1374         OFono_Simple_Cb_Context *ctx = NULL;
1375         OFono_Error err = OFONO_ERROR_OFFLINE;
1376         OFono_Pending *p;
1377         DBusMessage *msg;
1378         OFono_Modem *m = _modem_selected_get();
1379         EINA_SAFETY_ON_NULL_GOTO(m, error);
1380         EINA_SAFETY_ON_NULL_GOTO(what, error);
1381         EINA_SAFETY_ON_NULL_GOTO(puk, error);
1382         EINA_SAFETY_ON_NULL_GOTO(new, error);
1383
1384         if ((m->interfaces & OFONO_API_SIM) == 0)
1385                 goto error;
1386         err = OFONO_ERROR_FAILED;
1387
1388         if (cb) {
1389                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1390                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1391                 ctx->cb = cb;
1392                 ctx->data = data;
1393         }
1394
1395         msg = dbus_message_new_method_call(
1396                 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
1397         if (!msg)
1398                 goto error;
1399
1400         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1401                                         DBUS_TYPE_STRING, &puk,
1402                                         DBUS_TYPE_STRING, &new,
1403                                         DBUS_TYPE_INVALID))
1404                 goto error_message;
1405
1406         INF("ResetPin(%s, %s, %s)", what, puk, new);
1407         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1408         return p;
1409
1410 error_message:
1411         dbus_message_unref(msg);
1412 error:
1413         if (cb)
1414                 cb((void *)data, err);
1415         free(ctx);
1416         return NULL;
1417 }
1418
1419 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
1420                                         DBusMessageIter *itr)
1421 {
1422         const char *ussd_response;
1423
1424         if (dbus_message_iter_get_arg_type(itr) != DBUS_TYPE_STRING) {
1425                 ERR("Invalid type: %c (expected: %c)",
1426                         dbus_message_iter_get_arg_type(itr), DBUS_TYPE_STRING);
1427                 return NULL;
1428         }
1429         dbus_message_iter_get_basic(itr, &ussd_response);
1430         EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
1431         return strdup(ussd_response);
1432 }
1433
1434 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
1435                                                 DBusMessageIter *dict)
1436 {
1437         for (; dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY;
1438                         dbus_message_iter_next(dict)) {
1439                 DBusMessageIter e, v;
1440                 const char *key, *value;
1441
1442                 dbus_message_iter_recurse(dict, &e);
1443                 dbus_message_iter_get_basic(&e, &key);
1444
1445                 dbus_message_iter_next(&e);
1446                 dbus_message_iter_recurse(&e, &v);
1447                 dbus_message_iter_get_basic(&v, &value);
1448
1449                 eina_strbuf_append_printf(buf, "&nbsp;&nbsp;&nbsp;%s=%s<br>",
1450                                                 key, value);
1451         }
1452 }
1453
1454 static char *_ss_initiate_convert_call1(const char *type, DBusMessageIter *itr)
1455 {
1456         DBusMessageIter array, dict;
1457         const char *ss_op, *service;
1458         Eina_Strbuf *buf;
1459         char *str;
1460
1461         dbus_message_iter_recurse(itr, &array);
1462
1463         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1464                 ERR("Invalid type: %c (expected: %c)",
1465                         dbus_message_iter_get_arg_type(&array),
1466                         DBUS_TYPE_STRING);
1467                 return NULL;
1468         }
1469         dbus_message_iter_get_basic(&array, &ss_op);
1470         EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1471
1472         if (!dbus_message_iter_next(&array)) {
1473                 ERR("Missing %s service", type);
1474                 return NULL;
1475         }
1476
1477         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1478                 ERR("Invalid type: %c (expected: %c)",
1479                         dbus_message_iter_get_arg_type(&array),
1480                         DBUS_TYPE_STRING);
1481                 return NULL;
1482         }
1483         dbus_message_iter_get_basic(&array, &service);
1484         EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
1485
1486         if (!dbus_message_iter_next(&array)) {
1487                 ERR("Missing %s information", type);
1488                 return NULL;
1489         }
1490
1491         buf = eina_strbuf_new();
1492         eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
1493                                         type, ss_op, service);
1494
1495         dbus_message_iter_recurse(&array, &dict);
1496         _ss_initiate_cb_dict_convert(buf, &dict);
1497
1498         str = eina_strbuf_string_steal(buf);
1499         eina_strbuf_free(buf);
1500         return str;
1501 }
1502
1503 static char *_ss_initiate_convert_call_waiting(const char *type,
1504                                                 DBusMessageIter *itr)
1505 {
1506         DBusMessageIter array, dict;
1507         const char *ss_op;
1508         Eina_Strbuf *buf;
1509         char *str;
1510
1511         dbus_message_iter_recurse(itr, &array);
1512
1513         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1514                 ERR("Invalid type: %c (expected: %c)",
1515                         dbus_message_iter_get_arg_type(&array),
1516                         DBUS_TYPE_STRING);
1517                 return NULL;
1518         }
1519         dbus_message_iter_get_basic(&array, &ss_op);
1520         EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1521
1522         if (!dbus_message_iter_next(&array)) {
1523                 ERR("Missing %s information", type);
1524                 return NULL;
1525         }
1526
1527         buf = eina_strbuf_new();
1528         eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
1529                                         type, ss_op);
1530
1531         dbus_message_iter_recurse(&array, &dict);
1532         _ss_initiate_cb_dict_convert(buf, &dict);
1533
1534         str = eina_strbuf_string_steal(buf);
1535         eina_strbuf_free(buf);
1536         return str;
1537 }
1538
1539 static char *_ss_initiate_convert_call2(const char *type,
1540                                                 DBusMessageIter *itr)
1541 {
1542         DBusMessageIter array;
1543         const char *ss_op, *status;
1544         Eina_Strbuf *buf;
1545         char *str;
1546
1547         dbus_message_iter_recurse(itr, &array);
1548
1549         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1550                 ERR("Invalid type: %c (expected: %c)",
1551                         dbus_message_iter_get_arg_type(&array),
1552                         DBUS_TYPE_STRING);
1553                 return NULL;
1554         }
1555         dbus_message_iter_get_basic(&array, &ss_op);
1556         EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1557
1558         if (!dbus_message_iter_next(&array)) {
1559                 ERR("Missing %s status", type);
1560                 return NULL;
1561         }
1562
1563         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1564                 ERR("Invalid type: %c (expected: %c)",
1565                         dbus_message_iter_get_arg_type(&array),
1566                         DBUS_TYPE_STRING);
1567                 return NULL;
1568         }
1569         dbus_message_iter_get_basic(&array, &status);
1570         EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
1571
1572         buf = eina_strbuf_new();
1573         eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
1574                                         type, ss_op, status);
1575
1576         str = eina_strbuf_string_steal(buf);
1577         eina_strbuf_free(buf);
1578         return str;
1579 }
1580
1581 static const struct SS_Initiate_Convert_Map {
1582         const char *type;
1583         size_t typelen;
1584         char *(*convert)(const char *type, DBusMessageIter *itr);
1585 } ss_initiate_convert_map[] = {
1586 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
1587         MAP("USSD", _ss_initiate_convert_ussd),
1588         MAP("CallBarring", _ss_initiate_convert_call1),
1589         MAP("CallForwarding", _ss_initiate_convert_call1),
1590         MAP("CallWaiting", _ss_initiate_convert_call_waiting),
1591         MAP("CallingLinePresentation", _ss_initiate_convert_call2),
1592         MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
1593         MAP("CallingLineRestriction", _ss_initiate_convert_call2),
1594         MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
1595 #undef MAP
1596         {NULL, 0, NULL}
1597 };
1598
1599 static char *_ss_initiate_convert(DBusMessage *msg)
1600 {
1601         DBusMessageIter array, variant;
1602         const struct SS_Initiate_Convert_Map *citr;
1603         const char *type = NULL;
1604         size_t typelen;
1605
1606         if (!dbus_message_iter_init(msg, &array))
1607                 goto error;
1608
1609         if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1610                 ERR("Invalid type for first argument: %c (expected: %c)",
1611                         dbus_message_iter_get_arg_type(&array),
1612                         DBUS_TYPE_STRING);
1613                 goto error;
1614         }
1615         dbus_message_iter_get_basic(&array, &type);
1616         if (!type) {
1617                 ERR("Couldn't get SupplementaryServices.Initiate type");
1618                 goto error;
1619         }
1620         DBG("type: %s", type);
1621
1622         if (!dbus_message_iter_next(&array)) {
1623                 ERR("Couldn't get SupplementaryServices.Initiate payload");
1624                 goto error;
1625         }
1626         dbus_message_iter_recurse(&array, &variant);
1627
1628         typelen = strlen(type);
1629         for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
1630                 if ((citr->typelen == typelen) &&
1631                         (memcmp(citr->type, type, typelen) == 0)) {
1632                         return citr->convert(type, &variant);
1633                 }
1634         }
1635         ERR("Could not convert SupplementaryServices.Initiate type %s", type);
1636
1637 error:
1638         return NULL;
1639 }
1640
1641 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
1642 {
1643         OFono_String_Cb_Context *ctx = NULL;
1644         OFono_Error err = OFONO_ERROR_OFFLINE;
1645         OFono_Pending *p;
1646         DBusMessage *msg;
1647         OFono_Modem *m = _modem_selected_get();
1648         EINA_SAFETY_ON_NULL_GOTO(m, error);
1649         EINA_SAFETY_ON_NULL_GOTO(command, error);
1650
1651         if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
1652                 goto error;
1653         err = OFONO_ERROR_FAILED;
1654
1655         ctx = calloc(1, sizeof(OFono_String_Cb_Context));
1656         EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1657         ctx->cb = cb;
1658         ctx->data = data;
1659         ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
1660         ctx->convert = _ss_initiate_convert;
1661
1662         msg = dbus_message_new_method_call(
1663                 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1664                 "Initiate");
1665         if (!msg)
1666                 goto error;
1667
1668         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &command,
1669                                         DBUS_TYPE_INVALID))
1670                 goto error_message;
1671
1672         INF("SupplementaryServices.Initiate(%s)", command);
1673         p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
1674         return p;
1675
1676 error_message:
1677         dbus_message_unref(msg);
1678 error:
1679         if (cb)
1680                 cb((void *)data, err, NULL);
1681         free(ctx);
1682         return NULL;
1683 }
1684
1685 typedef struct _OFono_Call_Cb_Context
1686 {
1687         OFono_Call_Cb cb;
1688         OFono_Modem *modem;
1689         const void *data;
1690         const char *name;
1691 } OFono_Call_Cb_Context;
1692
1693 static void _ofono_dial_reply(void *data, DBusMessage *msg, DBusError *err)
1694 {
1695         OFono_Call_Cb_Context *ctx = data;
1696         OFono_Call *c = NULL;
1697         OFono_Error oe = OFONO_ERROR_NONE;
1698
1699         if (!msg) {
1700                 DBG("%s: %s", err->name, err->message);
1701                 oe = _ofono_error_parse(err->name);
1702         } else {
1703                 DBusError e;
1704                 const char *path;
1705                 dbus_error_init(&e);
1706                 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
1707                                                 &path, DBUS_TYPE_INVALID)) {
1708                         ERR("Could not get Dial reply: %s: %s",
1709                                 e.name, e.message);
1710                         dbus_error_free(&e);
1711                         oe = OFONO_ERROR_FAILED;
1712                 } else {
1713                         c = eina_hash_find(ctx->modem->calls, path);
1714                         if (!c) {
1715                                 _call_add(ctx->modem, path, NULL);
1716                                 c = eina_hash_find(ctx->modem->calls, path);
1717                         }
1718                         if (!c) {
1719                                 ERR("Could not find call %s", path);
1720                                 oe = OFONO_ERROR_FAILED;
1721                         }
1722                 }
1723         }
1724
1725         if (ctx->cb)
1726                 ctx->cb((void *)ctx->data, oe, c);
1727 }
1728
1729 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
1730                                 OFono_Call_Cb cb, const void *data)
1731 {
1732         OFono_Call_Cb_Context *ctx = NULL;
1733         OFono_Error err = OFONO_ERROR_OFFLINE;
1734         OFono_Pending *p;
1735         DBusMessage *msg;
1736         OFono_Modem *m = _modem_selected_get();
1737         EINA_SAFETY_ON_NULL_GOTO(m, error);
1738
1739
1740         if ((m->interfaces & OFONO_API_VOICE) == 0)
1741                 goto error;
1742         err = OFONO_ERROR_FAILED;
1743
1744         if (!hide_callerid)
1745                 hide_callerid = "";
1746
1747         ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
1748         EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1749         ctx->cb = cb;
1750         ctx->data = data;
1751         ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
1752         ctx->modem = m;
1753
1754         msg = dbus_message_new_method_call(
1755                 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
1756         if (!msg)
1757                 goto error;
1758
1759         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
1760                                         DBUS_TYPE_STRING, &hide_callerid,
1761                                         DBUS_TYPE_INVALID))
1762                 goto error_message;
1763
1764         INF("Dial(%s, %s)", number, hide_callerid);
1765         p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
1766         return p;
1767
1768 error_message:
1769         dbus_message_unref(msg);
1770 error:
1771         if (cb)
1772                 cb((void *)data, err, NULL);
1773         free(ctx);
1774         return NULL;
1775 }
1776
1777 const char *ofono_modem_serial_get(void)
1778 {
1779         OFono_Modem *m = _modem_selected_get();
1780         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
1781         return m->serial;
1782 }
1783
1784 void ofono_modem_api_require(unsigned int api_mask)
1785 {
1786         if (modem_api_mask == api_mask)
1787                 return;
1788         modem_api_mask = api_mask;
1789         modem_selected = NULL;
1790 }
1791
1792 void ofono_modem_path_wanted_set(const char *path)
1793 {
1794         if (eina_stringshare_replace(&modem_path_wanted, path))
1795                 modem_selected = NULL;
1796 }
1797
1798 void ofono_connected_cb_set(void (*cb)(void *data), const void *data)
1799 {
1800         connected_cb = cb;
1801         connected_cb_data = data;
1802 }
1803
1804 void ofono_disconnected_cb_set(void (*cb)(void *data), const void *data)
1805 {
1806         disconnected_cb = cb;
1807         disconnected_cb_data = data;
1808 }
1809
1810 void ofono_changed_cb_set(void (*cb)(void *data), const void *data)
1811 {
1812         changed_cb = cb;
1813         changed_cb_data = data;
1814 }
1815
1816 void ofono_call_added_cb_set(void (*cb)(void *data, OFono_Call *call),
1817                                 const void *data)
1818 {
1819         call_added_cb = cb;
1820         call_added_cb_data = data;
1821 }
1822
1823 void ofono_call_removed_cb_set(void (*cb)(void *data, OFono_Call *call),
1824                                 const void *data)
1825 {
1826         call_removed_cb = cb;
1827         call_removed_cb_data = data;
1828 }
1829
1830 void ofono_call_changed_cb_set(void (*cb)(void *data, OFono_Call *call),
1831                                 const void *data)
1832 {
1833         call_changed_cb = cb;
1834         call_changed_cb_data = data;
1835 }
1836
1837 void ofono_call_disconnected_cb_set(void (*cb)(void *data, OFono_Call *call, const char *reason),
1838                                 const void *data)
1839 {
1840         call_disconnected_cb = cb;
1841         call_disconnected_cb_data = data;
1842 }
1843
1844 Eina_Bool ofono_init(void)
1845 {
1846         if (!elm_need_e_dbus()) {
1847                 CRITICAL("Elementary does not support DBus.");
1848                 return EINA_FALSE;
1849         }
1850
1851         bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
1852         if (!bus_conn) {
1853                 CRITICAL("Could not get DBus System Bus");
1854                 return EINA_FALSE;
1855         }
1856
1857         modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
1858         EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
1859
1860         e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
1861                                         E_DBUS_FDO_INTERFACE,
1862                                         "NameOwnerChanged",
1863                                         _name_owner_changed, NULL);
1864
1865         e_dbus_get_name_owner(bus_conn, bus_name, _ofono_get_name_owner, NULL);
1866
1867         return EINA_TRUE;
1868 }
1869
1870 void ofono_shutdown(void)
1871 {
1872         if (pc_get_modems) {
1873                 dbus_pending_call_cancel(pc_get_modems);
1874                 pc_get_modems = NULL;
1875         }
1876
1877         _ofono_disconnected();
1878         eina_stringshare_replace(&modem_path_wanted, NULL);
1879
1880         eina_hash_free(modems);
1881         modems = NULL;
1882 }
1883
1884 static OFono_Pending *_ofono_call_volume_property_set(char *property,
1885                                                         int type, void *value,
1886                                                         OFono_Simple_Cb cb,
1887                                                         const void *data)
1888 {
1889         OFono_Pending *p;
1890         OFono_Simple_Cb_Context *ctx = NULL;
1891         DBusMessage *msg;
1892         DBusMessageIter iter, variant;
1893         OFono_Modem *m = _modem_selected_get();
1894         char type_to_send[2] = { type , DBUS_TYPE_INVALID };
1895
1896         EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
1897
1898         if (cb) {
1899                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1900                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
1901                 ctx->cb = cb;
1902                 ctx->data = data;
1903         }
1904
1905         msg = dbus_message_new_method_call(bus_id, m->base.path,
1906                                            OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1907                                            "SetProperty");
1908         if (!msg)
1909                 goto error_no_dbus_message;
1910
1911         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &property,
1912                                  DBUS_TYPE_INVALID))
1913                 goto error_message_args;
1914
1915         dbus_message_iter_init_append(msg, &iter);
1916
1917         if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1918                                          type_to_send, &variant))
1919                 goto error_message_args;
1920
1921         if (!dbus_message_iter_append_basic(&variant, type, value) ||
1922                         !dbus_message_iter_close_container(&iter, &variant)) {
1923                 dbus_message_iter_abandon_container(&iter, &variant);
1924                 goto error_message_args;
1925         }
1926
1927         INF("Call-Volume - Property:%s called.", property);
1928         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1929         return p;
1930
1931 error_message_args:
1932         dbus_message_unref(msg);
1933
1934 error_no_dbus_message:
1935         if (cb)
1936                 cb((void *)data, OFONO_ERROR_FAILED);
1937         free(ctx);
1938         return NULL;
1939 }
1940
1941 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
1942                                 const void *data)
1943 {
1944         dbus_bool_t dbus_mute = !!mute;
1945
1946         return  _ofono_call_volume_property_set("Muted", DBUS_TYPE_BOOLEAN,
1947                                                 &dbus_mute, cb, data);
1948 }
1949
1950 Eina_Bool ofono_mute_get(void)
1951 {
1952         OFono_Modem *m = _modem_selected_get();
1953         EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
1954         return m->muted;
1955 }
1956
1957 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
1958                                         OFono_Simple_Cb cb,
1959                                         const void *data)
1960 {
1961
1962         return _ofono_call_volume_property_set("SpeakerVolume", DBUS_TYPE_BYTE,
1963                                                 &volume, cb, data);
1964 }
1965
1966 unsigned char ofono_volume_speaker_get(void)
1967 {
1968         OFono_Modem *m = _modem_selected_get();
1969         EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
1970         return m->speaker_volume;
1971 }
1972
1973 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
1974                                                 OFono_Simple_Cb cb,
1975                                                 const void *data)
1976 {
1977         return _ofono_call_volume_property_set("MicrophoneVolume",
1978                                                 DBUS_TYPE_BYTE, &volume, cb,
1979                                                 data);
1980 }
1981
1982 unsigned char ofono_volume_microphone_get(void)
1983 {
1984         OFono_Modem *m = _modem_selected_get();
1985         EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
1986         return m->microphone_volume;
1987 }
1988
1989 OFono_Pending *ofono_tones_send(const char *tones,
1990                                                 OFono_Simple_Cb cb,
1991                                                 const void *data)
1992 {
1993         OFono_Pending *p;
1994         DBusMessage *msg;
1995         OFono_Simple_Cb_Context *ctx = NULL;
1996         OFono_Modem *m = _modem_selected_get();
1997
1998         EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
1999
2000         if (cb) {
2001                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2002                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2003                 ctx->cb = cb;
2004                 ctx->data = data;
2005         }
2006
2007         msg = dbus_message_new_method_call(
2008                                 bus_id, m->base.path,
2009                                 OFONO_PREFIX OFONO_VOICE_IFACE,
2010                                 "SendTones");
2011         if (!msg)
2012                 goto error_no_dbus_message;
2013
2014         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &tones,
2015                                       DBUS_TYPE_INVALID))
2016                 goto error_message_args;
2017
2018         INF("Voice-Call-Manager - SendTones:%s called.", tones);
2019         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2020
2021         return p;
2022 error_message_args:
2023         dbus_message_unref(msg);
2024
2025 error_no_dbus_message:
2026         if (cb)
2027                 cb((void *)data, OFONO_ERROR_FAILED);
2028         free(ctx);
2029         return NULL;
2030 }
2031
2032 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
2033                                         const void *data)
2034 {
2035         return _ofono_multiparty("CreateMultiparty",
2036                                         _ofono_simple_reply, cb, data);
2037 }
2038