Fix TC-2372 Dialer crashes when BT phone is offline
[profile/ivi/lemolo.git] / utils / ofono.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include <Elementary.h>
5 #include <Eldbus.h>
6
7 #include "ofono.h"
8 #include "log.h"
9
10 #include <time.h>
11
12 typedef struct _OFono_Modem OFono_Modem;
13 typedef struct _OFono_Bus_Object OFono_Bus_Object;
14
15 static const char bus_name[] = "org.ofono";
16
17 static const char *known_modem_types[] = {"hfp", "sap", "hardware", NULL};
18
19 static Eldbus_Connection *bus_conn = NULL;
20 static char *bus_id = NULL;
21 static Eina_Hash *modems = NULL;
22 static OFono_Modem *modem_selected = NULL;
23 static const char *modem_path_wanted = NULL;
24 static unsigned int modem_api_mask = 0;
25 static Eina_List *modem_types = NULL;
26 static Eldbus_Signal_Handler *sig_modem_added = NULL;
27 static Eldbus_Signal_Handler *sig_modem_removed = NULL;
28 static Eldbus_Signal_Handler *sig_modem_prop_changed = NULL;
29 static Eldbus_Pending *pc_get_modems = NULL;
30
31 static void _ofono_call_volume_properties_get(OFono_Modem *m);
32 static void _ofono_msg_waiting_properties_get(OFono_Modem *m);
33 static void _ofono_suppl_serv_properties_get(OFono_Modem *m);
34 static void _ofono_msg_properties_get(OFono_Modem *m);
35
36 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
37                                         OFono_Simple_Cb cb, const void *data);
38
39 struct _OFono_Callback_List_Modem_Node
40 {
41         EINA_INLIST;
42         void (*cb)(void *data);
43         const void *cb_data;
44 };
45
46 struct _OFono_Callback_List_Call_Node
47 {
48         EINA_INLIST;
49         void (*cb)(void *data, OFono_Call *call);
50         const void *cb_data;
51 };
52
53 struct _OFono_Callback_List_Call_Disconnected_Node
54 {
55         EINA_INLIST;
56         void (*cb)(void *data, OFono_Call *call, const char *reason);
57         const void *cb_data;
58 };
59
60 struct _OFono_Callback_List_USSD_Notify_Node
61 {
62         EINA_INLIST;
63         void (*cb)(void *data, Eina_Bool needs_reply, const char *msg);
64         const void *cb_data;
65 };
66
67 struct _OFono_Callback_List_Sent_SMS_Node
68 {
69         EINA_INLIST;
70         OFono_Sent_SMS_Cb cb;
71         const void *cb_data;
72 };
73
74 struct _OFono_Callback_List_Incoming_SMS_Node
75 {
76         EINA_INLIST;
77         OFono_Incoming_SMS_Cb cb;
78         const void *cb_data;
79 };
80
81 static Eina_Inlist *cbs_modem_changed = NULL;
82 static Eina_Inlist *cbs_modem_connected = NULL;
83 static Eina_Inlist *cbs_modem_disconnected = NULL;
84 static Eina_Inlist *cbs_ussd_notify = NULL;
85
86 static Eina_Inlist *cbs_call_changed = NULL;
87 static Eina_Inlist *cbs_call_added = NULL;
88 static Eina_Inlist *cbs_call_disconnected = NULL;
89 static Eina_Inlist *cbs_call_removed = NULL;
90
91 static Eina_Inlist *cbs_sent_sms_changed = NULL;
92 static Eina_Inlist *cbs_incoming_sms = NULL;
93
94 #define OFONO_SERVICE                   "org.ofono"
95
96 #define OFONO_PREFIX                    OFONO_SERVICE "."
97 #define OFONO_PREFIX_ERROR              OFONO_SERVICE ".Error."
98 #define OFONO_MODEM_IFACE               "Modem"
99 #define OFONO_MANAGER_IFACE             "Manager"
100 #define OFONO_SIM_IFACE                 "SimManager"
101 #define OFONO_NETREG_IFACE              "NetworkRegistration"
102 #define OFONO_VOICE_IFACE               "VoiceCallManager"
103 #define OFONO_MSG_IFACE                 "MessageManager"
104 #define OFONO_MSG_WAITING_IFACE         "MessageWaiting"
105 #define OFONO_SMART_MSG_IFACE           "SmartMessaging"
106 #define OFONO_STK_IFACE                 "SimToolkit"
107
108 #define OFONO_CALL_FW_IFACE             "CallForwarding"
109 #define OFONO_CALL_VOL_IFACE            "CallVolume"
110 #define OFONO_CALL_METER_IFACE          "CallMeter"
111 #define OFONO_CALL_SET_IFACE            "CallSettings"
112 #define OFONO_CALL_BAR_IFACE            "CallBarring"
113 #define OFONO_SUPPL_SERV_IFACE          "SupplementaryServices"
114 #define OFONO_TXT_TEL_IFACE             "TextTelephony"
115 #define OFONO_CELL_BROAD_IFACE          "CellBroadcast"
116 #define OFONO_CONNMAN_IFACE             "ConnectionManager"
117 #define OFONO_PUSH_NOTIF_IFACE          "PushNotification"
118 #define OFONO_PHONEBOOK_IFACE           "Phonebook"
119 #define OFONO_ASN_IFACE                 "AssistedSatelliteNavigation"
120
121 static const struct API_Interface_Map {
122         unsigned int bit;
123         const char *name;
124         size_t namelen;
125 } api_iface_map[] = {
126 #define MAP(bit, name) {bit, name, sizeof(name) - 1}
127         MAP(OFONO_API_SIM, OFONO_SIM_IFACE),
128         MAP(OFONO_API_NETREG, OFONO_NETREG_IFACE),
129         MAP(OFONO_API_VOICE, OFONO_VOICE_IFACE),
130         MAP(OFONO_API_MSG, OFONO_MSG_IFACE),
131         MAP(OFONO_API_MSG_WAITING, OFONO_MSG_WAITING_IFACE),
132         MAP(OFONO_API_SMART_MSG, OFONO_SMART_MSG_IFACE),
133         MAP(OFONO_API_STK, OFONO_STK_IFACE),
134         MAP(OFONO_API_CALL_FW, OFONO_CALL_FW_IFACE),
135         MAP(OFONO_API_CALL_VOL, OFONO_CALL_VOL_IFACE),
136         MAP(OFONO_API_CALL_METER, OFONO_CALL_METER_IFACE),
137         MAP(OFONO_API_CALL_SET, OFONO_CALL_SET_IFACE),
138         MAP(OFONO_API_CALL_BAR, OFONO_CALL_BAR_IFACE),
139         MAP(OFONO_API_SUPPL_SERV, OFONO_SUPPL_SERV_IFACE),
140         MAP(OFONO_API_TXT_TEL, OFONO_TXT_TEL_IFACE),
141         MAP(OFONO_API_CELL_BROAD, OFONO_CELL_BROAD_IFACE),
142         MAP(OFONO_API_CONNMAN, OFONO_CONNMAN_IFACE),
143         MAP(OFONO_API_PUSH_NOTIF, OFONO_PUSH_NOTIF_IFACE),
144         MAP(OFONO_API_PHONEBOOK, OFONO_PHONEBOOK_IFACE),
145         MAP(OFONO_API_ASN, OFONO_ASN_IFACE),
146 #undef MAP
147         {0, NULL, 0}
148 };
149
150 static const struct Error_Map {
151         OFono_Error id;
152         const char *name;
153         const char *message;
154         size_t namelen;
155 } error_map[] = {
156 #define MAP(id, name, msg) {id, name, msg, sizeof(name) - 1}
157         MAP(OFONO_ERROR_FAILED, "Failed", "Failed"),
158         MAP(OFONO_ERROR_DOES_NOT_EXIST, "DoesNotExist", "Does not exist"),
159         MAP(OFONO_ERROR_IN_PROGRESS, "InProgress", "Operation in progress"),
160         MAP(OFONO_ERROR_IN_USE, "InUse", "Already in use"),
161         MAP(OFONO_ERROR_INVALID_ARGS, "InvalidArguments", "Invalid arguments"),
162         MAP(OFONO_ERROR_INVALID_FORMAT, "InvalidFormat", "Invalid format"),
163         MAP(OFONO_ERROR_ACCESS_DENIED, "AccessDenied", "Access Denied"),
164         MAP(OFONO_ERROR_ATTACH_IN_PROGRESS, "AttachInProgress",
165                 "Attach is already in progress"),
166         MAP(OFONO_ERROR_INCORRECT_PASSWORD, "IncorrectPassword",
167                 "Incorrect password"),
168         MAP(OFONO_ERROR_NOT_ACTIVE, "NotActive", "Not active"),
169         MAP(OFONO_ERROR_NOT_ALLOWED, "NotAllowed", "Not allowed"),
170         MAP(OFONO_ERROR_NOT_ATTACHED, "NotAttached", "Not attached"),
171         MAP(OFONO_ERROR_NOT_AVAILABLE, "NotAvailable", "Not available"),
172         MAP(OFONO_ERROR_NOT_FOUND, "NotFound", "Not found"),
173         MAP(OFONO_ERROR_NOT_IMPLEMENTED, "NotImplemented", "Not implemented"),
174         MAP(OFONO_ERROR_NOT_RECOGNIZED, "NotRecognized", "Not recognized"),
175         MAP(OFONO_ERROR_NOT_REGISTERED, "NotRegistered", "Not registered"),
176         MAP(OFONO_ERROR_NOT_SUPPORTED, "NotSupported", "Not supported"),
177         MAP(OFONO_ERROR_SIM_NOT_READY, "SimNotReady", "SIM not ready"),
178         MAP(OFONO_ERROR_STK, "SimToolkit", "SIM Toolkit Failed"),
179         MAP(OFONO_ERROR_TIMEDOUT, "Timedout", "Timed out"),
180 #undef MAP
181         {0, NULL, NULL, 0}
182 };
183
184 const char *ofono_error_message_get(OFono_Error e)
185 {
186         const struct Error_Map *itr;
187
188         if (e == OFONO_ERROR_NONE)
189                 return "No error";
190
191         for (itr = error_map; itr->name != NULL; itr++)
192                 if (itr->id == e)
193                         return itr->message;
194
195         return "Unknown error";
196 }
197
198 static OFono_Error _ofono_error_parse(const char *name)
199 {
200         size_t namelen, prefixlen = sizeof(OFONO_PREFIX_ERROR) - 1;
201         const struct Error_Map *itr;
202
203         /* whenever interfaces are not there due modem being offline */
204         if (strcmp(name, "org.freedesktop.DBus.Error.UnknownMethod") == 0)
205                 return OFONO_ERROR_OFFLINE;
206
207         if (strncmp(name, OFONO_PREFIX_ERROR, prefixlen) != 0)
208                 return OFONO_ERROR_FAILED;
209
210         name += prefixlen;
211         namelen = strlen(name);
212         for (itr = error_map; itr->name != NULL; itr++)
213                 if ((itr->namelen == namelen) &&
214                         (memcmp(name, itr->name, namelen) == 0))
215                         return itr->id;
216
217         return OFONO_ERROR_FAILED;
218 }
219
220 typedef struct _OFono_Simple_Cb_Context
221 {
222         OFono_Simple_Cb cb;
223         const void *data;
224 } OFono_Simple_Cb_Context;
225
226 static void _ofono_simple_reply(void *data, Eldbus_Message *msg,
227                                                 Eldbus_Pending *pending __UNUSED__)
228 {
229         OFono_Simple_Cb_Context *ctx = data;
230         OFono_Error oe = OFONO_ERROR_NONE;
231         const char *err_name, *err_message;
232
233         if (!msg) {
234                 ERR("No message");
235                 oe = OFONO_ERROR_FAILED;
236         }
237
238         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
239                 ERR("Ofono reply error %s: %s", err_name, err_message);
240                 oe = _ofono_error_parse(err_name);
241         }
242
243         if (ctx) {
244                 ctx->cb((void *)ctx->data, oe);
245                 free(ctx);
246         }
247 }
248
249 typedef struct _OFono_String_Cb_Context
250 {
251         OFono_String_Cb cb;
252         const void *data;
253         const char *name;
254         char *(*convert)(Eldbus_Message *msg);
255 } OFono_String_Cb_Context;
256
257 static void _ofono_string_reply(void *data, Eldbus_Message *msg,
258                                                 Eldbus_Pending *pending __UNUSED__)
259 {
260         OFono_String_Cb_Context *ctx = data;
261         OFono_Error oe = OFONO_ERROR_NONE;
262         char *str = NULL;
263         const char *err_name, *err_message;
264
265         EINA_SAFETY_ON_NULL_RETURN(data);
266
267         if (!msg) {
268                 ERR("No message");
269                 oe = OFONO_ERROR_FAILED;
270         }
271
272         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
273                 ERR("Ofono reply error %s: %s", err_name, err_message);
274                 oe = _ofono_error_parse(err_name);
275         } else {
276                 str = ctx->convert(msg);
277                 if (!str)
278                         oe = OFONO_ERROR_NOT_SUPPORTED;
279         }
280
281         if (ctx->cb)
282                 ctx->cb((void *)ctx->data, oe, str);
283         else
284                 DBG("%s %s", ctx->name, str);
285
286         free(str);
287         free(ctx);
288 }
289
290 struct _OFono_Pending
291 {
292         EINA_INLIST;
293         Eldbus_Pending *pending;
294         Eldbus_Message_Cb cb;
295         void *data;
296         void *owner;
297 };
298
299 struct _OFono_Bus_Object
300 {
301         const char *path;
302         Eina_Inlist *dbus_pending; /* of OFono_Pending */
303         Eina_List *dbus_signals; /* of Eldbus_Signal_Handler */
304 };
305
306 static void _notify_ofono_callbacks_call_list(Eina_Inlist *list,
307                                                 OFono_Call *call)
308 {
309         OFono_Callback_List_Call_Node *node;
310
311         EINA_INLIST_FOREACH(list, node)
312                 node->cb((void *) node->cb_data, call);
313 }
314
315 static void _notify_ofono_callbacks_call_disconnected_list(Eina_Inlist *list,
316                                                                 OFono_Call *call,
317                                                                 const char *reason)
318 {
319         OFono_Callback_List_Call_Disconnected_Node *node;
320
321         DBG("call=%p, reason=%s", call, reason);
322
323         EINA_INLIST_FOREACH(list, node)
324                 node->cb((void *) node->cb_data, call, reason);
325 }
326
327 static void _notify_ofono_callbacks_ussd_notify_list(Eina_Inlist *list,
328                                                         Eina_Bool needs_reply,
329                                                         const char *msg)
330 {
331         OFono_Callback_List_USSD_Notify_Node *node;
332
333         DBG("needs_reply=%hhu, msg=%s", needs_reply, msg);
334
335         EINA_INLIST_FOREACH(list, node)
336                 node->cb((void *) node->cb_data, needs_reply, msg);
337 }
338
339 static void _bus_object_free(OFono_Bus_Object *o)
340 {
341         Eldbus_Signal_Handler *sh;
342
343         eina_stringshare_del(o->path);
344
345         while (o->dbus_pending) {
346                 ofono_pending_cancel(
347                         EINA_INLIST_CONTAINER_GET(o->dbus_pending,
348                                                         OFono_Pending));
349         }
350
351         EINA_LIST_FREE(o->dbus_signals, sh)
352                 eldbus_signal_handler_del(sh);
353
354         free(o);
355 }
356
357 static void _bus_object_message_send_reply(void *data, Eldbus_Message *reply,
358                                                 Eldbus_Pending *pending __UNUSED__)
359 {
360         OFono_Pending *p = data;
361         OFono_Bus_Object *o = p->owner;
362
363         if (p->cb)
364                 p->cb(p->data, reply, NULL);
365
366         if (!o->dbus_pending)
367                 return;
368
369         o->dbus_pending = eina_inlist_remove(o->dbus_pending, EINA_INLIST_GET(p));
370         free(p);
371 }
372
373 static OFono_Pending *_bus_object_message_send(OFono_Bus_Object *o,
374                                                 Eldbus_Message *msg,
375                                                 Eldbus_Message_Cb cb,
376                                                 void *data)
377 {
378         OFono_Pending *p;
379         EINA_SAFETY_ON_NULL_GOTO(o, error);
380         EINA_SAFETY_ON_NULL_GOTO(msg, error);
381
382         p = calloc(1, sizeof(OFono_Pending));
383         EINA_SAFETY_ON_NULL_GOTO(p, error);
384
385         p->owner = o;
386         p->cb = cb;
387         p->data = data;
388
389         p->pending = eldbus_connection_send(
390                 bus_conn, msg, _bus_object_message_send_reply, p, -1);
391         EINA_SAFETY_ON_NULL_GOTO(p->pending, error_send);
392
393         o->dbus_pending = eina_inlist_append(o->dbus_pending,
394                                                 EINA_INLIST_GET(p));
395
396         return p;
397
398 error_send:
399         free(p);
400 error:
401         if (cb) {
402                 cb(data, NULL, NULL);
403         }
404         eldbus_message_unref(msg);
405         return NULL;
406 }
407
408 void ofono_pending_cancel(OFono_Pending *p)
409 {
410         OFono_Bus_Object *o;
411
412         EINA_SAFETY_ON_NULL_RETURN(p);
413
414         o = p->owner;
415         o->dbus_pending = eina_inlist_remove(o->dbus_pending, EINA_INLIST_GET(p));
416
417         if (p->cb)
418                 p->cb(p->data, NULL, NULL);
419
420         eldbus_pending_cancel(p->pending);
421         free(p);
422 }
423
424 static void _bus_object_signal_listen(OFono_Bus_Object *o, const char *iface,
425                                         const char *name, Eldbus_Signal_Cb cb,
426                                         void *data)
427 {
428         Eldbus_Signal_Handler *sh = eldbus_signal_handler_add(
429                 bus_conn, bus_id, o->path, iface, name, cb, data);
430         EINA_SAFETY_ON_NULL_RETURN(sh);
431
432         o->dbus_signals = eina_list_append(o->dbus_signals, sh);
433 }
434
435 typedef struct _OFono_Call_Cb_Context
436 {
437         OFono_Call_Cb cb;
438         OFono_Modem *modem;
439         const void *data;
440         const char *name;
441 } OFono_Call_Cb_Context;
442
443 struct _OFono_Call
444 {
445         OFono_Bus_Object base;
446         const char *line_id;
447         const char *incoming_line;
448         const char *name;
449         double start_time;
450         time_t full_start_time;
451         OFono_Call_State state;
452         Eina_Bool multiparty : 1;
453         Eina_Bool emergency : 1;
454         OFono_Call_Cb_Context *pending_dial;
455 };
456
457 typedef struct _OFono_Sent_SMS_Cb_Context
458 {
459         OFono_Sent_SMS_Cb cb;
460         OFono_Modem *modem;
461         const void *data;
462         const char *destination;
463         const char *message;
464 } OFono_Sent_SMS_Cb_Context;
465
466 struct _OFono_Sent_SMS
467 {
468         OFono_Bus_Object base;
469         OFono_Sent_SMS_State state;
470         OFono_Sent_SMS_Cb_Context *pending_send;
471         const char *destination;
472         const char *message;
473         time_t timestamp;
474 };
475
476 struct _OFono_Modem
477 {
478         OFono_Bus_Object base;
479         const char *name;
480         const char *serial;
481         const char *voicemail_number;
482         const char *serv_center_addr;
483         const char *msg_bearer;
484         const char *msg_alphabet;
485         Eina_Hash *calls;
486         Eina_Hash *sent_sms;
487         unsigned int interfaces;
488         unsigned char strength;
489         unsigned char data_strength;
490         unsigned char speaker_volume;
491         unsigned char microphone_volume;
492         unsigned char voicemail_count;
493         OFono_USSD_State ussd_state;
494         Eina_Bool ignored : 1;
495         Eina_Bool powered : 1;
496         Eina_Bool online : 1;
497         Eina_Bool roaming : 1;
498         Eina_Bool muted : 1;
499         Eina_Bool voicemail_waiting : 1;
500         Eina_Bool use_delivery_reports : 1;
501 };
502
503 static OFono_Call *_call_new(const char *path)
504 {
505         OFono_Call *c = calloc(1, sizeof(OFono_Call));
506         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
507
508         c->base.path = eina_stringshare_add(path);
509         EINA_SAFETY_ON_NULL_GOTO(c->base.path, error_path);
510
511         c->start_time = -1.0;
512
513         return c;
514
515 error_path:
516         free(c);
517         return NULL;
518 }
519
520 static void _call_free(OFono_Call *c)
521 {
522         DBG("c=%p %s", c, c->base.path);
523         ofono_call_hangup(c, NULL, NULL);
524
525         _notify_ofono_callbacks_call_list(cbs_call_removed, c);
526
527         eina_stringshare_del(c->line_id);
528         eina_stringshare_del(c->incoming_line);
529         eina_stringshare_del(c->name);
530
531         _bus_object_free(&c->base);
532 }
533
534 static OFono_Call_State _call_state_parse(const char *str)
535 {
536         if (strcmp(str, "active") == 0)
537                 return OFONO_CALL_STATE_ACTIVE;
538         else if (strcmp(str, "held") == 0)
539                 return OFONO_CALL_STATE_HELD;
540         else if (strcmp(str, "dialing") == 0)
541                 return OFONO_CALL_STATE_DIALING;
542         else if (strcmp(str, "alerting") == 0)
543                 return OFONO_CALL_STATE_ALERTING;
544         else if (strcmp(str, "incoming") == 0)
545                 return OFONO_CALL_STATE_INCOMING;
546         else if (strcmp(str, "waiting") == 0)
547                 return OFONO_CALL_STATE_WAITING;
548         else if (strcmp(str, "disconnected") == 0)
549                 return OFONO_CALL_STATE_DISCONNECTED;
550
551         ERR("unknown call state: %s", str);
552         return OFONO_CALL_STATE_DISCONNECTED;
553 }
554
555 static time_t _ofono_time_parse(const char *str)
556 {
557         struct tm tm;
558         time_t zonediff;
559
560         memset(&tm, 0, sizeof(tm));
561
562         strptime(str, "%Y-%m-%dT%H:%M:%S%z", &tm);
563         zonediff = tm.tm_gmtoff; /* mktime resets it */
564
565         return mktime(&tm) - zonediff - timezone;
566 }
567
568 static void _call_property_update(OFono_Call *c, const char *key,
569                                         Eldbus_Message_Iter *value)
570 {
571         if (strcmp(key, "LineIdentification") == 0) {
572                 const char *str;
573                 eldbus_message_iter_basic_get(value, &str);
574                 DBG("%s LineIdentification %s", c->base.path, str);
575                 eina_stringshare_replace(&c->line_id, str);
576         } else if (strcmp(key, "IncomingLine") == 0) {
577                 const char *str;
578                 eldbus_message_iter_basic_get(value, &str);
579                 DBG("%s IncomingLine %s", c->base.path, str);
580                 eina_stringshare_replace(&c->incoming_line, str);
581         } else if (strcmp(key, "State") == 0) {
582                 const char *str;
583                 OFono_Call_State state;
584                 eldbus_message_iter_basic_get(value, &str);
585                 state = _call_state_parse(str);
586                 DBG("%s State %s (%d)", c->base.path, str, state);
587                 c->state = state;
588                 if (state == OFONO_CALL_STATE_ACTIVE) {
589                         if (c->start_time < 0.0)
590                                 c->start_time = ecore_loop_time_get();
591                         if (c->full_start_time == 0)
592                                 c->full_start_time = time(NULL);
593                 }
594         } else if (strcmp(key, "Name") == 0) {
595                 const char *str;
596                 eldbus_message_iter_basic_get(value, &str);
597                 DBG("%s Name %s", c->base.path, str);
598                 eina_stringshare_replace(&c->name, str);
599         } else if (strcmp(key, "Multiparty") == 0) {
600                 Eina_Bool v;
601                 eldbus_message_iter_basic_get(value, &v);
602                 DBG("%s Multiparty %d", c->base.path, v);
603                 c->multiparty = v;
604         } else if (strcmp(key, "Emergency") == 0) {
605                 Eina_Bool v;
606                 eldbus_message_iter_basic_get(value, &v);
607                 DBG("%s Emergency %d", c->base.path, v);
608                 c->emergency = v;
609         } else if (strcmp(key, "StartTime") == 0) {
610                 const char *ts = NULL;
611                 time_t st, ut;
612                 double lt;
613                 eldbus_message_iter_basic_get(value, &ts);
614
615                 st = _ofono_time_parse(ts);
616                 ut = time(NULL);
617                 lt = ecore_loop_time_get();
618                 c->start_time = st - ut + lt;
619                 c->full_start_time = st;
620                 DBG("%s StartTime %f (%s)", c->base.path, c->start_time, ts);
621         } else
622                 DBG("%s %s (unused property)", c->base.path, key);
623 }
624
625 static void _call_property_changed(void *data, Eldbus_Message *msg)
626 {
627         OFono_Call *c = data;
628         Eldbus_Message_Iter *value;
629         const char *key;
630
631         if (!msg) {
632                 ERR("Could not handle message %p", msg);
633                 return;
634         }
635
636         DBG("path=%s", c->base.path);
637
638         if (!eldbus_message_arguments_get(msg, "sv", &key, &value)) {
639                 ERR("Could not get call PropertyChanged arguments");
640                 return;
641         }
642
643         _call_property_update(c, key, value);
644
645         _notify_ofono_callbacks_call_list(cbs_call_changed, c);
646 }
647
648 static void _call_disconnect_reason(void *data, Eldbus_Message *msg)
649 {
650         OFono_Call *c = data;
651         const char *reason;
652
653         if (!msg) {
654                 ERR("No message");
655                 return;
656         }
657
658         DBG("path=%s", c->base.path);
659         c->state = OFONO_CALL_STATE_DISCONNECTED;
660
661         if (!eldbus_message_arguments_get(msg, "s", &reason)) {
662                 ERR("Could not get DisconnectReason arguments");
663                 return;
664         }
665
666         _notify_ofono_callbacks_call_disconnected_list(cbs_call_disconnected,
667                                                         c, reason);
668 }
669
670 static OFono_Call *_call_common_add(OFono_Modem *m, const char *path)
671 {
672         OFono_Call *c = _call_new(path);
673         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
674         eina_hash_add(m->calls, c->base.path, c);
675
676         _bus_object_signal_listen(&c->base,
677                                         OFONO_PREFIX "VoiceCall",
678                                         "DisconnectReason",
679                                         _call_disconnect_reason, c);
680         _bus_object_signal_listen(&c->base,
681                                         OFONO_PREFIX "VoiceCall",
682                                         "PropertyChanged",
683                                         _call_property_changed, c);
684         return c;
685 }
686
687 static OFono_Call *_call_pending_add(OFono_Modem *m, const char *path,
688                                         OFono_Call_Cb_Context *ctx)
689 {
690         OFono_Call *c;
691
692         DBG("path=%s, ctx=%p", path, ctx);
693
694         c = _call_common_add(m, path);
695         c->pending_dial = ctx;
696         return c;
697 }
698
699 static void _call_add(OFono_Modem *m, const char *path, Eldbus_Message_Iter *prop)
700 {
701         OFono_Call *c;
702         Eina_Bool needs_cb_added;
703         Eldbus_Message_Iter *dict_entry;
704
705         DBG("path=%s, prop=%p", path, prop);
706
707         c = eina_hash_find(m->calls, path);
708         needs_cb_added = !c;
709         if (c)
710                 DBG("Call already exists %p (%s)", c, path);
711         else {
712                 c = _call_common_add(m, path);
713                 EINA_SAFETY_ON_NULL_RETURN(c);
714         }
715
716         while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
717                 Eldbus_Message_Iter *value;
718                 const char *key;
719
720                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
721                         ERR("Could not get arguments");
722                         return;
723                 }
724
725                 _call_property_update(c, key, value);
726         }
727
728         if (c->pending_dial) {
729                 OFono_Call_Cb_Context *ctx = c->pending_dial;
730                 if (ctx->cb)
731                         ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, c);
732                 free(ctx);
733                 c->pending_dial = NULL;
734                 needs_cb_added = EINA_TRUE;
735         }
736
737         if (needs_cb_added)
738                 _notify_ofono_callbacks_call_list(cbs_call_added, c);
739
740         _notify_ofono_callbacks_call_list(cbs_call_changed, c);
741 }
742
743 static void _call_remove(OFono_Modem *m, const char *path)
744 {
745         DBG("path=%s", path);
746         eina_hash_del_by_key(m->calls, path);
747 }
748
749 static void _call_added(void *data, Eldbus_Message *msg)
750 {
751         OFono_Modem *m = data;
752         Eldbus_Message_Iter *properties;
753         const char *path;
754
755         if (!msg) {
756                 ERR("Could not handle message %p", msg);
757                 return;
758         }
759
760         if (!eldbus_message_arguments_get(msg, "oa{sv}", &path, &properties)) {
761                 ERR("Could not get CallAdded arguments");
762                 return;
763         }
764
765         _call_add(m, path, properties);
766 }
767
768 static void _call_removed(void *data, Eldbus_Message *msg)
769 {
770         OFono_Modem *m = data;
771         const char *path;
772
773         if (!msg) {
774                 ERR("Could not handle message %p", msg);
775                 return;
776         }
777
778         if (!eldbus_message_arguments_get(msg, "o", &path)) {
779                 ERR("Could not get CallRemoved arguments");
780                 return;
781         }
782
783         _call_remove(m, path);
784 }
785
786 static OFono_Modem *_modem_selected_get(void)
787 {
788         OFono_Modem *found_path = NULL, *found_api = NULL, *m;
789         unsigned int online = 0, powered = 0;
790         Eina_Iterator *itr;
791
792         if (modem_selected)
793                 return modem_selected;
794
795         itr = eina_hash_iterator_data_new(modems);
796         EINA_ITERATOR_FOREACH(itr, m) {
797                 if (m->ignored)
798                         continue;
799
800                 if (m->online)
801                         online++;
802                 if (m->powered)
803                         powered++;
804
805                 if ((modem_path_wanted) && (!found_path)) {
806                         DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
807                         if (m->base.path == modem_path_wanted) {
808                                 found_path = m;
809                                 break;
810                         }
811                 }
812
813                 if ((!found_api) || ((!found_api->online) ||
814                                         (!found_api->powered))) {
815                         DBG("m=%#x, mask=%#x, previous=%s "
816                                 "(online=%d, powered=%d)",
817                                 m->interfaces, modem_api_mask,
818                                 found_api ? found_api->base.path : "",
819                                 found_api ? found_api->online : 0,
820                                 found_api ? found_api->powered : 0);
821                         if ((m->interfaces & modem_api_mask) == modem_api_mask)
822                                 found_api = m;
823                 }
824         }
825         eina_iterator_free(itr);
826
827         INF("found_path=%s, found_api=%s, wanted_path=%s, api_mask=%#x",
828                 found_path ? found_path->base.path : "",
829                 found_api ? found_api->base.path: "",
830                 modem_path_wanted ? modem_path_wanted : "",
831                 modem_api_mask);
832
833         if (!powered)
834                 ERR("No modems powered! Run connman or test/enable-modem");
835         if (!online)
836                 WRN("No modems online! Run connman or test/online-modem");
837
838         modem_selected = found_path ? found_path : found_api;
839         return modem_selected;
840 }
841
842 static OFono_Pending *_ofono_multiparty(const char *method,
843                                         OFono_Simple_Cb cb, const void *data)
844 {
845
846         OFono_Pending *p;
847         Eldbus_Message *msg;
848         OFono_Simple_Cb_Context *ctx = NULL;
849         OFono_Modem *m = _modem_selected_get();
850
851         EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
852
853         if (cb) {
854                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
855                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
856                 ctx->cb = cb;
857                 ctx->data = data;
858         }
859
860         msg = eldbus_message_method_call_new(
861                                 bus_id, m->base.path,
862                                 OFONO_PREFIX OFONO_VOICE_IFACE,
863                                 method);
864
865         if (!msg)
866                 goto error_no_message;
867
868         INF("%s()", method);
869         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
870
871         return p;
872
873 error_no_message:
874         if (cb)
875                 cb((void *)data, OFONO_ERROR_FAILED);
876         free(ctx);
877         return NULL;
878 }
879
880 OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb,
881                                         const void *data)
882 {
883         OFono_Simple_Cb_Context *ctx = NULL;
884         OFono_Pending *p;
885         Eldbus_Message *msg;
886
887         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
888
889         if (cb) {
890                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
891                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
892                 ctx->cb = cb;
893                 ctx->data = data;
894         }
895
896         msg = eldbus_message_method_call_new(
897                 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Hangup");
898         if (!msg)
899                 goto error;
900
901         INF("Hangup(%s)", c->base.path);
902         p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
903         return p;
904
905 error:
906         if (cb)
907                 cb((void *)data, OFONO_ERROR_FAILED);
908         free(ctx);
909         return NULL;
910 }
911
912 OFono_Pending *ofono_call_answer(OFono_Call *c, OFono_Simple_Cb cb,
913                                         const void *data)
914 {
915         OFono_Simple_Cb_Context *ctx = NULL;
916         OFono_Pending *p;
917         Eldbus_Message *msg;
918
919         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
920
921         if (cb) {
922                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
923                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
924                 ctx->cb = cb;
925                 ctx->data = data;
926         }
927
928         msg = eldbus_message_method_call_new(
929                 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Answer");
930         if (!msg)
931                 goto error;
932
933         INF("Answer(%s)", c->base.path);
934         p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
935         return p;
936
937 error:
938         if (cb)
939                 cb((void *)data, OFONO_ERROR_FAILED);
940         free(ctx);
941         return NULL;
942 }
943
944 OFono_Call_State ofono_call_state_get(const OFono_Call *c)
945 {
946         EINA_SAFETY_ON_NULL_RETURN_VAL(c, OFONO_CALL_STATE_DISCONNECTED);
947         return c->state;
948 }
949
950 const char *ofono_call_name_get(const OFono_Call *c)
951 {
952         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
953         return c->name;
954 }
955
956 const char *ofono_call_line_id_get(const OFono_Call *c)
957 {
958         EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
959         return c->line_id;
960 }
961
962 Eina_Bool ofono_call_multiparty_get(const OFono_Call *c)
963 {
964         EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
965         return c->multiparty;
966 }
967
968 double ofono_call_start_time_get(const OFono_Call *c)
969 {
970         EINA_SAFETY_ON_NULL_RETURN_VAL(c, -1.0);
971         return c->start_time;
972 }
973
974 time_t ofono_call_full_start_time_get(const OFono_Call *c)
975 {
976         EINA_SAFETY_ON_NULL_RETURN_VAL(c, 0);
977         return c->full_start_time;
978 }
979
980 static void _ofono_calls_get_reply(void *data, Eldbus_Message *msg,
981                                                 Eldbus_Pending *pending __UNUSED__)
982 {
983         Eldbus_Message_Iter *array, *dict_entry;
984         const char *err_name, *err_message;
985
986         EINA_SAFETY_ON_NULL_RETURN(data);
987         OFono_Modem *m = data;
988
989         if (!msg) {
990                 ERR("No message");
991                 return;
992         }
993
994         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
995                 ERR("Failed to get reply: %s: %s", err_name, err_message);
996                 return;
997         }
998
999         eina_hash_free_buckets(m->calls);
1000
1001         if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array)) {
1002                 ERR("Could not get calls");
1003                 return;
1004         }
1005
1006         while (eldbus_message_iter_get_and_next(array, 'r', &dict_entry)) {
1007                 Eldbus_Message_Iter *properties;
1008                 const char *path;
1009
1010                 if (!eldbus_message_iter_arguments_get(dict_entry, "oa{sv}", &path, &properties)) {
1011                         ERR("Could not get CallAdded arguments");
1012                         return;
1013                 }
1014
1015                 _call_add(m, path, properties);
1016         }
1017 }
1018
1019 static void _modem_calls_load(OFono_Modem *m)
1020 {
1021         Eldbus_Message *msg = eldbus_message_method_call_new(
1022                 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE,
1023                 "GetCalls");
1024
1025         DBG("Get calls of %s", m->base.path);
1026         _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m);
1027 }
1028
1029 static OFono_Sent_SMS *_sent_sms_new(const char *path)
1030 {
1031         OFono_Sent_SMS *sms = calloc(1, sizeof(OFono_Sent_SMS));
1032         EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
1033
1034         sms->base.path = eina_stringshare_add(path);
1035         EINA_SAFETY_ON_NULL_GOTO(sms->base.path, error_path);
1036
1037         return sms;
1038
1039 error_path:
1040         free(sms);
1041         return NULL;
1042 }
1043
1044 static void _sent_sms_free(OFono_Sent_SMS *sms)
1045 {
1046         DBG("sms=%p %s", sms, sms->base.path);
1047         eina_stringshare_del(sms->destination);
1048         eina_stringshare_del(sms->message);
1049         _bus_object_free(&sms->base);
1050 }
1051
1052 static OFono_Modem *_modem_new(const char *path)
1053 {
1054         OFono_Modem *m = calloc(1, sizeof(OFono_Modem));
1055         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
1056
1057         m->base.path = eina_stringshare_add(path);
1058         EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
1059
1060         m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free));
1061         EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls);
1062
1063         m->sent_sms = eina_hash_string_small_new(EINA_FREE_CB(_sent_sms_free));
1064         EINA_SAFETY_ON_NULL_GOTO(m->sent_sms, error_sent_sms);
1065
1066         return m;
1067
1068 error_sent_sms:
1069         eina_hash_free(m->calls);
1070 error_calls:
1071         eina_stringshare_del(m->base.path);
1072 error_path:
1073         free(m);
1074         return NULL;
1075 }
1076
1077 static void _modem_free(OFono_Modem *m)
1078 {
1079         DBG("m=%p %s", m, m->base.path);
1080
1081         if (modem_selected == m)
1082                 modem_selected = NULL;
1083
1084         eina_stringshare_del(m->name);
1085         eina_stringshare_del(m->serial);
1086         eina_stringshare_del(m->voicemail_number);
1087         eina_stringshare_del(m->serv_center_addr);
1088         eina_stringshare_del(m->msg_bearer);
1089         eina_stringshare_del(m->msg_alphabet);
1090
1091         eina_hash_free(m->calls);
1092         eina_hash_free(m->sent_sms);
1093
1094         _bus_object_free(&m->base);
1095 }
1096
1097
1098 static void _call_volume_property_update(OFono_Modem *m, const char *prop_name,
1099                                                 Eldbus_Message_Iter *iter)
1100 {
1101
1102         if (strcmp(prop_name, "Muted") == 0) {
1103                 Eina_Bool b;
1104                 eldbus_message_iter_basic_get(iter, &b);
1105                 m->muted = b;
1106                 DBG("%s Muted %d", m->base.path, m->muted);
1107         } else if (strcmp(prop_name, "SpeakerVolume") == 0) {
1108                 eldbus_message_iter_basic_get(iter, &m->speaker_volume);
1109                 DBG("%s Speaker Volume %hhu", m->base.path, m->speaker_volume);
1110         } else if (strcmp(prop_name, "MicrophoneVolume") == 0) {
1111                 eldbus_message_iter_basic_get(iter, &m->microphone_volume);
1112                 DBG("%s Microphone Volume %hhu", m->base.path, m->speaker_volume);
1113         } else
1114                 DBG("%s %s (unused property)", m->base.path, prop_name);
1115 }
1116
1117 static void _msg_waiting_property_update(OFono_Modem *m, const char *prop_name,
1118                                                 Eldbus_Message_Iter *iter)
1119 {
1120
1121         if (strcmp(prop_name, "VoicemailWaiting") == 0) {
1122                 Eina_Bool b;
1123                 eldbus_message_iter_basic_get(iter, &b);
1124                 m->voicemail_waiting = b;
1125                 DBG("%s VoicemailWaiting %d",
1126                         m->base.path, m->voicemail_waiting);
1127         } else if (strcmp(prop_name, "VoicemailMessageCount") == 0) {
1128                 eldbus_message_iter_basic_get(iter, &m->voicemail_count);
1129                 DBG("%s VoicemailMessageCount %hhu",
1130                         m->base.path, m->voicemail_count);
1131         } else if (strcmp(prop_name, "VoicemailMailboxNumber") == 0) {
1132                 const char *s;
1133                 eldbus_message_iter_basic_get(iter, &s);
1134                 eina_stringshare_replace(&(m->voicemail_number), s);
1135                 DBG("%s VoicemailMailboxNumber %s",
1136                         m->base.path, m->voicemail_number);
1137         } else
1138                 DBG("%s %s (unused property)", m->base.path, prop_name);
1139 }
1140
1141 static OFono_USSD_State _suppl_serv_state_parse(const char *s)
1142 {
1143         EINA_SAFETY_ON_NULL_RETURN_VAL(s, OFONO_USSD_STATE_IDLE);
1144         if (strcmp(s, "idle") == 0)
1145                 return OFONO_USSD_STATE_IDLE;
1146         else if (strcmp(s, "active") == 0)
1147                 return OFONO_USSD_STATE_ACTIVE;
1148         else if (strcmp(s, "user-response") == 0)
1149                 return OFONO_USSD_STATE_USER_RESPONSE;
1150
1151         ERR("unknown state: %s", s);
1152         return OFONO_USSD_STATE_IDLE;
1153 }
1154
1155 static void _suppl_serv_property_update(OFono_Modem *m, const char *prop_name,
1156                                         Eldbus_Message_Iter *iter)
1157 {
1158
1159         if (strcmp(prop_name, "State") == 0) {
1160                 const char *s;
1161                 eldbus_message_iter_basic_get(iter, &s);
1162                 m->ussd_state = _suppl_serv_state_parse(s);
1163                 DBG("%s USSD.State %d", m->base.path, m->ussd_state);
1164         } else
1165                 DBG("%s %s (unused property)", m->base.path, prop_name);
1166 }
1167
1168 static void _msg_property_update(OFono_Modem *m, const char *prop_name,
1169                                         Eldbus_Message_Iter *iter)
1170 {
1171
1172         if (strcmp(prop_name, "ServiceCenterAddress") == 0) {
1173                 const char *str;
1174                 eldbus_message_iter_arguments_get(iter, "s", &str);
1175                 DBG("%s ServiceCenterAddress %s", m->base.path, str);
1176                 eina_stringshare_replace(&(m->serv_center_addr), str);
1177         } else if (strcmp(prop_name, "UseDeliveryReports") == 0) {
1178                 Eina_Bool b;
1179                 eldbus_message_iter_arguments_get(iter, "b", &b);
1180                 m->use_delivery_reports = b;
1181                 DBG("%s UseDeliveryReports %hhu", m->base.path,
1182                         m->use_delivery_reports);
1183         } else if (strcmp(prop_name, "Bearer") == 0) {
1184                 const char *str;
1185                 eldbus_message_iter_arguments_get(iter, "s", &str);
1186                 DBG("%s Bearer %s", m->base.path, str);
1187                 eina_stringshare_replace(&(m->msg_bearer), str);
1188         } else if (strcmp(prop_name, "Alphabet") == 0) {
1189                 const char *str;
1190                 eldbus_message_iter_arguments_get(iter, "s", &str);
1191                 DBG("%s Alphabet %s", m->base.path, str);
1192                 eina_stringshare_replace(&(m->msg_alphabet), str);
1193         } else
1194                 DBG("%s %s (unused property)", m->base.path, prop_name);
1195 }
1196
1197 static void _notify_ofono_callbacks_modem_list(Eina_Inlist *list)
1198 {
1199         OFono_Callback_List_Modem_Node *node;
1200
1201         EINA_INLIST_FOREACH(list, node)
1202                 node->cb((void *) node->cb_data);
1203 }
1204
1205 static void _call_volume_property_changed(void *data, Eldbus_Message *msg)
1206 {
1207         OFono_Modem *m = data;
1208         Eldbus_Message_Iter *variant_iter;
1209         const char *prop_name;
1210
1211         if (!msg) {
1212                 ERR("Could not handle message %p", msg);
1213                 return;
1214         }
1215
1216         if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1217                 ERR("Could not get volume PropertyChanged arguments");
1218                 return;
1219         }
1220
1221         _call_volume_property_update(m, prop_name, variant_iter);
1222
1223         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1224 }
1225
1226 static void _msg_waiting_property_changed(void *data, Eldbus_Message *msg)
1227 {
1228         OFono_Modem *m = data;
1229         Eldbus_Message_Iter *variant_iter;
1230         const char *prop_name;
1231
1232         if (!msg) {
1233                 ERR("Could not handle message %p", msg);
1234                 return;
1235         }
1236
1237         if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1238                 ERR("Could not get message waiting PropertyChanged arguments");
1239                 return;
1240         }
1241
1242         _msg_waiting_property_update(m, prop_name, variant_iter);
1243
1244         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1245 }
1246
1247 static void _suppl_serv_property_changed(void *data, Eldbus_Message *msg)
1248 {
1249         OFono_Modem *m = data;
1250         Eldbus_Message_Iter *variant_iter;
1251         const char *prop_name;
1252
1253         if (!msg) {
1254                 ERR("Could not handle message %p", msg);
1255                 return;
1256         }
1257
1258         if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1259                 ERR("Could not get supplicant service PropertyChanged arguments");
1260                 return;
1261         }
1262
1263         _suppl_serv_property_update(m, prop_name, variant_iter);
1264
1265         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1266 }
1267
1268 static void _suppl_serv_notification_recv(void *data __UNUSED__,
1269                                                 Eldbus_Message *msg)
1270 {
1271         const char *s;
1272
1273         if (!msg) {
1274                 ERR("Could not handle message %p", msg);
1275                 return;
1276         }
1277
1278         if (!eldbus_message_arguments_get(msg, "s", &s)) {
1279                 ERR("Could not get supplementary respond arguments");
1280                 return;
1281         }
1282
1283         _notify_ofono_callbacks_ussd_notify_list(
1284                 cbs_ussd_notify, EINA_FALSE, s);
1285 }
1286
1287 static void _suppl_serv_request_recv(void *data __UNUSED__, Eldbus_Message *msg)
1288 {
1289         const char *s;
1290
1291         if (!msg) {
1292                 ERR("Could not handle message %p", msg);
1293                 return;
1294         }
1295
1296         if (!eldbus_message_arguments_get(msg, "s", &s)) {
1297                 ERR("Could not get supplementary service request arguments");
1298                 return;
1299         }
1300
1301         _notify_ofono_callbacks_ussd_notify_list(cbs_ussd_notify, EINA_TRUE, s);
1302 }
1303
1304 static void _msg_property_changed(void *data, Eldbus_Message *msg)
1305 {
1306         OFono_Modem *m = data;
1307         Eldbus_Message_Iter *variant_iter;
1308         const char *prop_name;
1309
1310         if (!msg) {
1311                 ERR("Could not handle message %p", msg);
1312                 return;
1313         }
1314
1315         if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1316                 ERR("Could not get message PropertyChanged arguments");
1317                 return;
1318         }
1319         _msg_property_update(m, prop_name, variant_iter);
1320
1321         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1322 }
1323
1324 static OFono_Sent_SMS_State _sent_sms_state_parse(const char *str)
1325 {
1326         if (strcmp(str, "pending") == 0)
1327                 return OFONO_SENT_SMS_STATE_PENDING;
1328         else if (strcmp(str, "failed") == 0)
1329                 return OFONO_SENT_SMS_STATE_FAILED;
1330         else if (strcmp(str, "sent") == 0)
1331                 return OFONO_SENT_SMS_STATE_SENT;
1332
1333         ERR("unknown message state: %s", str);
1334         return OFONO_SENT_SMS_STATE_FAILED;
1335 }
1336
1337 static void _sent_sms_property_update(OFono_Sent_SMS *sms, const char *key,
1338                                         Eldbus_Message_Iter *value)
1339 {
1340         if (strcmp(key, "State") == 0) {
1341                 const char *str;
1342                 OFono_Sent_SMS_State state;
1343                 eldbus_message_iter_arguments_get(value, "s", &str);;
1344                 state = _sent_sms_state_parse(str);
1345                 DBG("%s State %d %s", sms->base.path, state, str);
1346                 sms->state = state;
1347         } else
1348                 DBG("%s %s (unused property)", sms->base.path, key);
1349 }
1350
1351 static void _notify_ofono_callbacks_sent_sms(OFono_Error err,
1352                                                 OFono_Sent_SMS *sms)
1353 {
1354         OFono_Callback_List_Sent_SMS_Node *node;
1355
1356         EINA_INLIST_FOREACH(cbs_sent_sms_changed, node)
1357                 node->cb((void *) node->cb_data, err, sms);
1358 }
1359
1360 static void _sent_sms_property_changed(void *data, Eldbus_Message *msg)
1361 {
1362         OFono_Sent_SMS *sms = data;
1363         Eldbus_Message_Iter *value;
1364         const char *key;
1365
1366         if (!msg) {
1367                 ERR("Could not handle message %p", msg);
1368                 return;
1369         }
1370
1371         DBG("path=%s", sms->base.path);
1372
1373         if (!eldbus_message_arguments_get(msg, "sv", &key, &value)) {
1374                 ERR("Could not get sent sms PropertyChanged arguments");
1375                 return;
1376         }
1377
1378         _sent_sms_property_update(sms, key, value);
1379
1380         _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms);
1381 }
1382
1383 static void _notify_ofono_callbacks_incoming_sms(unsigned int sms_class,
1384                                                         time_t timestamp,
1385                                                         const char *sender,
1386                                                         const char *message)
1387 {
1388         OFono_Callback_List_Incoming_SMS_Node *node;
1389
1390         EINA_INLIST_FOREACH(cbs_incoming_sms, node) {
1391                 node->cb((void *) node->cb_data, sms_class, timestamp, sender,
1392                         message);
1393         }
1394 }
1395
1396 static void _msg_notify(unsigned int sms_class, Eldbus_Message_Iter *iter)
1397 {
1398         Eldbus_Message_Iter *info, *dict_entry;
1399         const char *message = NULL;
1400         const char *sender = NULL;
1401         const char *orig_timestamp = NULL;
1402         const char *local_timestamp = NULL;
1403         time_t timestamp;
1404
1405         EINA_SAFETY_ON_NULL_RETURN(iter);
1406
1407         if (!eldbus_message_iter_arguments_get(iter, "sa{sv}", &message, &info)) {
1408                 ERR("Could not get message notify arguments");
1409                 return;
1410         }
1411
1412         EINA_SAFETY_ON_NULL_RETURN(message);
1413         DBG("Message '%s'", message);
1414
1415         while (eldbus_message_iter_get_and_next(info, 'e', &dict_entry)) {
1416                 Eldbus_Message_Iter *value;
1417                 const char *key;
1418
1419                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1420                         ERR("Could not get ModemAdded arguments");
1421                         return;
1422                 }
1423
1424                 if (strcmp(key, "Sender") == 0) {
1425                         eldbus_message_iter_basic_get(value, &sender);
1426                         DBG("Sender %s", sender);
1427                 } else if (strcmp(key, "SentTime") == 0) {
1428                         eldbus_message_iter_basic_get(value, &orig_timestamp);
1429                         DBG("SentTime %s", orig_timestamp);
1430                 } else if (strcmp(key, "LocalSentTime") == 0) {
1431                         eldbus_message_iter_basic_get(value, &local_timestamp);
1432                         DBG("LocalSentTime %s", local_timestamp);
1433                 } else
1434                         DBG("%s (unused property)", key);
1435         }
1436
1437         EINA_SAFETY_ON_NULL_RETURN(sender);
1438         EINA_SAFETY_ON_NULL_RETURN(local_timestamp);
1439         timestamp = _ofono_time_parse(local_timestamp);
1440
1441         _notify_ofono_callbacks_incoming_sms(sms_class, timestamp, sender,
1442                                                 message);
1443 }
1444
1445 static void _msg_immediate(void *data, Eldbus_Message *msg)
1446 {
1447         OFono_Modem *m = data;
1448         Eldbus_Message_Iter *iter;
1449
1450         if (!msg) {
1451                 ERR("Could not handle message %p", msg);
1452                 return;
1453         }
1454
1455         iter = eldbus_message_iter_get(msg);
1456
1457         DBG("path=%s", m->base.path);
1458         _msg_notify(0, iter);
1459 }
1460
1461 static void _msg_incoming(void *data, Eldbus_Message *msg)
1462 {
1463         OFono_Modem *m = data;
1464         Eldbus_Message_Iter *iter;
1465
1466         iter = eldbus_message_iter_get(msg);
1467
1468         if (!iter) {
1469                 ERR("Could not handle message %p", msg);
1470                 return;
1471         }
1472
1473         DBG("path=%s", m->base.path);
1474         _msg_notify(1, iter);
1475 }
1476
1477 static OFono_Sent_SMS *_sent_sms_common_add(OFono_Modem *m, const char *path)
1478 {
1479         OFono_Sent_SMS *sms = _sent_sms_new(path);
1480         EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
1481         eina_hash_add(m->sent_sms, sms->base.path, sms);
1482
1483         _bus_object_signal_listen(&sms->base,
1484                                         OFONO_PREFIX "Message",
1485                                         "PropertyChanged",
1486                                         _sent_sms_property_changed, sms);
1487         return sms;
1488 }
1489
1490 static OFono_Sent_SMS *_sent_sms_pending_add(OFono_Modem *m, const char *path,
1491                                                 OFono_Sent_SMS_Cb_Context *ctx)
1492 {
1493         OFono_Sent_SMS *sms;
1494
1495         DBG("path=%s, ctx=%p", path, ctx);
1496
1497         sms = _sent_sms_common_add(m, path);
1498         sms->pending_send = ctx;
1499         return sms;
1500 }
1501
1502 static void _msg_add(OFono_Modem *m, const char *path, Eldbus_Message_Iter *prop)
1503 {
1504         Eldbus_Message_Iter *dict_entry;
1505         OFono_Sent_SMS *sms;
1506
1507         DBG("path=%s, prop=%p", path, prop);
1508
1509         sms = eina_hash_find(m->sent_sms, path);
1510         if (sms)
1511                 DBG("SMS already exists %p (%s)", sms, path);
1512         else {
1513                 sms = _sent_sms_common_add(m, path);
1514                 EINA_SAFETY_ON_NULL_RETURN(sms);
1515         }
1516
1517         while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1518                 Eldbus_Message_Iter *value;
1519                 const char *key;
1520
1521                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1522                         ERR("Could not get arguments");
1523                         return;
1524                 }
1525
1526                 _sent_sms_property_update(sms, key, value);
1527         }
1528
1529         if (sms->pending_send) {
1530                 OFono_Sent_SMS_Cb_Context *ctx = sms->pending_send;
1531                 sms->destination = ctx->destination;
1532                 sms->message = ctx->message;
1533                 sms->timestamp = time(NULL);
1534                 if (ctx->cb)
1535                         ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, sms);
1536                 free(ctx);
1537                 sms->pending_send = NULL;
1538         }
1539
1540         _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms);
1541 }
1542
1543 static void _msg_added(void *data, Eldbus_Message *msg)
1544 {
1545         OFono_Modem *m = data;
1546         Eldbus_Message_Iter *properties;
1547         const char *path;
1548
1549         if (!msg) {
1550                 ERR("Could not handle message %p", msg);
1551                 return;
1552         }
1553
1554         if (!eldbus_message_arguments_get(msg, "oa{sv}", &path, &properties)) {
1555                 ERR("Could not get MessageAdded arguments");
1556                 return;
1557         }
1558
1559         _msg_add(m, path, properties);
1560 }
1561
1562 static void _msg_remove(OFono_Modem *m, const char *path)
1563 {
1564         DBG("path=%s", path);
1565         eina_hash_del_by_key(m->sent_sms, path);
1566 }
1567
1568 static void _msg_removed(void *data, Eldbus_Message *msg)
1569 {
1570         OFono_Modem *m = data;
1571         const char *path;
1572
1573         if (!msg) {
1574                 ERR("Could not handle message %p", msg);
1575                 return;
1576         }
1577
1578         if (!eldbus_message_arguments_get(msg, "o", &path)) {
1579                 ERR("Could not get MessageRemoved arguments");
1580                 return;
1581         }
1582
1583         _msg_remove(m, path);
1584 }
1585
1586 static unsigned int _modem_interfaces_extract(Eldbus_Message_Iter *iter)
1587 {
1588         Eldbus_Message_Iter *array;
1589         const char* name;
1590         unsigned int interfaces = 0;
1591
1592         if (!eldbus_message_iter_arguments_get(iter, "as", &array)) {
1593                 ERR("Could not get modem interfaces arguments");
1594                 return;
1595         }
1596
1597         while (eldbus_message_iter_get_and_next(array, 's', &name)) {
1598                 const struct API_Interface_Map *itr;
1599                 size_t namelen;
1600
1601                 if (strncmp(name, OFONO_PREFIX, strlen(OFONO_PREFIX)) != 0)
1602                         continue;
1603
1604                 name += strlen(OFONO_PREFIX);
1605                 namelen = strlen(name);
1606
1607                 DBG("interface: %s", name);
1608                 for (itr = api_iface_map; itr->name != NULL; itr++) {
1609                         if ((itr->namelen == namelen) &&
1610                                 (memcmp(itr->name, name, namelen) == 0)) {
1611                                 interfaces |= itr->bit;
1612                                 break;
1613                         }
1614                 }
1615                 if (itr->name == NULL)
1616                         WRN("ignored %s", name);
1617         }
1618
1619         return interfaces;
1620 }
1621
1622 static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces)
1623 {
1624
1625         if (((m->interfaces & OFONO_API_CALL_VOL) == 0) &&
1626                 (ifaces & OFONO_API_CALL_VOL) == OFONO_API_CALL_VOL)
1627                 _ofono_call_volume_properties_get(m);
1628
1629         if (((m->interfaces & OFONO_API_MSG_WAITING) == 0) &&
1630                 (ifaces & OFONO_API_MSG_WAITING) == OFONO_API_MSG_WAITING)
1631                 _ofono_msg_waiting_properties_get(m);
1632
1633         if (((m->interfaces & OFONO_API_SUPPL_SERV) == 0) &&
1634                 (ifaces & OFONO_API_SUPPL_SERV) == OFONO_API_SUPPL_SERV)
1635                 _ofono_suppl_serv_properties_get(m);
1636
1637         if (((m->interfaces & OFONO_API_MSG) == 0) &&
1638                 (ifaces & OFONO_API_MSG) == OFONO_API_MSG)
1639                 _ofono_msg_properties_get(m);
1640 }
1641
1642 static void _modem_property_update(OFono_Modem *m, const char *key,
1643                                         Eldbus_Message_Iter *value)
1644 {
1645         if (strcmp(key, "Powered") == 0) {
1646                 Eina_Bool b;
1647                 eldbus_message_iter_basic_get(value, &b);
1648                 m->powered = b;
1649                 DBG("%s Powered %d", m->base.path, m->powered);
1650         } else if (strcmp(key, "Online") == 0) {
1651                 Eina_Bool b;
1652                 eldbus_message_iter_basic_get(value, &b);
1653                 m->online = b;
1654                 DBG("%s Online %d", m->base.path, m->online);
1655         } else if (strcmp(key, "Interfaces") == 0) {
1656                 unsigned int ifaces = _modem_interfaces_extract(value);
1657                 DBG("%s Interfaces 0x%02x", m->base.path, ifaces);
1658                 if (m->interfaces != ifaces) {
1659                         _modem_update_interfaces(m, ifaces);
1660                         m->interfaces = ifaces;
1661
1662                         if (modem_selected && modem_path_wanted &&
1663                                 modem_selected->base.path != modem_path_wanted)
1664                                 modem_selected = NULL;
1665                 }
1666         } else if (strcmp(key, "Serial") == 0) {
1667                 const char *serial;
1668                 eldbus_message_iter_basic_get(value, &serial);
1669                 DBG("%s Serial %s", m->base.path, serial);
1670                 eina_stringshare_replace(&m->serial, serial);
1671         } else if (strcmp(key, "Type") == 0) {
1672                 const char *type;
1673                 eldbus_message_iter_basic_get(value, &type);
1674                 DBG("%s Type %s", m->base.path, type);
1675
1676                 if (!modem_types)
1677                         m->ignored = EINA_FALSE;
1678                 else {
1679                         const Eina_List *n;
1680                         const char *t;
1681                         m->ignored = EINA_TRUE;
1682                         EINA_LIST_FOREACH(modem_types, n, t) {
1683                                 if (strcmp(t, type) == 0) {
1684                                         m->ignored = EINA_FALSE;
1685                                         break;
1686                                 }
1687                         }
1688                         if (m->ignored)
1689                                 INF("Modem %s type %s is ignored",
1690                                         m->base.path, type);
1691                 }
1692         } else
1693                 DBG("%s %s (unused property)", m->base.path, key);
1694 }
1695
1696 static void _ofono_call_volume_properties_get_reply(void *data,
1697                                                 Eldbus_Message *msg,
1698                                                 Eldbus_Pending *pending __UNUSED__)
1699 {
1700         OFono_Modem *m = data;
1701         Eldbus_Message_Iter *prop, *dict_entry;
1702         const char *err_name, *err_message;
1703
1704         if (!msg) {
1705                 ERR("No message");
1706                 return;
1707         }
1708
1709         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1710                 ERR("Call volume reply error %s: %s",   err_name, err_message);
1711                 return;
1712         }
1713
1714         if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1715                 ERR("Could not get call volume arguments");
1716                 return;
1717         }
1718
1719         DBG("m=%s", m->base.path);
1720         while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1721                 Eldbus_Message_Iter *value;
1722                 const char *key;
1723
1724                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1725                         ERR("Could not get arguments");
1726                         return;
1727                 }
1728                 _call_volume_property_update(m, key, value);
1729         }
1730
1731         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1732 }
1733
1734 static void _ofono_call_volume_properties_get(OFono_Modem *m)
1735 {
1736         Eldbus_Message *msg;
1737         msg = eldbus_message_method_call_new(bus_id, m->base.path,
1738                                                 OFONO_PREFIX
1739                                                 OFONO_CALL_VOL_IFACE,
1740                                                 "GetProperties");
1741         DBG("m=%s", m->base.path);
1742         EINA_SAFETY_ON_NULL_RETURN(msg);
1743
1744         _bus_object_message_send(&m->base, msg,
1745                                 _ofono_call_volume_properties_get_reply, m);
1746 }
1747
1748 static void _ofono_msg_waiting_properties_get_reply(void *data,
1749                                                 Eldbus_Message *msg,
1750                                                 Eldbus_Pending *pending __UNUSED__)
1751 {
1752         OFono_Modem *m = data;
1753         Eldbus_Message_Iter *prop, *dict_entry;
1754         const char *err_name, *err_message;
1755
1756         if (!msg) {
1757                 ERR("No message");
1758                 return;
1759         }
1760
1761         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1762                 ERR("Ofono reply error %s: %s", err_name, err_message);
1763                 return;
1764         }
1765
1766         if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1767                 ERR("Could not get message waiting properties arguments");
1768                 return;
1769         }
1770
1771         DBG("m=%s", m->base.path);
1772         while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1773                 Eldbus_Message_Iter *value;
1774                 const char *key;
1775
1776                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1777                         ERR("Could not get arguments");
1778                         return;
1779                 }
1780                 _msg_waiting_property_update(m, key, value);
1781         }
1782
1783         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1784 }
1785
1786 static void _ofono_msg_waiting_properties_get(OFono_Modem *m)
1787 {
1788         Eldbus_Message *msg;
1789         msg = eldbus_message_method_call_new(bus_id, m->base.path,
1790                                                 OFONO_PREFIX
1791                                                 OFONO_MSG_WAITING_IFACE,
1792                                                 "GetProperties");
1793         DBG("m=%s", m->base.path);
1794         EINA_SAFETY_ON_NULL_RETURN(msg);
1795
1796         _bus_object_message_send(&m->base, msg,
1797                                 _ofono_msg_waiting_properties_get_reply, m);
1798 }
1799
1800 static void _ofono_suppl_serv_properties_get_reply(void *data,
1801                                                 Eldbus_Message *msg,
1802                                                 Eldbus_Pending *pending __UNUSED__)
1803 {
1804         OFono_Modem *m = data;
1805         Eldbus_Message_Iter *prop, *dict_entry;
1806         const char *err_name, *err_message;
1807
1808         if (!msg) {
1809                 ERR("No message");
1810                 return;
1811         }
1812
1813         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1814                 ERR("SS service properties reply error %s: %s", err_name, err_message);
1815                 return;
1816         }
1817
1818         if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1819                 ERR("Could not get supplementary service properties arguments");
1820                 return;
1821         }
1822
1823         DBG("m=%s", m->base.path);
1824         while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1825                 Eldbus_Message_Iter *value;
1826                 const char *key;
1827
1828                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1829                         ERR("Could not get arguments");
1830                         return;
1831                 }
1832                 _suppl_serv_property_update(m, key, value);
1833         }
1834
1835         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1836 }
1837
1838 static void _ofono_suppl_serv_properties_get(OFono_Modem *m)
1839 {
1840         Eldbus_Message *msg;
1841         msg = eldbus_message_method_call_new(bus_id, m->base.path,
1842                                                 OFONO_PREFIX
1843                                                 OFONO_SUPPL_SERV_IFACE,
1844                                                 "GetProperties");
1845         DBG("m=%s", m->base.path);
1846         EINA_SAFETY_ON_NULL_RETURN(msg);
1847
1848         _bus_object_message_send(&m->base, msg,
1849                                 _ofono_suppl_serv_properties_get_reply, m);
1850 }
1851
1852
1853 static void _ofono_msg_properties_get_reply(void *data, Eldbus_Message *msg,
1854                                                 Eldbus_Pending *pending __UNUSED__)
1855 {
1856         OFono_Modem *m = data;
1857         Eldbus_Message_Iter *prop, *dict_entry;
1858         const char *err_name, *err_message;
1859
1860         if (!msg) {
1861                 ERR("No message");
1862                 return;
1863         }
1864
1865         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1866                 ERR("Message properties reply error %s: %s",    err_name, err_message);
1867                 return;
1868         }
1869
1870         if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1871                 ERR("Could not get message properties arguments");
1872                 return;
1873         }
1874
1875         DBG("m=%s", m->base.path);
1876         while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1877                 Eldbus_Message_Iter *value;
1878                 const char *key;
1879
1880                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1881                         ERR("Could not get arguments");
1882                         return;
1883                 }
1884                 _msg_property_update(m, key, value);
1885         }
1886
1887         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1888 }
1889
1890 static void _ofono_msg_properties_get(OFono_Modem *m)
1891 {
1892         Eldbus_Message *msg;
1893         msg = eldbus_message_method_call_new(bus_id, m->base.path,
1894                                                 OFONO_PREFIX
1895                                                 OFONO_MSG_IFACE,
1896                                                 "GetProperties");
1897         DBG("m=%s", m->base.path);
1898         EINA_SAFETY_ON_NULL_RETURN(msg);
1899
1900         _bus_object_message_send(&m->base, msg,
1901                                 _ofono_msg_properties_get_reply, m);
1902 }
1903
1904 static void _modem_add(const char *path, Eldbus_Message_Iter *prop)
1905 {
1906         OFono_Modem *m;
1907         Eldbus_Message_Iter *dict_entry;
1908
1909         DBG("path=%s", path);
1910
1911         m = eina_hash_find(modems, path);
1912         if (m) {
1913                 DBG("Modem already exists %p (%s)", m, path);
1914                 goto update_properties;
1915         }
1916
1917         m = _modem_new(path);
1918         EINA_SAFETY_ON_NULL_RETURN(m);
1919         eina_hash_add(modems, m->base.path, m);
1920
1921         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1922                                         "CallAdded", _call_added, m);
1923         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1924                                         "CallRemoved", _call_removed, m);
1925         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1926                                         "PropertyChanged",
1927                                         _call_volume_property_changed, m);
1928         _bus_object_signal_listen(&m->base,
1929                                         OFONO_PREFIX OFONO_MSG_WAITING_IFACE,
1930                                         "PropertyChanged",
1931                                         _msg_waiting_property_changed, m);
1932         _bus_object_signal_listen(&m->base,
1933                                         OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1934                                         "PropertyChanged",
1935                                         _suppl_serv_property_changed, m);
1936         _bus_object_signal_listen(&m->base,
1937                                         OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1938                                         "NotificationReceived",
1939                                         _suppl_serv_notification_recv, m);
1940         _bus_object_signal_listen(&m->base,
1941                                         OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1942                                         "RequestReceived",
1943                                         _suppl_serv_request_recv, m);
1944
1945         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1946                                         "PropertyChanged",
1947                                         _msg_property_changed, m);
1948         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1949                                         "ImmediateMessage", _msg_immediate, m);
1950         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1951                                         "IncomingMessage", _msg_incoming, m);
1952         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1953                                         "MessageAdded", _msg_added, m);
1954         _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1955                                         "MessageRemoved", _msg_removed, m);
1956
1957         /* TODO: do we need to listen to BarringActive or Forwarded? */
1958
1959         if (modem_selected && modem_path_wanted &&
1960                 modem_selected->base.path != modem_path_wanted)
1961                 modem_selected = NULL;
1962
1963 update_properties:
1964         if (!prop)
1965                 return;
1966         while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1967                 Eldbus_Message_Iter *value;
1968                 const char *key;
1969
1970                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1971                         ERR("Could not get ModemAdded arguments");
1972                         return;
1973                 }
1974
1975                 _modem_property_update(m, key, value);
1976         }
1977
1978         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1979
1980         if (m->interfaces & OFONO_API_VOICE)
1981                 _modem_calls_load(m);
1982 }
1983
1984 static void _modem_remove(const char *path)
1985 {
1986         DBG("path=%s", path);
1987         eina_hash_del_by_key(modems, path);
1988 }
1989
1990 static void _ofono_modems_get_reply(void *data __UNUSED__, Eldbus_Message *msg,
1991                                                 Eldbus_Pending *pending __UNUSED__)
1992 {
1993         Eldbus_Message_Iter *array, *dict_entry;
1994         const char *err_name, *err_message;
1995
1996         pc_get_modems = NULL;
1997
1998         if (!msg) {
1999                 ERR("No message");
2000                 return;
2001         }
2002
2003         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
2004                 ERR("Failed to get modems: %s: %s", err_name, err_message);
2005                 return;
2006         }
2007
2008         EINA_SAFETY_ON_NULL_RETURN(modems);
2009         eina_hash_free_buckets(modems);
2010
2011         if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array)) {
2012                 ERR("Could not get modems");
2013                 return;
2014         }
2015
2016         while (eldbus_message_iter_get_and_next(array, 'r', &dict_entry)) {
2017                 Eldbus_Message_Iter *properties;
2018                 const char *path;
2019
2020                 if (!eldbus_message_iter_arguments_get(dict_entry, "oa{sv}", &path, &properties)) {
2021                         ERR("Could not get ModemAdded arguments");
2022                         return;
2023                 }
2024
2025                 _modem_add(path, properties);
2026         }
2027
2028         if (!ofono_voice_is_online()) {
2029                 ofono_powered_set(EINA_TRUE, NULL, NULL);
2030                 return;
2031         }
2032 }
2033
2034 static void _modem_added(void *data __UNUSED__, Eldbus_Message *msg)
2035 {
2036         Eldbus_Message_Iter *properties;
2037         const char *path;
2038
2039         if (!msg) {
2040                 ERR("Could not handle message %p", msg);
2041                 return;
2042         }
2043
2044         if (!eldbus_message_arguments_get(msg, "sa{sv}", &path, &properties)) {
2045                 ERR("Could not get ModemAdded arguments");
2046                 return;
2047         }
2048
2049         _modem_add(path, properties);
2050 }
2051
2052 static void _modem_removed(void *data __UNUSED__, Eldbus_Message *msg)
2053 {
2054         const char *path;
2055
2056         if (!msg) {
2057                 ERR("Could not handle message %p", msg);
2058                 return;
2059         }
2060
2061         if (!eldbus_message_arguments_get(msg, "o", &path)) {
2062                 ERR("Could not get ModemRemoved arguments");
2063                 return;
2064         }
2065
2066         _modem_remove(path);
2067 }
2068
2069 static void _modem_property_changed(void *data __UNUSED__, Eldbus_Message *msg)
2070 {
2071         const char *path;
2072         OFono_Modem *m;
2073         Eldbus_Message_Iter *value;
2074         const char *key;
2075
2076         if (!msg) {
2077                 ERR("Could not handle message %p", msg);
2078                 return;
2079         }
2080
2081         path = eldbus_message_path_get(msg);
2082         DBG("path=%s", path);
2083
2084         m = eina_hash_find(modems, path);
2085         if (!m) {
2086                 DBG("Modem is unknown (%s)", path);
2087                 return;
2088         }
2089
2090         if (!eldbus_message_arguments_get(msg, "sv", &key, &value)) {
2091                 ERR("Could not get modem PropertyChanged arguments");
2092                 return;
2093         }
2094
2095         _modem_property_update(m, key, value);
2096
2097         _notify_ofono_callbacks_modem_list(cbs_modem_changed);
2098 }
2099
2100 static void _modems_load(void)
2101 {
2102         Eldbus_Message *msg = eldbus_message_method_call_new(
2103                 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
2104
2105         if (pc_get_modems)
2106                 eldbus_pending_cancel(pc_get_modems);
2107
2108         DBG("Get modems");
2109         pc_get_modems = eldbus_connection_send(
2110                 bus_conn, msg, _ofono_modems_get_reply, NULL, -1);
2111 }
2112
2113 static void _ofono_connected(const char *id)
2114 {
2115         free(bus_id);
2116         bus_id = strdup(id);
2117
2118         sig_modem_added = eldbus_signal_handler_add(
2119                 bus_conn, bus_id, "/",
2120                 OFONO_PREFIX OFONO_MANAGER_IFACE,
2121                 "ModemAdded",
2122                 _modem_added, NULL);
2123
2124         sig_modem_removed = eldbus_signal_handler_add(
2125                 bus_conn, bus_id, "/",
2126                 OFONO_PREFIX OFONO_MANAGER_IFACE,
2127                 "ModemRemoved",
2128                 _modem_removed, NULL);
2129
2130         sig_modem_prop_changed = eldbus_signal_handler_add(
2131                 bus_conn, bus_id, NULL,
2132                 OFONO_PREFIX OFONO_MODEM_IFACE,
2133                 "PropertyChanged",
2134                 _modem_property_changed, NULL);
2135
2136         _modems_load();
2137
2138         _notify_ofono_callbacks_modem_list(cbs_modem_connected);
2139 }
2140
2141 static void _ofono_disconnected(void)
2142 {
2143         eina_hash_free_buckets(modems);
2144
2145         if (sig_modem_added) {
2146                 eldbus_signal_handler_del(sig_modem_added);
2147                 sig_modem_added = NULL;
2148         }
2149
2150         if (sig_modem_removed) {
2151                 eldbus_signal_handler_del(sig_modem_removed);
2152                 sig_modem_removed = NULL;
2153         }
2154
2155         if (sig_modem_prop_changed) {
2156                 eldbus_signal_handler_del(sig_modem_prop_changed);
2157                 sig_modem_prop_changed = NULL;
2158         }
2159
2160         if (bus_id) {
2161                 _notify_ofono_callbacks_modem_list(cbs_modem_disconnected);
2162                 free(bus_id);
2163                 bus_id = NULL;
2164         }
2165 }
2166
2167 static void _name_owner_changed(void *data __UNUSED__, Eldbus_Message *msg)
2168 {
2169         const char *name, *from, *to;
2170
2171         if (!eldbus_message_arguments_get(msg, "sss", &name, &from, &to)) {
2172                 ERR("Could not get NameOwnerChanged arguments");
2173                 return;
2174         }
2175
2176         if (strcmp(name, bus_name) != 0)
2177                 return;
2178
2179         DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
2180
2181         if (from[0] == '\0' && to[0] != '\0') {
2182                 INF("oFono appeared as %s", to);
2183                 _ofono_connected(to);
2184         } else if (from[0] != '\0' && to[0] == '\0') {
2185                 INF("oFono disappeared from %s", from);
2186                 _ofono_disconnected();
2187         }
2188 }
2189
2190 static void _ofono_get_name_owner(void *data __UNUSED__, Eldbus_Message *msg,
2191                                                 Eldbus_Pending *pending __UNUSED__)
2192 {
2193         const char *id, *err_name, *err_message;
2194
2195         if (!msg) {
2196                 ERR("No message");
2197                 return;
2198         }
2199
2200         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
2201                 ERR("Failed to get name owner: %s: %s", err_name, err_message);
2202                 return;
2203         }
2204
2205         if (!eldbus_message_arguments_get(msg, "s", &id)) {
2206                 ERR("Could not get arguments");
2207                 return;
2208         }
2209
2210         if (!id || id[0] == '\0') {
2211                 ERR("No name owner fo %s!", bus_name);
2212                 return;
2213         }
2214
2215         INF("oFono bus id: %s", id);
2216         _ofono_connected(id);
2217 }
2218
2219 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
2220                                         const char *new, OFono_Simple_Cb cb,
2221                                         const void *data)
2222 {
2223         OFono_Simple_Cb_Context *ctx = NULL;
2224         OFono_Error err = OFONO_ERROR_OFFLINE;
2225         OFono_Pending *p;
2226         Eldbus_Message *msg;
2227         OFono_Modem *m = _modem_selected_get();
2228         EINA_SAFETY_ON_NULL_GOTO(m, error);
2229         EINA_SAFETY_ON_NULL_GOTO(what, error);
2230         EINA_SAFETY_ON_NULL_GOTO(old, error);
2231         EINA_SAFETY_ON_NULL_GOTO(new, error);
2232
2233         if ((m->interfaces & OFONO_API_SIM) == 0)
2234                 goto error;
2235         err = OFONO_ERROR_FAILED;
2236
2237         if (cb) {
2238                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2239                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2240                 ctx->cb = cb;
2241                 ctx->data = data;
2242         }
2243
2244         msg = eldbus_message_method_call_new(
2245                 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
2246                 "ChangePin");
2247         if (!msg)
2248                 goto error;
2249
2250         if (!eldbus_message_arguments_append(msg, "sss", what, old, new))
2251                 goto error_message;
2252
2253         INF("ChangePin(%s, %s, %s)", what, old, new);
2254         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2255         return p;
2256
2257 error_message:
2258         eldbus_message_unref(msg);
2259 error:
2260         if (cb)
2261                 cb((void *)data, err);
2262         free(ctx);
2263         return NULL;
2264 }
2265
2266 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
2267                                         const char *new, OFono_Simple_Cb cb,
2268                                         const void *data)
2269 {
2270         OFono_Simple_Cb_Context *ctx = NULL;
2271         OFono_Error err = OFONO_ERROR_OFFLINE;
2272         OFono_Pending *p;
2273         Eldbus_Message *msg;
2274         OFono_Modem *m = _modem_selected_get();
2275         EINA_SAFETY_ON_NULL_GOTO(m, error);
2276         EINA_SAFETY_ON_NULL_GOTO(what, error);
2277         EINA_SAFETY_ON_NULL_GOTO(puk, error);
2278         EINA_SAFETY_ON_NULL_GOTO(new, error);
2279
2280         if ((m->interfaces & OFONO_API_SIM) == 0)
2281                 goto error;
2282         err = OFONO_ERROR_FAILED;
2283
2284         if (cb) {
2285                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2286                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2287                 ctx->cb = cb;
2288                 ctx->data = data;
2289         }
2290
2291         msg = eldbus_message_method_call_new(
2292                 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
2293         if (!msg)
2294                 goto error;
2295
2296         if (!eldbus_message_arguments_append(msg, "sss", what, puk, new))
2297                 goto error_message;
2298
2299         INF("ResetPin(%s, %s, %s)", what, puk, new);
2300         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2301         return p;
2302
2303 error_message:
2304         eldbus_message_unref(msg);
2305 error:
2306         if (cb)
2307                 cb((void *)data, err);
2308         free(ctx);
2309         return NULL;
2310 }
2311
2312 static OFono_Pending *_ofono_modem_property_set(const char *property,
2313                                                 int type,
2314                                                 void *value,
2315                                                 OFono_Simple_Cb cb,
2316                                                 const void *data)
2317 {
2318         OFono_Pending *p;
2319         OFono_Simple_Cb_Context *ctx = NULL;
2320         Eldbus_Message *msg;
2321         Eldbus_Message_Iter *iter, *variant;
2322         OFono_Modem *found_path = NULL, *found_hfp = NULL, *m;
2323         Eina_Iterator *itr;
2324
2325         if (modem_selected)
2326                 m = modem_selected;
2327         else {
2328                 itr = eina_hash_iterator_data_new(modems);
2329                 EINA_ITERATOR_FOREACH(itr, m) {
2330                         if (m->ignored)
2331                                 continue;
2332
2333                     if ((modem_path_wanted) && (!found_path)) {
2334                                 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
2335                                 if (m->base.path == modem_path_wanted) {
2336                                         found_path = m;
2337                                         break;
2338                                 }
2339                         }
2340
2341                         if (!found_hfp) {
2342                                 DBG("m=%#x, mask=%#x, previous=%s "
2343                                         "(online=%d, powered=%d)",
2344                                         m->interfaces, modem_api_mask,
2345                                         found_hfp ? found_hfp->base.path : "",
2346                                         found_hfp ? found_hfp->online : 0,
2347                                         found_hfp ? found_hfp->powered : 0);
2348                                         if (strncmp(m->base.path, "/hfp", 4) == 0)
2349                                                 found_hfp = m;
2350                         }
2351                 }
2352                 eina_iterator_free(itr);
2353                 m = found_path ? found_path : found_hfp;
2354         }
2355
2356         if (!m)
2357                 return NULL;
2358
2359         EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2360
2361         if (cb) {
2362                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2363                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2364                 ctx->cb = cb;
2365                 ctx->data = data;
2366         }
2367
2368         msg = eldbus_message_method_call_new(bus_id, m->base.path,
2369                                                                                 OFONO_PREFIX OFONO_MODEM_IFACE,
2370                                                                                 "SetProperty");
2371         if (!msg)
2372                 goto error_no_dbus_message;
2373
2374         if (!eldbus_message_arguments_append(msg, "s", property))
2375                 goto error_message_args;
2376
2377         iter = eldbus_message_iter_get(msg);
2378
2379         variant = eldbus_message_iter_container_new(iter, 'v', (const char*) &type);
2380
2381         if (!variant)
2382                 goto error_message_args;
2383
2384         if (strcmp(property, "Powered") == 0) {
2385                 if (!eldbus_message_iter_basic_append(variant, type, *(Eina_Bool *) value) ||
2386                         !eldbus_message_iter_container_close(iter, variant)) {
2387                         goto error_message_args;
2388                 }
2389         } else {
2390                 ERR("Unsupported property: %s", property);
2391         }
2392
2393         INF("%s.SetProperty(%s)", OFONO_MODEM_IFACE, property);
2394         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2395         return p;
2396
2397 error_message_args:
2398         eldbus_message_unref(msg);
2399
2400 error_no_dbus_message:
2401         if (cb)
2402                 cb((void *)data, OFONO_ERROR_FAILED);
2403         free(ctx);
2404         return NULL;
2405 }
2406
2407 OFono_Pending *ofono_powered_set(Eina_Bool powered, OFono_Simple_Cb cb,
2408                                 const void *data)
2409 {
2410         Eina_Bool dbus_powered = !!powered;
2411
2412         return  _ofono_modem_property_set("Powered", 'b',
2413                 &dbus_powered, cb, data);
2414 }
2415
2416 Eina_Bool ofono_powered_get(void)
2417 {
2418         OFono_Modem *m = _modem_selected_get();
2419         EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
2420         return m->powered;
2421 }
2422
2423 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
2424                                         Eldbus_Message_Iter *itr)
2425 {
2426         const char *ussd_response;
2427
2428         eldbus_message_iter_basic_get(itr, &ussd_response);
2429         EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
2430         return strdup(ussd_response);
2431 }
2432
2433 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
2434                                                 Eldbus_Message_Iter *dict)
2435 {
2436         Eldbus_Message_Iter *dict_entry;
2437
2438         while (eldbus_message_iter_get_and_next(dict, 'e', &dict_entry)) {
2439                 Eldbus_Message_Iter *value;
2440                 const char *key;
2441
2442                 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
2443                         ERR("Could not get ss init dictionary arguments");
2444                         return;
2445                 }
2446
2447                 eina_strbuf_append_printf(buf, "&nbsp;&nbsp;&nbsp;%s=%s<br>",
2448                                                 key, value);
2449         }
2450 }
2451
2452 static char *_ss_initiate_convert_call1(const char *type, Eldbus_Message_Iter *itr)
2453 {
2454         Eldbus_Message_Iter *array, *dict, *entry;
2455         const char *ss_op, *service;
2456         Eina_Strbuf *buf;
2457         char *str;
2458
2459         if (!eldbus_message_iter_arguments_get(itr, "(ssa{sv})", &array)) {
2460                 ERR("Could not get call1 array");
2461                 return NULL;
2462         }
2463
2464         if (!eldbus_message_iter_arguments_get(array, "ssa{sv}", &ss_op, &service, &dict)) {
2465                 ERR("Could not get call1 arguments");
2466                 return NULL;
2467         }
2468
2469         EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2470         EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
2471
2472         if (!eldbus_message_iter_get_and_next(array, 'e', &entry)){
2473                 ERR("Missing %s information", type);
2474                 return NULL;
2475         }
2476
2477         buf = eina_strbuf_new();
2478         eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
2479                                         type, ss_op, service);
2480
2481         _ss_initiate_cb_dict_convert(buf, &dict);
2482
2483         str = eina_strbuf_string_steal(buf);
2484         eina_strbuf_free(buf);
2485         return str;
2486 }
2487
2488 static char *_ss_initiate_convert_call_waiting(const char *type,
2489                                                 Eldbus_Message_Iter *itr)
2490 {
2491         Eldbus_Message_Iter *array, *dict;
2492         const char *ss_op;
2493         Eina_Strbuf *buf;
2494         char *str;
2495
2496         if (!eldbus_message_iter_arguments_get(itr, "(sa{sv})", &array)) {
2497                 ERR("Could not get call waiting array");
2498                 return NULL;
2499         }
2500
2501         if (!eldbus_message_iter_arguments_get(array, "sa{sv}", &ss_op, &dict)) {
2502                 ERR("Could not get CallWaiting arguments");
2503                 return NULL;
2504         }
2505
2506         EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2507
2508         buf = eina_strbuf_new();
2509         eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
2510                                         type, ss_op);
2511
2512         _ss_initiate_cb_dict_convert(buf, &dict);
2513
2514         str = eina_strbuf_string_steal(buf);
2515         eina_strbuf_free(buf);
2516         return str;
2517 }
2518
2519 static char *_ss_initiate_convert_call2(const char *type,
2520                                                 Eldbus_Message_Iter *itr)
2521 {
2522         Eldbus_Message_Iter *array;
2523         const char *ss_op, *status;
2524         Eina_Strbuf *buf;
2525         char *str;
2526
2527         if (!eldbus_message_iter_arguments_get(itr, "(ss)", &array)) {
2528                 ERR("Could not get call2 array");
2529                 return NULL;
2530         }
2531
2532         if (!eldbus_message_iter_arguments_get(array, "ss", &ss_op, &status)) {
2533                 ERR("Could not get call2 arguments");
2534                 return NULL;
2535         }
2536
2537         EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
2538
2539         buf = eina_strbuf_new();
2540         eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
2541                                         type, ss_op, status);
2542
2543         str = eina_strbuf_string_steal(buf);
2544         eina_strbuf_free(buf);
2545         return str;
2546 }
2547
2548 static const struct SS_Initiate_Convert_Map {
2549         const char *type;
2550         size_t typelen;
2551         char *(*convert)(const char *type, Eldbus_Message_Iter *itr);
2552 } ss_initiate_convert_map[] = {
2553 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
2554         MAP("USSD", _ss_initiate_convert_ussd),
2555         MAP("CallBarring", _ss_initiate_convert_call1),
2556         MAP("CallForwarding", _ss_initiate_convert_call1),
2557         MAP("CallWaiting", _ss_initiate_convert_call_waiting),
2558         MAP("CallingLinePresentation", _ss_initiate_convert_call2),
2559         MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
2560         MAP("CallingLineRestriction", _ss_initiate_convert_call2),
2561         MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
2562 #undef MAP
2563         {NULL, 0, NULL}
2564 };
2565
2566 static char *_ss_initiate_convert(Eldbus_Message *msg)
2567 {
2568         Eldbus_Message_Iter *variant;
2569         const struct SS_Initiate_Convert_Map *citr;
2570         const char *type = NULL;
2571         size_t typelen;
2572
2573         if (!eldbus_message_arguments_get(msg, "sv", &type, &variant)) {
2574                 ERR("Couldn't get supplementary service nitiate arguments");
2575                 goto error;
2576         }
2577         DBG("SupplementaryServices.Initiate type: %s", type);
2578
2579         typelen = strlen(type);
2580         for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
2581                 if ((citr->typelen == typelen) &&
2582                         (memcmp(citr->type, type, typelen) == 0)) {
2583                         return citr->convert(type, &variant);
2584                 }
2585         }
2586         ERR("Could not convert SupplementaryServices.Initiate type %s", type);
2587
2588 error:
2589         return NULL;
2590 }
2591
2592 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
2593 {
2594         OFono_String_Cb_Context *ctx = NULL;
2595         OFono_Error err = OFONO_ERROR_OFFLINE;
2596         OFono_Pending *p;
2597         Eldbus_Message *msg;
2598         OFono_Modem *m = _modem_selected_get();
2599         EINA_SAFETY_ON_NULL_GOTO(m, error);
2600         EINA_SAFETY_ON_NULL_GOTO(command, error);
2601
2602         if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2603                 goto error;
2604         err = OFONO_ERROR_FAILED;
2605
2606         ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2607         EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2608         ctx->cb = cb;
2609         ctx->data = data;
2610         ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2611         ctx->convert = _ss_initiate_convert;
2612
2613         msg = eldbus_message_method_call_new(
2614                 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2615                 "Initiate");
2616         if (!msg)
2617                 goto error;
2618
2619         if (!eldbus_message_arguments_append(msg, "s", command))
2620                 goto error_message;
2621
2622         INF("SupplementaryServices.Initiate(%s)", command);
2623         p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2624         return p;
2625
2626 error_message:
2627         eldbus_message_unref(msg);
2628 error:
2629         if (cb)
2630                 cb((void *)data, err, NULL);
2631         free(ctx);
2632         return NULL;
2633 }
2634
2635 static char *_ussd_respond_convert(Eldbus_Message *msg)
2636 {
2637         const char *s;
2638
2639         if (!msg) {
2640                 ERR("Could not handle message %p", msg);
2641                 return NULL;
2642         }
2643
2644         if (!eldbus_message_arguments_get(msg, "s", &s)) {
2645                 ERR("Could not get ussd respond arguments");
2646                 return NULL;
2647         }
2648
2649         EINA_SAFETY_ON_NULL_RETURN_VAL(s, NULL);
2650         return strdup(s);
2651 }
2652
2653 OFono_Pending *ofono_ussd_respond(const char *string,
2654                                         OFono_String_Cb cb, const void *data)
2655 {
2656         OFono_String_Cb_Context *ctx = NULL;
2657         OFono_Error err = OFONO_ERROR_OFFLINE;
2658         OFono_Pending *p;
2659         Eldbus_Message *msg;
2660         OFono_Modem *m = _modem_selected_get();
2661         EINA_SAFETY_ON_NULL_GOTO(m, error);
2662         EINA_SAFETY_ON_NULL_GOTO(string, error);
2663
2664         if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2665                 goto error;
2666         err = OFONO_ERROR_FAILED;
2667
2668         ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2669         EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2670         ctx->cb = cb;
2671         ctx->data = data;
2672         ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2673         ctx->convert = _ussd_respond_convert;
2674
2675         msg = eldbus_message_method_call_new(
2676                 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2677                 "Respond");
2678         if (!msg)
2679                 goto error;
2680
2681         if (!eldbus_message_arguments_append(msg, "s", string))
2682                 goto error_message;
2683
2684         INF("SupplementaryServices.Respond(%s)", string);
2685         p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2686         return p;
2687
2688 error_message:
2689         eldbus_message_unref(msg);
2690 error:
2691         if (cb)
2692                 cb((void *)data, err, NULL);
2693         free(ctx);
2694         return NULL;
2695 }
2696
2697 OFono_Pending *ofono_ussd_cancel(OFono_Simple_Cb cb, const void *data)
2698 {
2699         return _ofono_simple_do(OFONO_API_SUPPL_SERV, "Cancel", cb, data);
2700 }
2701
2702 static void _ofono_dial_reply(void *data, Eldbus_Message *msg,
2703                                                 Eldbus_Pending *pending __UNUSED__)
2704 {
2705         OFono_Call_Cb_Context *ctx = data;
2706         OFono_Call *c = NULL;
2707         OFono_Error oe = OFONO_ERROR_NONE;
2708         const char *err_name, *err_message;
2709
2710         EINA_SAFETY_ON_NULL_RETURN(data);
2711
2712         if (!msg) {
2713                 ERR("No message");
2714                 oe = OFONO_ERROR_FAILED;
2715         }
2716
2717         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
2718                 ERR("Ofono reply error %s: %s", err_name, err_message);
2719                 oe = _ofono_error_parse(err_name);
2720         } else {
2721                 const char *path;
2722                 if (!eldbus_message_arguments_get(msg, "o", &path)) {
2723                         ERR("Could not get Dial reply");
2724                         oe = OFONO_ERROR_FAILED;
2725                 } else {
2726                         c = eina_hash_find(ctx->modem->calls, path);
2727                         DBG("path=%s, existing call=%p", path, c);
2728                         if (!c) {
2729                                 c = _call_pending_add(ctx->modem, path, ctx);
2730                                 if (c) {
2731                                         /* ctx->cb will be dispatched on
2732                                          * CallAdded signal handler.
2733                                          */
2734                                         return;
2735                                 }
2736                         }
2737
2738                         ERR("Could not find call %s", path);
2739                         oe = OFONO_ERROR_FAILED;
2740                 }
2741         }
2742
2743         if (ctx->cb)
2744                 ctx->cb((void *)ctx->data, oe, c);
2745
2746         free(ctx);
2747 }
2748
2749 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
2750                                 OFono_Call_Cb cb, const void *data)
2751 {
2752         OFono_Call_Cb_Context *ctx = NULL;
2753         OFono_Error err = OFONO_ERROR_OFFLINE;
2754         OFono_Pending *p;
2755         Eldbus_Message *msg;
2756         OFono_Modem *m = _modem_selected_get();
2757         EINA_SAFETY_ON_NULL_GOTO(m, error);
2758
2759
2760         if ((m->interfaces & OFONO_API_VOICE) == 0)
2761                 goto error;
2762         err = OFONO_ERROR_FAILED;
2763
2764         if (!hide_callerid)
2765                 hide_callerid = "";
2766
2767         ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
2768         EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2769         ctx->cb = cb;
2770         ctx->data = data;
2771         ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
2772         ctx->modem = m;
2773
2774         msg = eldbus_message_method_call_new(
2775                 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
2776         if (!msg)
2777                 goto error;
2778
2779         if (!eldbus_message_arguments_append(msg, "ss", number, hide_callerid))
2780                 goto error_message;
2781
2782         INF("Dial(%s, %s)", number, hide_callerid);
2783         p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
2784         return p;
2785
2786 error_message:
2787         eldbus_message_unref(msg);
2788 error:
2789         if (cb)
2790                 cb((void *)data, err, NULL);
2791         free(ctx);
2792         return NULL;
2793 }
2794
2795 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
2796                                         OFono_Simple_Cb cb, const void *data)
2797 {
2798         OFono_Simple_Cb_Context *ctx = NULL;
2799         OFono_Error err = OFONO_ERROR_OFFLINE;
2800         OFono_Pending *p;
2801         Eldbus_Message *msg;
2802         char iface[128] = "";
2803         const struct API_Interface_Map *itr;
2804         OFono_Modem *m = _modem_selected_get();
2805         EINA_SAFETY_ON_NULL_GOTO(m, error);
2806         EINA_SAFETY_ON_NULL_GOTO(method, error);
2807
2808         if ((m->interfaces & api) == 0)
2809                 goto error;
2810         err = OFONO_ERROR_FAILED;
2811
2812         for (itr = api_iface_map; itr->name != NULL; itr++) {
2813                 if (itr->bit == api) {
2814                         snprintf(iface, sizeof(iface), "%s%s",
2815                                         OFONO_PREFIX, itr->name);
2816                         break;
2817                 }
2818         }
2819         if (iface[0] == '\0') {
2820                 ERR("Could not map api %d to interface name!", api);
2821                 goto error;
2822         }
2823
2824         if (cb) {
2825                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2826                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2827                 ctx->cb = cb;
2828                 ctx->data = data;
2829         }
2830
2831         msg = eldbus_message_method_call_new(bus_id, m->base.path, iface, method);
2832         if (!msg)
2833                 goto error;
2834
2835         INF("%s.%s()", iface, method);
2836         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2837         return p;
2838
2839 error:
2840         if (cb)
2841                 cb((void *)data, err);
2842         free(ctx);
2843         return NULL;
2844 }
2845
2846 OFono_Pending *ofono_transfer(OFono_Simple_Cb cb, const void *data)
2847 {
2848         return _ofono_simple_do(OFONO_API_VOICE, "Transfer", cb, data);
2849 }
2850
2851 OFono_Pending *ofono_swap_calls(OFono_Simple_Cb cb, const void *data)
2852 {
2853         return _ofono_simple_do(OFONO_API_VOICE, "SwapCalls", cb, data);
2854 }
2855
2856 OFono_Pending *ofono_release_and_answer(OFono_Simple_Cb cb, const void *data)
2857 {
2858         return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndAnswer", cb, data);
2859 }
2860
2861 OFono_Pending *ofono_release_and_swap(OFono_Simple_Cb cb, const void *data)
2862 {
2863         return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndSwap", cb, data);
2864 }
2865
2866 OFono_Pending *ofono_hold_and_answer(OFono_Simple_Cb cb, const void *data)
2867 {
2868         return _ofono_simple_do(OFONO_API_VOICE, "HoldAndAnswer", cb, data);
2869 }
2870
2871 OFono_Pending *ofono_hangup_all(OFono_Simple_Cb cb, const void *data)
2872 {
2873         return _ofono_simple_do(OFONO_API_VOICE, "HangupAll", cb, data);
2874 }
2875
2876 const char *ofono_modem_serial_get(void)
2877 {
2878         OFono_Modem *m = _modem_selected_get();
2879         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
2880         return m->serial;
2881 }
2882
2883 void ofono_modem_api_require(const char *spec)
2884 {
2885         unsigned int api_mask = 0;
2886         const char *name = spec;
2887
2888         EINA_SAFETY_ON_NULL_RETURN(spec);
2889
2890         do {
2891                 const struct API_Interface_Map *itr;
2892                 const char *p;
2893                 unsigned int namelen;
2894
2895                 p = strchr(name, ',');
2896                 if (p)
2897                         namelen = p - name;
2898                 else
2899                         namelen = strlen(name);
2900
2901                 for (itr = api_iface_map; itr->name != NULL; itr++) {
2902                         if ((itr->namelen == namelen) &&
2903                                 (memcmp(itr->name, name, namelen) == 0)) {
2904                                 api_mask |= itr->bit;
2905                                 break;
2906                         }
2907                 }
2908                 if (itr->name == NULL)
2909                         WRN("Unknown oFono API: %.*s", namelen, name);
2910
2911                 if (p)
2912                         name = p + 1;
2913                 else
2914                         name = NULL;
2915         } while (name);
2916
2917         if (api_mask)
2918                 DBG("API parsed: '%s' = %#x", spec, api_mask);
2919         else {
2920                 ERR("Could not parse API: %s", spec);
2921                 return;
2922         }
2923
2924         if (modem_api_mask == api_mask)
2925                 return;
2926         modem_api_mask = api_mask;
2927         modem_selected = NULL;
2928 }
2929
2930 void ofono_modem_api_list(FILE *fp, const char *prefix, const char *suffix)
2931 {
2932         const struct API_Interface_Map *itr;
2933         for (itr = api_iface_map; itr->name != NULL; itr++)
2934                 fprintf(fp, "%s%s%s", prefix, itr->name, suffix);
2935 }
2936
2937 void ofono_modem_type_require(const char *spec)
2938 {
2939         Eina_List *lst = NULL;
2940         const char *name = spec;
2941
2942         EINA_SAFETY_ON_NULL_RETURN(spec);
2943
2944         do {
2945                 const char **itr;
2946                 const char *p;
2947                 unsigned int namelen;
2948
2949                 p = strchr(name, ',');
2950                 if (p)
2951                         namelen = p - name;
2952                 else
2953                         namelen = strlen(name);
2954
2955                 for (itr = known_modem_types; *itr != NULL; itr++) {
2956                         unsigned int itrlen = strlen(*itr);
2957                         if ((itrlen == namelen) &&
2958                                 (memcmp(*itr, name, namelen) == 0)) {
2959                                 lst = eina_list_append(lst, *itr);
2960                                 break;
2961                         }
2962                 }
2963                 if (*itr == NULL)
2964                         WRN("Unknown oFono type: %.*s", namelen, name);
2965
2966                 if (p)
2967                         name = p + 1;
2968                 else
2969                         name = NULL;
2970         } while (name);
2971
2972         if (lst)
2973                 DBG("Type parsed: '%s'", spec);
2974         else {
2975                 ERR("Could not parse type: %s", spec);
2976                 return;
2977         }
2978
2979         eina_list_free(modem_types);
2980         modem_types = lst;
2981         modem_selected = NULL;
2982 }
2983
2984 void ofono_modem_type_list(FILE *fp, const char *prefix, const char *suffix)
2985 {
2986         const char **itr;
2987         for (itr = known_modem_types; *itr != NULL; itr++)
2988                 fprintf(fp, "%s%s%s", prefix, *itr, suffix);
2989 }
2990
2991 void ofono_modem_path_wanted_set(const char *path)
2992 {
2993         if (eina_stringshare_replace(&modem_path_wanted, path))
2994                 modem_selected = NULL;
2995 }
2996
2997 unsigned int ofono_modem_api_get(void)
2998 {
2999         OFono_Modem *m = _modem_selected_get();
3000         EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3001         return m->interfaces;
3002 }
3003
3004 Eina_Bool ofono_init(void)
3005 {
3006         tzset();
3007
3008         if (!elm_need_eldbus()) {
3009                 CRITICAL("Elementary does not support DBus.");
3010                 return EINA_FALSE;
3011         }
3012
3013         bus_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
3014         if (!bus_conn) {
3015                 CRITICAL("Could not get DBus System Bus");
3016                 return EINA_FALSE;
3017         }
3018
3019         modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
3020         EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
3021
3022         eldbus_signal_handler_add(bus_conn, ELDBUS_FDO_BUS, ELDBUS_FDO_PATH,
3023                                         ELDBUS_FDO_INTERFACE,
3024                                         "NameOwnerChanged",
3025                                         _name_owner_changed, NULL);
3026
3027         eldbus_name_owner_get(bus_conn, bus_name, _ofono_get_name_owner, NULL);
3028
3029         return EINA_TRUE;
3030 }
3031
3032 void ofono_shutdown(void)
3033 {
3034         if (pc_get_modems) {
3035                 eldbus_pending_cancel(pc_get_modems);
3036                 pc_get_modems = NULL;
3037         }
3038
3039         _ofono_disconnected();
3040         eina_stringshare_replace(&modem_path_wanted, NULL);
3041
3042         eina_hash_free(modems);
3043         modems = NULL;
3044
3045         eina_list_free(modem_types);
3046 }
3047
3048 static OFono_Pending *_ofono_call_volume_property_set(const char *property,
3049                                                 int type,
3050                                                 void *value,
3051                                                 OFono_Simple_Cb cb,
3052                                                 const void *data)
3053 {
3054         OFono_Pending *p;
3055         OFono_Simple_Cb_Context *ctx = NULL;
3056         Eldbus_Message *msg;
3057         Eldbus_Message_Iter *iter, *variant;
3058         OFono_Modem *m = _modem_selected_get();
3059
3060         EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
3061
3062         if (cb) {
3063                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3064                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
3065                 ctx->cb = cb;
3066                 ctx->data = data;
3067         }
3068
3069         msg = eldbus_message_method_call_new(bus_id, m->base.path,
3070                                            OFONO_PREFIX OFONO_CALL_VOL_IFACE,
3071                                            "SetProperty");
3072         if (!msg)
3073                 goto error_no_dbus_message;
3074
3075         if (!eldbus_message_arguments_append(msg, "s", property))
3076                 goto error_message_args;
3077
3078         iter = eldbus_message_iter_get(msg);
3079
3080         variant = eldbus_message_iter_container_new(iter, 'v', (const char*) &type);
3081
3082         if (!variant)
3083                 goto error_message_args;
3084
3085         if (strcmp(property, "Muted") == 0) {
3086                 if (!eldbus_message_iter_basic_append(variant, type, *(Eina_Bool *) value) ||
3087                         !eldbus_message_iter_container_close(iter, variant)) {
3088                         goto error_message_args;
3089                 }
3090         } else if (strcmp(property, "SpeakerVolume") == 0 || strcmp(property, "MicrophoneVolume") == 0) {
3091                 if (!eldbus_message_iter_basic_append(variant, type, *(char *) value) ||
3092                         !eldbus_message_iter_container_close(iter, variant)) {
3093                         goto error_message_args;
3094                 }
3095         } else {
3096                 ERR("Unsupported property: %s", property);
3097         }
3098
3099         INF("%s.SetProperty(%s)", OFONO_CALL_VOL_IFACE, property);
3100         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3101         return p;
3102
3103 error_message_args:
3104         eldbus_message_unref(msg);
3105
3106 error_no_dbus_message:
3107         if (cb)
3108                 cb((void *)data, OFONO_ERROR_FAILED);
3109         free(ctx);
3110         return NULL;
3111 }
3112
3113 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
3114                                 const void *data)
3115 {
3116         Eina_Bool dbus_mute = !!mute;
3117
3118         return  _ofono_call_volume_property_set("Muted", 'b',
3119                                                 &dbus_mute, cb, data);
3120 }
3121
3122 Eina_Bool ofono_mute_get(void)
3123 {
3124         OFono_Modem *m = _modem_selected_get();
3125         EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3126         return m->muted;
3127 }
3128
3129 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
3130                                         OFono_Simple_Cb cb,
3131                                         const void *data)
3132 {
3133
3134         return _ofono_call_volume_property_set("SpeakerVolume", 'y',
3135                                                 &volume, cb, data);
3136 }
3137
3138 unsigned char ofono_volume_speaker_get(void)
3139 {
3140         OFono_Modem *m = _modem_selected_get();
3141         EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3142         return m->speaker_volume;
3143 }
3144
3145 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
3146                                                 OFono_Simple_Cb cb,
3147                                                 const void *data)
3148 {
3149         return _ofono_call_volume_property_set("MicrophoneVolume",
3150                                                 'y', &volume, cb,
3151                                                 data);
3152 }
3153
3154 unsigned char ofono_volume_microphone_get(void)
3155 {
3156         OFono_Modem *m = _modem_selected_get();
3157         EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3158         return m->microphone_volume;
3159 }
3160
3161 Eina_Bool ofono_voicemail_waiting_get(void)
3162 {
3163         OFono_Modem *m = _modem_selected_get();
3164         EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3165         return m->voicemail_waiting;
3166 }
3167
3168 unsigned char ofono_voicemail_count_get(void)
3169 {
3170         OFono_Modem *m = _modem_selected_get();
3171         EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3172         return m->voicemail_count;
3173 }
3174
3175 const char *ofono_voicemail_number_get(void)
3176 {
3177         OFono_Modem *m = _modem_selected_get();
3178         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3179         return m->voicemail_number;
3180 }
3181
3182 OFono_USSD_State ofono_ussd_state_get(void)
3183 {
3184         OFono_Modem *m = _modem_selected_get();
3185         EINA_SAFETY_ON_NULL_RETURN_VAL(m, OFONO_USSD_STATE_IDLE);
3186         return m->ussd_state;
3187 }
3188
3189 const char *ofono_service_center_address_get(void)
3190 {
3191         OFono_Modem *m = _modem_selected_get();
3192         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3193         return m->serv_center_addr;
3194 }
3195
3196 Eina_Bool ofono_use_delivery_reports_get(void)
3197 {
3198         OFono_Modem *m = _modem_selected_get();
3199         EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3200         return m->use_delivery_reports;
3201 }
3202
3203 const char *ofono_message_bearer_get(void)
3204 {
3205         OFono_Modem *m = _modem_selected_get();
3206         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3207         return m->msg_bearer;
3208 }
3209
3210 const char *ofono_message_alphabet_get(void)
3211 {
3212         OFono_Modem *m = _modem_selected_get();
3213         EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3214         return m->msg_alphabet;
3215 }
3216
3217 OFono_Sent_SMS_State ofono_sent_sms_state_get(const OFono_Sent_SMS *sms)
3218 {
3219         EINA_SAFETY_ON_NULL_RETURN_VAL(sms, OFONO_SENT_SMS_STATE_FAILED);
3220         return sms->state;
3221 }
3222
3223 const char *ofono_sent_sms_destination_get(const OFono_Sent_SMS *sms)
3224 {
3225         EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3226         return sms->destination;
3227 }
3228
3229 const char *ofono_sent_sms_message_get(const OFono_Sent_SMS *sms)
3230 {
3231         EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3232         return sms->message;
3233 }
3234
3235 time_t ofono_sent_sms_timestamp_get(const OFono_Sent_SMS *sms)
3236 {
3237         EINA_SAFETY_ON_NULL_RETURN_VAL(sms, 0);
3238         return sms->timestamp;
3239 }
3240
3241 OFono_Pending *ofono_sent_sms_cancel(OFono_Sent_SMS *sms, OFono_Simple_Cb cb,
3242                                         const void *data)
3243 {
3244         OFono_Simple_Cb_Context *ctx = NULL;
3245         OFono_Error err = OFONO_ERROR_OFFLINE;
3246         OFono_Pending *p;
3247         Eldbus_Message *msg;
3248
3249         if (cb) {
3250                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3251                 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3252                 ctx->cb = cb;
3253                 ctx->data = data;
3254         }
3255
3256         msg = eldbus_message_method_call_new(bus_id, sms->base.path,
3257                                                 OFONO_PREFIX "Message",
3258                                                 "Cancel");
3259         if (!msg)
3260                 goto error;
3261
3262         INF("Cancel(%s)", sms->base.path);
3263         p = _bus_object_message_send(&sms->base, msg, _ofono_simple_reply, ctx);
3264         return p;
3265
3266 error:
3267         if (cb)
3268                 cb((void *)data, err);
3269         free(ctx);
3270         return NULL;
3271 }
3272
3273 static void _ofono_sms_send_reply(void *data, Eldbus_Message *msg,
3274                                                 Eldbus_Pending *pending __UNUSED__)
3275 {
3276         OFono_Sent_SMS_Cb_Context *ctx = data;
3277         OFono_Sent_SMS *sms = NULL;
3278         OFono_Error oe = OFONO_ERROR_NONE;
3279         const char *err_name, *err_message;
3280
3281         EINA_SAFETY_ON_NULL_RETURN(data);
3282
3283         if (!msg) {
3284                 ERR("No message");
3285                 oe = OFONO_ERROR_FAILED;
3286         }
3287
3288         if (eldbus_message_error_get(msg, &err_name, &err_message)) {
3289                 ERR("Ofono reply error %s: %s", err_name, err_message);
3290                 oe = _ofono_error_parse(err_name);
3291         } else {
3292                 const char *path;
3293                 if (!eldbus_message_arguments_get(msg, "o", &path)) {
3294                         ERR("Could not get SendMessage reply");
3295                         oe = OFONO_ERROR_FAILED;
3296                 } else {
3297                         sms = eina_hash_find(ctx->modem->sent_sms, path);
3298                         DBG("path=%s, existing sms=%p", path, sms);
3299                         if (!sms) {
3300                                 sms = _sent_sms_pending_add(ctx->modem, path,
3301                                                                 ctx);
3302                                 if (sms) {
3303                                         /* ctx->cb will be dispatched on
3304                                          * MessageAdded signal handler.
3305                                          */
3306                                         return;
3307                                 }
3308                         }
3309
3310                         ERR("Could not find sms %s", path);
3311                         oe = OFONO_ERROR_FAILED;
3312                 }
3313         }
3314
3315         if (ctx->cb)
3316                 ctx->cb((void *)ctx->data, oe, sms);
3317
3318         eina_stringshare_del(ctx->destination);
3319         eina_stringshare_del(ctx->message);
3320         free(ctx);
3321 }
3322
3323 OFono_Pending *ofono_sms_send(const char *number, const char *message,
3324                                 OFono_Sent_SMS_Cb cb, const void *data)
3325 {
3326         OFono_Sent_SMS_Cb_Context *ctx = NULL;
3327         OFono_Error err = OFONO_ERROR_OFFLINE;
3328         OFono_Pending *p;
3329         Eldbus_Message *msg;
3330         OFono_Modem *m = _modem_selected_get();
3331         EINA_SAFETY_ON_NULL_GOTO(m, error);
3332         EINA_SAFETY_ON_NULL_GOTO(number, error);
3333         EINA_SAFETY_ON_NULL_GOTO(message, error);
3334
3335         if ((m->interfaces & OFONO_API_MSG) == 0)
3336                 goto error;
3337         err = OFONO_ERROR_FAILED;
3338
3339         ctx = calloc(1, sizeof(OFono_Sent_SMS_Cb_Context));
3340         EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3341         ctx->cb = cb;
3342         ctx->data = data;
3343         ctx->modem = m;
3344         ctx->destination = eina_stringshare_add(number);
3345         ctx->message = eina_stringshare_add(message);
3346
3347         msg = eldbus_message_method_call_new(
3348                 bus_id, m->base.path, OFONO_PREFIX OFONO_MSG_IFACE,
3349                 "SendMessage");
3350         if (!msg)
3351                 goto error_setup;
3352
3353         if (!eldbus_message_arguments_append(msg, "ss", number, message))
3354                 goto error_message;
3355
3356         INF("SendMessage(%s, %s)", number, message);
3357         p = _bus_object_message_send(&m->base, msg, _ofono_sms_send_reply, ctx);
3358         return p;
3359
3360 error_message:
3361         eldbus_message_unref(msg);
3362 error_setup:
3363         eina_stringshare_del(ctx->destination);
3364         eina_stringshare_del(ctx->message);
3365 error:
3366         if (cb)
3367                 cb((void *)data, err, NULL);
3368         free(ctx);
3369         return NULL;
3370 }
3371
3372 OFono_Pending *ofono_tones_send(const char *tones,
3373                                                 OFono_Simple_Cb cb,
3374                                                 const void *data)
3375 {
3376         OFono_Pending *p;
3377         Eldbus_Message *msg;
3378         OFono_Simple_Cb_Context *ctx = NULL;
3379         OFono_Modem *m = _modem_selected_get();
3380
3381         EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
3382
3383         if (cb) {
3384                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3385                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
3386                 ctx->cb = cb;
3387                 ctx->data = data;
3388         }
3389
3390         msg = eldbus_message_method_call_new(
3391                                 bus_id, m->base.path,
3392                                 OFONO_PREFIX OFONO_VOICE_IFACE,
3393                                 "SendTones");
3394         if (!msg)
3395                 goto error_no_dbus_message;
3396
3397         if (!eldbus_message_arguments_append(msg, "s", tones))
3398                 goto error_message_args;
3399
3400         INF("SendTones(%s)", tones);
3401         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3402         return p;
3403
3404 error_message_args:
3405         eldbus_message_unref(msg);
3406
3407 error_no_dbus_message:
3408         if (cb)
3409                 cb((void *)data, OFONO_ERROR_FAILED);
3410         free(ctx);
3411         return NULL;
3412 }
3413
3414 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
3415                                         const void *data)
3416 {
3417         return _ofono_multiparty("CreateMultiparty", cb, data);
3418 }
3419
3420 OFono_Pending *ofono_multiparty_hangup(OFono_Simple_Cb cb, const void *data)
3421 {
3422         return _ofono_multiparty("HangupMultiparty", cb, data);
3423 }
3424
3425 OFono_Pending *ofono_private_chat(OFono_Call *c, OFono_Simple_Cb cb,
3426                                         const void *data)
3427 {
3428         OFono_Pending *p;
3429         Eldbus_Message *msg;
3430         OFono_Simple_Cb_Context *ctx = NULL;
3431         OFono_Modem *m = _modem_selected_get();
3432
3433         EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
3434         EINA_SAFETY_ON_NULL_GOTO(c, error_no_message);
3435
3436         if (cb) {
3437                 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3438                 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
3439                 ctx->cb = cb;
3440                 ctx->data = data;
3441         }
3442
3443         msg = eldbus_message_method_call_new(
3444                                 bus_id, m->base.path,
3445                                 OFONO_PREFIX OFONO_VOICE_IFACE,
3446                                 "PrivateChat");
3447
3448         if (!msg)
3449                 goto error_no_message;
3450
3451         if (!eldbus_message_arguments_append(msg, "o", c->base.path))
3452                 goto error_message_append;
3453
3454         INF("PrivateChat(%s)", c->base.path);
3455         p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3456         return p;
3457
3458 error_message_append:
3459         eldbus_message_unref(msg);
3460 error_no_message:
3461         if (cb)
3462                 cb((void *)data, OFONO_ERROR_FAILED);
3463         free(ctx);
3464         return NULL;
3465 }
3466
3467 static OFono_Callback_List_Modem_Node * _ofono_callback_modem_node_create(
3468         void (*cb)(void *data),const void *data)
3469 {
3470         OFono_Callback_List_Modem_Node *node_new;
3471
3472         node_new = calloc(1, sizeof(OFono_Callback_List_Modem_Node));
3473         EINA_SAFETY_ON_NULL_RETURN_VAL(node_new, NULL);
3474
3475         node_new->cb_data = data;
3476         node_new->cb = cb;
3477
3478         return node_new;
3479 }
3480
3481 OFono_Callback_List_Modem_Node *
3482 ofono_modem_conected_cb_add(void (*cb)(void *data), const void *data)
3483 {
3484         OFono_Callback_List_Modem_Node *node;
3485
3486         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3487         node = _ofono_callback_modem_node_create(cb, data);
3488         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3489
3490         cbs_modem_connected = eina_inlist_append(cbs_modem_connected,
3491                                                         EINA_INLIST_GET(node));
3492
3493         return node;
3494 }
3495
3496 OFono_Callback_List_Modem_Node *
3497 ofono_modem_disconnected_cb_add(void (*cb)(void *data), const void *data)
3498 {
3499         OFono_Callback_List_Modem_Node *node;
3500
3501         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3502         node = _ofono_callback_modem_node_create(cb, data);
3503         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3504
3505         cbs_modem_disconnected = eina_inlist_append(cbs_modem_disconnected,
3506                                                         EINA_INLIST_GET(node));
3507
3508         return node;
3509 }
3510
3511 OFono_Callback_List_Modem_Node *
3512 ofono_modem_changed_cb_add(void (*cb)(void *data), const void *data)
3513 {
3514         OFono_Callback_List_Modem_Node *node;
3515
3516         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3517         node = _ofono_callback_modem_node_create(cb, data);
3518         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3519
3520         cbs_modem_changed = eina_inlist_append(cbs_modem_changed,
3521                                                 EINA_INLIST_GET(node));
3522
3523         return node;
3524 }
3525
3526 static void _ofono_callback_modem_list_delete(Eina_Inlist **list,
3527                                         OFono_Callback_List_Modem_Node *node)
3528 {
3529         EINA_SAFETY_ON_NULL_RETURN(*list);
3530         *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3531         free(node);
3532 }
3533
3534 void ofono_modem_changed_cb_del(OFono_Callback_List_Modem_Node *node)
3535 {
3536         EINA_SAFETY_ON_NULL_RETURN(node);
3537         _ofono_callback_modem_list_delete(&cbs_modem_changed, node);
3538 }
3539
3540 void ofono_modem_disconnected_cb_del(OFono_Callback_List_Modem_Node *node)
3541 {
3542         EINA_SAFETY_ON_NULL_RETURN(node);
3543         _ofono_callback_modem_list_delete(&cbs_modem_disconnected, node);
3544 }
3545
3546 void ofono_modem_connected_cb_del(OFono_Callback_List_Modem_Node *node)
3547 {
3548         EINA_SAFETY_ON_NULL_RETURN(node);
3549         _ofono_callback_modem_list_delete(&cbs_modem_connected, node);
3550 }
3551
3552 static OFono_Callback_List_Call_Node *_ofono_callback_call_node_create(
3553         void (*cb)(void *data, OFono_Call *call),const void *data)
3554 {
3555         OFono_Callback_List_Call_Node *node;
3556
3557         node = calloc(1, sizeof(OFono_Callback_List_Call_Node));
3558         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3559
3560         node->cb_data = data;
3561         node->cb = cb;
3562
3563         return node;
3564 }
3565
3566 static OFono_Callback_List_Call_Disconnected_Node *
3567 _ofono_callback_call_disconnected_node_create(
3568         void (*cb)(void *data, OFono_Call *call, const char *reason),
3569         const void *data)
3570 {
3571         OFono_Callback_List_Call_Disconnected_Node *node;
3572
3573         node = calloc(1, sizeof(OFono_Callback_List_Call_Disconnected_Node));
3574         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3575
3576         node->cb_data = data;
3577         node->cb = cb;
3578
3579         return node;
3580 }
3581
3582 static OFono_Callback_List_USSD_Notify_Node *
3583 _ofono_callback_ussd_notify_node_create(
3584         void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3585         const void *data)
3586 {
3587         OFono_Callback_List_USSD_Notify_Node *node;
3588
3589         node = calloc(1, sizeof(OFono_Callback_List_USSD_Notify_Node));
3590         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3591
3592         node->cb_data = data;
3593         node->cb = cb;
3594
3595         return node;
3596 }
3597
3598 OFono_Callback_List_Call_Node *ofono_call_added_cb_add(
3599         void (*cb)(void *data,OFono_Call *call), const void *data)
3600 {
3601         OFono_Callback_List_Call_Node *node;
3602
3603         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3604         node = _ofono_callback_call_node_create(cb, data);
3605         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3606
3607         cbs_call_added = eina_inlist_append(cbs_call_added,
3608                                                 EINA_INLIST_GET(node));
3609
3610         return node;
3611 }
3612
3613 OFono_Callback_List_Call_Node *ofono_call_removed_cb_add(
3614         void (*cb)(void *data, OFono_Call *call), const void *data)
3615 {
3616         OFono_Callback_List_Call_Node *node;
3617
3618         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3619         node = _ofono_callback_call_node_create(cb, data);
3620         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3621
3622         cbs_call_removed = eina_inlist_append(cbs_call_removed,
3623                                                 EINA_INLIST_GET(node));
3624
3625         return node;
3626 }
3627
3628 OFono_Callback_List_Call_Node *ofono_call_changed_cb_add(
3629         void (*cb)(void *data, OFono_Call *call), const void *data)
3630 {
3631         OFono_Callback_List_Call_Node *node;
3632
3633         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3634         node = _ofono_callback_call_node_create(cb, data);
3635         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3636
3637         cbs_call_changed = eina_inlist_append(cbs_call_changed,
3638                                                 EINA_INLIST_GET(node));
3639
3640         return node;
3641 }
3642
3643 OFono_Callback_List_Call_Disconnected_Node *ofono_call_disconnected_cb_add(
3644         void (*cb)(void *data, OFono_Call *call, const char *reason),
3645         const void *data)
3646 {
3647         OFono_Callback_List_Call_Disconnected_Node *node;
3648
3649         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3650         node = _ofono_callback_call_disconnected_node_create(cb, data);
3651         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3652
3653         cbs_call_disconnected = eina_inlist_append(cbs_call_disconnected,
3654                                                         EINA_INLIST_GET(node));
3655
3656         return node;
3657 }
3658
3659 OFono_Callback_List_USSD_Notify_Node *ofono_ussd_notify_cb_add(
3660         void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3661         const void *data)
3662 {
3663         OFono_Callback_List_USSD_Notify_Node *node;
3664
3665         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3666         node = _ofono_callback_ussd_notify_node_create(cb, data);
3667         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3668
3669         cbs_ussd_notify = eina_inlist_append(cbs_ussd_notify,
3670                                                 EINA_INLIST_GET(node));
3671
3672         return node;
3673 }
3674
3675 static void _ofono_callback_call_list_delete(Eina_Inlist **list,
3676                                         OFono_Callback_List_Call_Node *node)
3677 {
3678         EINA_SAFETY_ON_NULL_RETURN(*list);
3679         *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3680         free(node);
3681 }
3682
3683 void ofono_call_changed_cb_del(OFono_Callback_List_Call_Node *node)
3684 {
3685         EINA_SAFETY_ON_NULL_RETURN(node);
3686         _ofono_callback_call_list_delete(&cbs_call_changed, node);
3687 }
3688
3689 void ofono_call_disconnected_cb_del(
3690         OFono_Callback_List_Call_Disconnected_Node *node)
3691 {
3692         EINA_SAFETY_ON_NULL_RETURN(node);
3693         EINA_SAFETY_ON_NULL_RETURN(cbs_call_disconnected);
3694         cbs_call_disconnected = eina_inlist_remove(cbs_call_disconnected,
3695                                                         EINA_INLIST_GET(node));
3696         free(node);
3697 }
3698
3699 void ofono_ussd_notify_cb_del(OFono_Callback_List_USSD_Notify_Node *node)
3700 {
3701         EINA_SAFETY_ON_NULL_RETURN(node);
3702         EINA_SAFETY_ON_NULL_RETURN(cbs_ussd_notify);
3703         cbs_ussd_notify = eina_inlist_remove(cbs_ussd_notify,
3704                                                 EINA_INLIST_GET(node));
3705         free(node);
3706 }
3707
3708 void ofono_call_added_cb_del(OFono_Callback_List_Call_Node *node)
3709 {
3710         EINA_SAFETY_ON_NULL_RETURN(node);
3711         _ofono_callback_call_list_delete(&cbs_call_added, node);
3712 }
3713
3714 void ofono_call_removed_cb_del(OFono_Callback_List_Call_Node *node)
3715 {
3716         EINA_SAFETY_ON_NULL_RETURN(node);
3717         _ofono_callback_call_list_delete(&cbs_call_removed, node);
3718 }
3719
3720 OFono_Callback_List_Sent_SMS_Node *
3721 ofono_sent_sms_changed_cb_add(OFono_Sent_SMS_Cb cb, const void *data)
3722 {
3723         OFono_Callback_List_Sent_SMS_Node *node;
3724
3725         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3726         node = calloc(1, sizeof(OFono_Callback_List_Sent_SMS_Node));
3727         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3728         node->cb = cb;
3729         node->cb_data = data;
3730
3731         cbs_sent_sms_changed = eina_inlist_append(cbs_sent_sms_changed,
3732                                                         EINA_INLIST_GET(node));
3733
3734         return node;
3735 }
3736
3737 void ofono_sent_sms_changed_cb_del(OFono_Callback_List_Sent_SMS_Node *node)
3738 {
3739         EINA_SAFETY_ON_NULL_RETURN(node);
3740         cbs_sent_sms_changed = eina_inlist_remove(cbs_sent_sms_changed,
3741                                                         EINA_INLIST_GET(node));
3742         free(node);
3743 }
3744
3745 OFono_Callback_List_Incoming_SMS_Node *
3746 ofono_incoming_sms_cb_add(OFono_Incoming_SMS_Cb cb, const void *data)
3747 {
3748         OFono_Callback_List_Incoming_SMS_Node *node;
3749
3750         EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3751         node = calloc(1, sizeof(OFono_Callback_List_Incoming_SMS_Node));
3752         EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3753         node->cb = cb;
3754         node->cb_data = data;
3755
3756         cbs_incoming_sms = eina_inlist_append(cbs_incoming_sms,
3757                                                 EINA_INLIST_GET(node));
3758
3759         return node;
3760 }
3761
3762 void ofono_incoming_sms_cb_del(OFono_Callback_List_Incoming_SMS_Node *node)
3763 {
3764         EINA_SAFETY_ON_NULL_RETURN(node);
3765         cbs_incoming_sms = eina_inlist_remove(cbs_incoming_sms,
3766                                                 EINA_INLIST_GET(node));
3767         free(node);
3768 }
3769
3770 Eina_Bool ofono_voice_is_online(void)
3771 {
3772         OFono_Modem *m = _modem_selected_get();
3773
3774         /* The modem is expected to be NULL here, because maybe
3775          * OFono isn't up yet.
3776          */
3777         if (!m)
3778                 return EINA_FALSE;
3779
3780         if (m->interfaces & OFONO_API_VOICE)
3781                 return EINA_TRUE;
3782
3783         return EINA_FALSE;
3784 }