4 #include <Elementary.h>
11 typedef struct _OFono_Modem OFono_Modem;
12 typedef struct _OFono_Bus_Object OFono_Bus_Object;
14 static const char bus_name[] = "org.ofono";
16 static const char *known_modem_types[] = {"hfp", "sap", "hardware", NULL};
18 static E_DBus_Connection *bus_conn = NULL;
19 static char *bus_id = NULL;
20 static Eina_Hash *modems = NULL;
21 static OFono_Modem *modem_selected = NULL;
22 static const char *modem_path_wanted = NULL;
23 static unsigned int modem_api_mask = 0;
24 static Eina_List *modem_types = NULL;
25 static E_DBus_Signal_Handler *sig_modem_added = NULL;
26 static E_DBus_Signal_Handler *sig_modem_removed = NULL;
27 static E_DBus_Signal_Handler *sig_modem_prop_changed = NULL;
28 static DBusPendingCall *pc_get_modems = NULL;
30 static void _ofono_call_volume_properties_get(OFono_Modem *m);
31 static void _ofono_msg_waiting_properties_get(OFono_Modem *m);
32 static void _ofono_suppl_serv_properties_get(OFono_Modem *m);
33 static void _ofono_msg_properties_get(OFono_Modem *m);
35 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
36 OFono_Simple_Cb cb, const void *data);
38 struct _OFono_Callback_List_Modem_Node
41 void (*cb)(void *data);
45 struct _OFono_Callback_List_Call_Node
48 void (*cb)(void *data, OFono_Call *call);
52 struct _OFono_Callback_List_Call_Disconnected_Node
55 void (*cb)(void *data, OFono_Call *call, const char *reason);
59 struct _OFono_Callback_List_USSD_Notify_Node
62 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg);
66 struct _OFono_Callback_List_Sent_SMS_Node
73 struct _OFono_Callback_List_Incoming_SMS_Node
76 OFono_Incoming_SMS_Cb cb;
80 static Eina_Inlist *cbs_modem_changed = NULL;
81 static Eina_Inlist *cbs_modem_connected = NULL;
82 static Eina_Inlist *cbs_modem_disconnected = NULL;
83 static Eina_Inlist *cbs_ussd_notify = NULL;
85 static Eina_Inlist *cbs_call_changed = NULL;
86 static Eina_Inlist *cbs_call_added = NULL;
87 static Eina_Inlist *cbs_call_disconnected = NULL;
88 static Eina_Inlist *cbs_call_removed = NULL;
90 static Eina_Inlist *cbs_sent_sms_changed = NULL;
91 static Eina_Inlist *cbs_incoming_sms = NULL;
93 #define OFONO_SERVICE "org.ofono"
95 #define OFONO_PREFIX OFONO_SERVICE "."
96 #define OFONO_PREFIX_ERROR OFONO_SERVICE ".Error."
97 #define OFONO_MODEM_IFACE "Modem"
98 #define OFONO_MANAGER_IFACE "Manager"
99 #define OFONO_SIM_IFACE "SimManager"
100 #define OFONO_NETREG_IFACE "NetworkRegistration"
101 #define OFONO_VOICE_IFACE "VoiceCallManager"
102 #define OFONO_MSG_IFACE "MessageManager"
103 #define OFONO_MSG_WAITING_IFACE "MessageWaiting"
104 #define OFONO_SMART_MSG_IFACE "SmartMessaging"
105 #define OFONO_STK_IFACE "SimToolkit"
107 #define OFONO_CALL_FW_IFACE "CallForwarding"
108 #define OFONO_CALL_VOL_IFACE "CallVolume"
109 #define OFONO_CALL_METER_IFACE "CallMeter"
110 #define OFONO_CALL_SET_IFACE "CallSettings"
111 #define OFONO_CALL_BAR_IFACE "CallBarring"
112 #define OFONO_SUPPL_SERV_IFACE "SupplementaryServices"
113 #define OFONO_TXT_TEL_IFACE "TextTelephony"
114 #define OFONO_CELL_BROAD_IFACE "CellBroadcast"
115 #define OFONO_CONNMAN_IFACE "ConnectionManager"
116 #define OFONO_PUSH_NOTIF_IFACE "PushNotification"
117 #define OFONO_PHONEBOOK_IFACE "Phonebook"
118 #define OFONO_ASN_IFACE "AssistedSatelliteNavigation"
120 static const struct API_Interface_Map {
124 } api_iface_map[] = {
125 #define MAP(bit, name) {bit, name, sizeof(name) - 1}
126 MAP(OFONO_API_SIM, OFONO_SIM_IFACE),
127 MAP(OFONO_API_NETREG, OFONO_NETREG_IFACE),
128 MAP(OFONO_API_VOICE, OFONO_VOICE_IFACE),
129 MAP(OFONO_API_MSG, OFONO_MSG_IFACE),
130 MAP(OFONO_API_MSG_WAITING, OFONO_MSG_WAITING_IFACE),
131 MAP(OFONO_API_SMART_MSG, OFONO_SMART_MSG_IFACE),
132 MAP(OFONO_API_STK, OFONO_STK_IFACE),
133 MAP(OFONO_API_CALL_FW, OFONO_CALL_FW_IFACE),
134 MAP(OFONO_API_CALL_VOL, OFONO_CALL_VOL_IFACE),
135 MAP(OFONO_API_CALL_METER, OFONO_CALL_METER_IFACE),
136 MAP(OFONO_API_CALL_SET, OFONO_CALL_SET_IFACE),
137 MAP(OFONO_API_CALL_BAR, OFONO_CALL_BAR_IFACE),
138 MAP(OFONO_API_SUPPL_SERV, OFONO_SUPPL_SERV_IFACE),
139 MAP(OFONO_API_TXT_TEL, OFONO_TXT_TEL_IFACE),
140 MAP(OFONO_API_CELL_BROAD, OFONO_CELL_BROAD_IFACE),
141 MAP(OFONO_API_CONNMAN, OFONO_CONNMAN_IFACE),
142 MAP(OFONO_API_PUSH_NOTIF, OFONO_PUSH_NOTIF_IFACE),
143 MAP(OFONO_API_PHONEBOOK, OFONO_PHONEBOOK_IFACE),
144 MAP(OFONO_API_ASN, OFONO_ASN_IFACE),
149 static Eina_Bool _dbus_bool_get(DBusMessageIter *itr)
152 dbus_message_iter_get_basic(itr, &val);
156 static const struct Error_Map {
162 #define MAP(id, name, msg) {id, name, msg, sizeof(name) - 1}
163 MAP(OFONO_ERROR_FAILED, "Failed", "Failed"),
164 MAP(OFONO_ERROR_DOES_NOT_EXIST, "DoesNotExist", "Does not exist"),
165 MAP(OFONO_ERROR_IN_PROGRESS, "InProgress", "Operation in progress"),
166 MAP(OFONO_ERROR_IN_USE, "InUse", "Already in use"),
167 MAP(OFONO_ERROR_INVALID_ARGS, "InvalidArguments", "Invalid arguments"),
168 MAP(OFONO_ERROR_INVALID_FORMAT, "InvalidFormat", "Invalid format"),
169 MAP(OFONO_ERROR_ACCESS_DENIED, "AccessDenied", "Access Denied"),
170 MAP(OFONO_ERROR_ATTACH_IN_PROGRESS, "AttachInProgress",
171 "Attach is already in progress"),
172 MAP(OFONO_ERROR_INCORRECT_PASSWORD, "IncorrectPassword",
173 "Incorrect password"),
174 MAP(OFONO_ERROR_NOT_ACTIVE, "NotActive", "Not active"),
175 MAP(OFONO_ERROR_NOT_ALLOWED, "NotAllowed", "Not allowed"),
176 MAP(OFONO_ERROR_NOT_ATTACHED, "NotAttached", "Not attached"),
177 MAP(OFONO_ERROR_NOT_AVAILABLE, "NotAvailable", "Not available"),
178 MAP(OFONO_ERROR_NOT_FOUND, "NotFound", "Not found"),
179 MAP(OFONO_ERROR_NOT_IMPLEMENTED, "NotImplemented", "Not implemented"),
180 MAP(OFONO_ERROR_NOT_RECOGNIZED, "NotRecognized", "Not recognized"),
181 MAP(OFONO_ERROR_NOT_REGISTERED, "NotRegistered", "Not registered"),
182 MAP(OFONO_ERROR_NOT_SUPPORTED, "NotSupported", "Not supported"),
183 MAP(OFONO_ERROR_SIM_NOT_READY, "SimNotReady", "SIM not ready"),
184 MAP(OFONO_ERROR_STK, "SimToolkit", "SIM Toolkit Failed"),
185 MAP(OFONO_ERROR_TIMEDOUT, "Timedout", "Timed out"),
190 const char *ofono_error_message_get(OFono_Error e)
192 const struct Error_Map *itr;
194 if (e == OFONO_ERROR_NONE)
197 for (itr = error_map; itr->name != NULL; itr++)
201 return "Unknown error";
204 static OFono_Error _ofono_error_parse(const char *name)
206 size_t namelen, prefixlen = sizeof(OFONO_PREFIX_ERROR) - 1;
207 const struct Error_Map *itr;
209 /* whenever interfaces are not there due modem being offline */
210 if (strcmp(name, "org.freedesktop.DBus.Error.UnknownMethod") == 0)
211 return OFONO_ERROR_OFFLINE;
213 if (strncmp(name, OFONO_PREFIX_ERROR, prefixlen) != 0)
214 return OFONO_ERROR_FAILED;
217 namelen = strlen(name);
218 for (itr = error_map; itr->name != NULL; itr++)
219 if ((itr->namelen == namelen) &&
220 (memcmp(name, itr->name, namelen) == 0))
223 return OFONO_ERROR_FAILED;
226 typedef struct _OFono_Simple_Cb_Context
230 } OFono_Simple_Cb_Context;
232 static void _ofono_simple_reply(void *data, DBusMessage *msg __UNUSED__,
235 OFono_Simple_Cb_Context *ctx = data;
236 OFono_Error e = OFONO_ERROR_NONE;
238 if (dbus_error_is_set(err)) {
239 DBG("%s: %s", err->name, err->message);
240 e = _ofono_error_parse(err->name);
244 ctx->cb((void *)ctx->data, e);
249 typedef struct _OFono_String_Cb_Context
254 char *(*convert)(DBusMessage *msg);
255 } OFono_String_Cb_Context;
257 static void _ofono_string_reply(void *data, DBusMessage *msg, DBusError *err)
259 OFono_String_Cb_Context *ctx = data;
260 OFono_Error e = OFONO_ERROR_NONE;
263 if (dbus_error_is_set(err)) {
264 DBG("%s: %s", err->name, err->message);
265 e = _ofono_error_parse(err->name);
267 str = ctx->convert(msg);
269 e = OFONO_ERROR_NOT_SUPPORTED;
273 ctx->cb((void *)ctx->data, e, str);
275 DBG("%s %s", ctx->name, str);
281 struct _OFono_Pending
284 DBusPendingCall *pending;
285 E_DBus_Method_Return_Cb cb;
290 struct _OFono_Bus_Object
293 Eina_Inlist *dbus_pending; /* of OFono_Pending */
294 Eina_List *dbus_signals; /* of E_DBus_Signal_Handler */
297 static void _notify_ofono_callbacks_call_list(Eina_Inlist *list,
300 OFono_Callback_List_Call_Node *node;
302 EINA_INLIST_FOREACH(list, node)
303 node->cb((void *) node->cb_data, call);
306 static void _notify_ofono_callbacks_call_disconnected_list(Eina_Inlist *list,
310 OFono_Callback_List_Call_Disconnected_Node *node;
312 DBG("call=%p, reason=%s", call, reason);
314 EINA_INLIST_FOREACH(list, node)
315 node->cb((void *) node->cb_data, call, reason);
318 static void _notify_ofono_callbacks_ussd_notify_list(Eina_Inlist *list,
319 Eina_Bool needs_reply,
322 OFono_Callback_List_USSD_Notify_Node *node;
324 DBG("needs_reply=%hhu, msg=%s", needs_reply, msg);
326 EINA_INLIST_FOREACH(list, node)
327 node->cb((void *) node->cb_data, needs_reply, msg);
330 static void _bus_object_free(OFono_Bus_Object *o)
332 E_DBus_Signal_Handler *sh;
334 eina_stringshare_del(o->path);
336 while (o->dbus_pending) {
337 ofono_pending_cancel(
338 EINA_INLIST_CONTAINER_GET(o->dbus_pending,
342 EINA_LIST_FREE(o->dbus_signals, sh)
343 e_dbus_signal_handler_del(bus_conn, sh);
348 static void _bus_object_message_send_reply(void *data, DBusMessage *reply,
351 OFono_Pending *p = data;
352 OFono_Bus_Object *o = p->owner;
355 p->cb(p->data, reply, err);
357 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
362 static OFono_Pending *_bus_object_message_send(OFono_Bus_Object *o,
364 E_DBus_Method_Return_Cb cb,
368 EINA_SAFETY_ON_NULL_GOTO(o, error);
369 EINA_SAFETY_ON_NULL_GOTO(msg, error);
371 p = calloc(1, sizeof(OFono_Pending));
372 EINA_SAFETY_ON_NULL_GOTO(p, error);
378 p->pending = e_dbus_message_send(
379 bus_conn, msg, _bus_object_message_send_reply, -1, p);
380 EINA_SAFETY_ON_NULL_GOTO(p->pending, error_send);
382 o->dbus_pending = eina_inlist_append(o->dbus_pending,
384 dbus_message_unref(msg);
392 dbus_error_init(&err);
393 dbus_set_error(&err, "Failed", "call setup failed.");
394 cb(data, NULL, &err);
396 dbus_message_unref(msg);
400 void ofono_pending_cancel(OFono_Pending *p)
404 EINA_SAFETY_ON_NULL_RETURN(p);
407 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
413 dbus_error_init(&err);
414 dbus_set_error(&err, "Canceled",
415 "Pending method call was canceled.");
416 p->cb(p->data, NULL, &err);
418 dbus_pending_call_cancel(p->pending);
422 static void _bus_object_signal_listen(OFono_Bus_Object *o, const char *iface,
423 const char *name, E_DBus_Signal_Cb cb,
426 E_DBus_Signal_Handler *sh = e_dbus_signal_handler_add(
427 bus_conn, bus_id, o->path, iface, name, cb, data);
428 EINA_SAFETY_ON_NULL_RETURN(sh);
430 o->dbus_signals = eina_list_append(o->dbus_signals, sh);
433 typedef struct _OFono_Call_Cb_Context
439 } OFono_Call_Cb_Context;
443 OFono_Bus_Object base;
445 const char *incoming_line;
448 time_t full_start_time;
449 OFono_Call_State state;
450 Eina_Bool multiparty : 1;
451 Eina_Bool emergency : 1;
452 OFono_Call_Cb_Context *pending_dial;
455 typedef struct _OFono_Sent_SMS_Cb_Context
457 OFono_Sent_SMS_Cb cb;
460 const char *destination;
462 } OFono_Sent_SMS_Cb_Context;
464 struct _OFono_Sent_SMS
466 OFono_Bus_Object base;
467 OFono_Sent_SMS_State state;
468 OFono_Sent_SMS_Cb_Context *pending_send;
469 const char *destination;
476 OFono_Bus_Object base;
479 const char *voicemail_number;
480 const char *serv_center_addr;
481 const char *msg_bearer;
482 const char *msg_alphabet;
485 unsigned int interfaces;
486 unsigned char strength;
487 unsigned char data_strength;
488 unsigned char speaker_volume;
489 unsigned char microphone_volume;
490 unsigned char voicemail_count;
491 OFono_USSD_State ussd_state;
492 Eina_Bool ignored : 1;
493 Eina_Bool powered : 1;
494 Eina_Bool online : 1;
495 Eina_Bool roaming : 1;
497 Eina_Bool voicemail_waiting : 1;
498 Eina_Bool use_delivery_reports : 1;
501 static OFono_Call *_call_new(const char *path)
503 OFono_Call *c = calloc(1, sizeof(OFono_Call));
504 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
506 c->base.path = eina_stringshare_add(path);
507 EINA_SAFETY_ON_NULL_GOTO(c->base.path, error_path);
509 c->start_time = -1.0;
518 static void _call_free(OFono_Call *c)
520 DBG("c=%p %s", c, c->base.path);
522 _notify_ofono_callbacks_call_list(cbs_call_removed, c);
524 eina_stringshare_del(c->line_id);
525 eina_stringshare_del(c->incoming_line);
526 eina_stringshare_del(c->name);
528 _bus_object_free(&c->base);
531 static OFono_Call_State _call_state_parse(const char *str)
533 if (strcmp(str, "active") == 0)
534 return OFONO_CALL_STATE_ACTIVE;
535 else if (strcmp(str, "held") == 0)
536 return OFONO_CALL_STATE_HELD;
537 else if (strcmp(str, "dialing") == 0)
538 return OFONO_CALL_STATE_DIALING;
539 else if (strcmp(str, "alerting") == 0)
540 return OFONO_CALL_STATE_ALERTING;
541 else if (strcmp(str, "incoming") == 0)
542 return OFONO_CALL_STATE_INCOMING;
543 else if (strcmp(str, "waiting") == 0)
544 return OFONO_CALL_STATE_WAITING;
545 else if (strcmp(str, "disconnected") == 0)
546 return OFONO_CALL_STATE_DISCONNECTED;
548 ERR("unknown call state: %s", str);
549 return OFONO_CALL_STATE_DISCONNECTED;
552 static time_t _ofono_time_parse(const char *str)
557 memset(&tm, 0, sizeof(tm));
559 strptime(str, "%Y-%m-%dT%H:%M:%S%z", &tm);
560 zonediff = tm.tm_gmtoff; /* mktime resets it */
562 return mktime(&tm) - zonediff - timezone;
565 static void _call_property_update(OFono_Call *c, const char *key,
566 DBusMessageIter *value)
568 if (strcmp(key, "LineIdentification") == 0) {
570 dbus_message_iter_get_basic(value, &str);
571 DBG("%s LineIdentification %s", c->base.path, str);
572 eina_stringshare_replace(&c->line_id, str);
573 } else if (strcmp(key, "IncomingLine") == 0) {
575 dbus_message_iter_get_basic(value, &str);
576 DBG("%s IncomingLine %s", c->base.path, str);
577 eina_stringshare_replace(&c->incoming_line, str);
578 } else if (strcmp(key, "State") == 0) {
580 OFono_Call_State state;
581 dbus_message_iter_get_basic(value, &str);
582 state = _call_state_parse(str);
583 DBG("%s State %s (%d)", c->base.path, str, state);
585 if (state == OFONO_CALL_STATE_ACTIVE) {
586 if (c->start_time < 0.0)
587 c->start_time = ecore_loop_time_get();
588 if (c->full_start_time == 0)
589 c->full_start_time = time(NULL);
591 } else if (strcmp(key, "Name") == 0) {
593 dbus_message_iter_get_basic(value, &str);
594 DBG("%s Name %s", c->base.path, str);
595 eina_stringshare_replace(&c->name, str);
596 } else if (strcmp(key, "Multiparty") == 0) {
598 dbus_message_iter_get_basic(value, &v);
599 DBG("%s Multiparty %d", c->base.path, v);
601 } else if (strcmp(key, "Emergency") == 0) {
603 dbus_message_iter_get_basic(value, &v);
604 DBG("%s Emergency %d", c->base.path, v);
606 } else if (strcmp(key, "StartTime") == 0) {
607 const char *ts = NULL;
610 dbus_message_iter_get_basic(value, &ts);
612 st = _ofono_time_parse(ts);
614 lt = ecore_loop_time_get();
615 c->start_time = st - ut + lt;
616 c->full_start_time = st;
617 DBG("%s StartTime %f (%s)", c->base.path, c->start_time, ts);
619 DBG("%s %s (unused property)", c->base.path, key);
622 static void _call_property_changed(void *data, DBusMessage *msg)
624 OFono_Call *c = data;
625 DBusMessageIter iter, value;
628 if (!msg || !dbus_message_iter_init(msg, &iter)) {
629 ERR("Could not handle message %p", msg);
633 DBG("path=%s", c->base.path);
635 dbus_message_iter_get_basic(&iter, &key);
636 dbus_message_iter_next(&iter);
637 dbus_message_iter_recurse(&iter, &value);
638 _call_property_update(c, key, &value);
640 _notify_ofono_callbacks_call_list(cbs_call_changed, c);
643 static void _call_disconnect_reason(void *data, DBusMessage *msg)
645 OFono_Call *c = data;
654 DBG("path=%s", c->base.path);
655 c->state = OFONO_CALL_STATE_DISCONNECTED;
657 dbus_error_init(&err);
658 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &reason,
659 DBUS_TYPE_INVALID)) {
660 ERR("Could not get DisconnectReason arguments: %s: %s",
661 err.name, err.message);
662 dbus_error_free(&err);
666 _notify_ofono_callbacks_call_disconnected_list(cbs_call_disconnected,
670 static OFono_Call *_call_common_add(OFono_Modem *m, const char *path)
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);
676 _bus_object_signal_listen(&c->base,
677 OFONO_PREFIX "VoiceCall",
679 _call_disconnect_reason, c);
680 _bus_object_signal_listen(&c->base,
681 OFONO_PREFIX "VoiceCall",
683 _call_property_changed, c);
687 static OFono_Call *_call_pending_add(OFono_Modem *m, const char *path,
688 OFono_Call_Cb_Context *ctx)
692 DBG("path=%s, ctx=%p", path, ctx);
694 c = _call_common_add(m, path);
695 c->pending_dial = ctx;
699 static void _call_add(OFono_Modem *m, const char *path, DBusMessageIter *prop)
702 Eina_Bool needs_cb_added;
704 DBG("path=%s, prop=%p", path, prop);
706 c = eina_hash_find(m->calls, path);
709 DBG("Call already exists %p (%s)", c, path);
711 c = _call_common_add(m, path);
712 EINA_SAFETY_ON_NULL_RETURN(c);
715 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
716 dbus_message_iter_next(prop)) {
717 DBusMessageIter entry, value;
720 dbus_message_iter_recurse(prop, &entry);
721 dbus_message_iter_get_basic(&entry, &key);
723 dbus_message_iter_next(&entry);
724 dbus_message_iter_recurse(&entry, &value);
726 _call_property_update(c, key, &value);
729 if (c->pending_dial) {
730 OFono_Call_Cb_Context *ctx = c->pending_dial;
732 ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, c);
734 c->pending_dial = NULL;
735 needs_cb_added = EINA_TRUE;
739 _notify_ofono_callbacks_call_list(cbs_call_added, c);
741 _notify_ofono_callbacks_call_list(cbs_call_changed, c);
744 static void _call_remove(OFono_Modem *m, const char *path)
746 DBG("path=%s", path);
747 eina_hash_del_by_key(m->calls, path);
750 static void _call_added(void *data, DBusMessage *msg)
752 OFono_Modem *m = data;
753 DBusMessageIter iter, properties;
756 if (!msg || !dbus_message_iter_init(msg, &iter)) {
757 ERR("Could not handle message %p", msg);
761 dbus_message_iter_get_basic(&iter, &path);
763 dbus_message_iter_next(&iter);
764 dbus_message_iter_recurse(&iter, &properties);
766 _call_add(m, path, &properties);
769 static void _call_removed(void *data, DBusMessage *msg)
771 OFono_Modem *m = data;
776 ERR("Could not handle message %p", msg);
780 dbus_error_init(&err);
781 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
783 ERR("Could not get CallRemoved arguments: %s: %s",
784 err.name, err.message);
785 dbus_error_free(&err);
789 _call_remove(m, path);
792 static OFono_Modem *_modem_selected_get(void)
794 OFono_Modem *found_path = NULL, *found_api = NULL, *m;
795 unsigned int online = 0, powered = 0;
799 return modem_selected;
801 itr = eina_hash_iterator_data_new(modems);
802 EINA_ITERATOR_FOREACH(itr, m) {
811 if ((modem_path_wanted) && (!found_path)) {
812 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
813 if (m->base.path == modem_path_wanted) {
819 if ((!found_api) || ((!found_api->online) ||
820 (!found_api->powered))) {
821 DBG("m=%#x, mask=%#x, previous=%s "
822 "(online=%d, powered=%d)",
823 m->interfaces, modem_api_mask,
824 found_api ? found_api->base.path : "",
825 found_api ? found_api->online : 0,
826 found_api ? found_api->powered : 0);
827 if ((m->interfaces & modem_api_mask) == modem_api_mask)
831 eina_iterator_free(itr);
833 INF("found_path=%s, found_api=%s, wanted_path=%s, api_mask=%#x",
834 found_path ? found_path->base.path : "",
835 found_api ? found_api->base.path: "",
836 modem_path_wanted ? modem_path_wanted : "",
840 ERR("No modems powered! Run connman or test/enable-modem");
842 WRN("No modems online! Run connman or test/online-modem");
844 modem_selected = found_path ? found_path : found_api;
845 return modem_selected;
848 static OFono_Pending *_ofono_multiparty(const char *method,
849 OFono_Simple_Cb cb, const void *data)
854 OFono_Simple_Cb_Context *ctx = NULL;
855 OFono_Modem *m = _modem_selected_get();
857 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
860 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
861 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
866 msg = dbus_message_new_method_call(
867 bus_id, m->base.path,
868 OFONO_PREFIX OFONO_VOICE_IFACE,
872 goto error_no_message;
874 if (!dbus_message_append_args(msg, DBUS_TYPE_INVALID))
875 goto error_message_append;
878 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
882 error_message_append:
883 dbus_message_unref(msg);
886 cb((void *)data, OFONO_ERROR_FAILED);
891 OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb,
894 OFono_Simple_Cb_Context *ctx = NULL;
898 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
901 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
902 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
907 msg = dbus_message_new_method_call(
908 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Hangup");
912 INF("Hangup(%s)", c->base.path);
913 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
918 cb((void *)data, OFONO_ERROR_FAILED);
923 OFono_Pending *ofono_call_answer(OFono_Call *c, OFono_Simple_Cb cb,
926 OFono_Simple_Cb_Context *ctx = NULL;
930 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
933 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
934 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
939 msg = dbus_message_new_method_call(
940 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Answer");
944 INF("Answer(%s)", c->base.path);
945 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
950 cb((void *)data, OFONO_ERROR_FAILED);
955 OFono_Call_State ofono_call_state_get(const OFono_Call *c)
957 EINA_SAFETY_ON_NULL_RETURN_VAL(c, OFONO_CALL_STATE_DISCONNECTED);
961 const char *ofono_call_name_get(const OFono_Call *c)
963 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
967 const char *ofono_call_line_id_get(const OFono_Call *c)
969 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
973 Eina_Bool ofono_call_multiparty_get(const OFono_Call *c)
975 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
976 return c->multiparty;
979 double ofono_call_start_time_get(const OFono_Call *c)
981 EINA_SAFETY_ON_NULL_RETURN_VAL(c, -1.0);
982 return c->start_time;
985 time_t ofono_call_full_start_time_get(const OFono_Call *c)
987 EINA_SAFETY_ON_NULL_RETURN_VAL(c, 0);
988 return c->full_start_time;
991 static void _ofono_calls_get_reply(void *data, DBusMessage *msg,
994 OFono_Modem *m = data;
995 DBusMessageIter array, dict;
999 ERR("%s: %s", err->name, err->message);
1005 eina_hash_free_buckets(m->calls);
1007 if (!dbus_message_iter_init(msg, &array)) {
1008 ERR("Could not get calls");
1012 dbus_message_iter_recurse(&array, &dict);
1013 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
1014 dbus_message_iter_next(&dict)) {
1015 DBusMessageIter value, properties;
1018 dbus_message_iter_recurse(&dict, &value);
1019 dbus_message_iter_get_basic(&value, &path);
1021 dbus_message_iter_next(&value);
1022 dbus_message_iter_recurse(&value, &properties);
1024 _call_add(m, path, &properties);
1028 static void _modem_calls_load(OFono_Modem *m)
1030 DBusMessage *msg = dbus_message_new_method_call(
1031 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE,
1034 DBG("Get calls of %s", m->base.path);
1035 _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m);
1038 static OFono_Sent_SMS *_sent_sms_new(const char *path)
1040 OFono_Sent_SMS *sms = calloc(1, sizeof(OFono_Sent_SMS));
1041 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
1043 sms->base.path = eina_stringshare_add(path);
1044 EINA_SAFETY_ON_NULL_GOTO(sms->base.path, error_path);
1053 static void _sent_sms_free(OFono_Sent_SMS *sms)
1055 DBG("sms=%p %s", sms, sms->base.path);
1056 eina_stringshare_del(sms->destination);
1057 eina_stringshare_del(sms->message);
1058 _bus_object_free(&sms->base);
1061 static OFono_Modem *_modem_new(const char *path)
1063 OFono_Modem *m = calloc(1, sizeof(OFono_Modem));
1064 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
1066 m->base.path = eina_stringshare_add(path);
1067 EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
1069 m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free));
1070 EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls);
1072 m->sent_sms = eina_hash_string_small_new(EINA_FREE_CB(_sent_sms_free));
1073 EINA_SAFETY_ON_NULL_GOTO(m->sent_sms, error_sent_sms);
1078 eina_hash_free(m->calls);
1080 eina_stringshare_del(m->base.path);
1086 static void _modem_free(OFono_Modem *m)
1088 DBG("m=%p %s", m, m->base.path);
1090 if (modem_selected == m)
1091 modem_selected = NULL;
1093 eina_stringshare_del(m->name);
1094 eina_stringshare_del(m->serial);
1095 eina_stringshare_del(m->voicemail_number);
1096 eina_stringshare_del(m->serv_center_addr);
1097 eina_stringshare_del(m->msg_bearer);
1098 eina_stringshare_del(m->msg_alphabet);
1100 eina_hash_free(m->calls);
1101 eina_hash_free(m->sent_sms);
1103 _bus_object_free(&m->base);
1107 static void _call_volume_property_update(OFono_Modem *m, const char *prop_name,
1108 DBusMessageIter *iter)
1111 if (strcmp(prop_name, "Muted") == 0) {
1112 m->muted = _dbus_bool_get(iter);
1113 DBG("%s Muted %d", m->base.path, m->muted);
1114 } else if (strcmp(prop_name, "SpeakerVolume") == 0) {
1115 dbus_message_iter_get_basic(iter, &m->speaker_volume);
1116 DBG("%s Speaker Volume %hhu", m->base.path, m->speaker_volume);
1117 } else if (strcmp(prop_name, "MicrophoneVolume") == 0) {
1118 dbus_message_iter_get_basic(iter, &m->microphone_volume);
1119 DBG("%s Microphone Volume %hhu", m->base.path, m->speaker_volume);
1121 DBG("%s %s (unused property)", m->base.path, prop_name);
1124 static void _msg_waiting_property_update(OFono_Modem *m, const char *prop_name,
1125 DBusMessageIter *iter)
1128 if (strcmp(prop_name, "VoicemailWaiting") == 0) {
1129 m->voicemail_waiting = _dbus_bool_get(iter);
1130 DBG("%s VoicemailWaiting %d",
1131 m->base.path, m->voicemail_waiting);
1132 } else if (strcmp(prop_name, "VoicemailMessageCount") == 0) {
1133 dbus_message_iter_get_basic(iter, &m->voicemail_count);
1134 DBG("%s VoicemailMessageCount %hhu",
1135 m->base.path, m->voicemail_count);
1136 } else if (strcmp(prop_name, "VoicemailMailboxNumber") == 0) {
1138 dbus_message_iter_get_basic(iter, &s);
1139 eina_stringshare_replace(&(m->voicemail_number), s);
1140 DBG("%s VoicemailMailboxNumber %s",
1141 m->base.path, m->voicemail_number);
1143 DBG("%s %s (unused property)", m->base.path, prop_name);
1146 static OFono_USSD_State _suppl_serv_state_parse(const char *s)
1148 EINA_SAFETY_ON_NULL_RETURN_VAL(s, OFONO_USSD_STATE_IDLE);
1149 if (strcmp(s, "idle") == 0)
1150 return OFONO_USSD_STATE_IDLE;
1151 else if (strcmp(s, "active") == 0)
1152 return OFONO_USSD_STATE_ACTIVE;
1153 else if (strcmp(s, "user-response") == 0)
1154 return OFONO_USSD_STATE_USER_RESPONSE;
1156 ERR("unknown state: %s", s);
1157 return OFONO_USSD_STATE_IDLE;
1160 static void _suppl_serv_property_update(OFono_Modem *m, const char *prop_name,
1161 DBusMessageIter *iter)
1164 if (strcmp(prop_name, "State") == 0) {
1166 dbus_message_iter_get_basic(iter, &s);
1167 m->ussd_state = _suppl_serv_state_parse(s);
1168 DBG("%s USSD.State %d", m->base.path, m->ussd_state);
1170 DBG("%s %s (unused property)", m->base.path, prop_name);
1173 static void _msg_property_update(OFono_Modem *m, const char *prop_name,
1174 DBusMessageIter *iter)
1177 if (strcmp(prop_name, "ServiceCenterAddress") == 0) {
1179 dbus_message_iter_get_basic(iter, &str);
1180 DBG("%s ServiceCenterAddress %s", m->base.path, str);
1181 eina_stringshare_replace(&(m->serv_center_addr), str);
1182 } else if (strcmp(prop_name, "UseDeliveryReports") == 0) {
1183 m->use_delivery_reports = _dbus_bool_get(iter);
1184 DBG("%s UseDeliveryReports %hhu", m->base.path,
1185 m->use_delivery_reports);
1186 } else if (strcmp(prop_name, "Bearer") == 0) {
1188 dbus_message_iter_get_basic(iter, &str);
1189 DBG("%s Bearer %s", m->base.path, str);
1190 eina_stringshare_replace(&(m->msg_bearer), str);
1191 } else if (strcmp(prop_name, "Alphabet") == 0) {
1193 dbus_message_iter_get_basic(iter, &str);
1194 DBG("%s Alphabet %s", m->base.path, str);
1195 eina_stringshare_replace(&(m->msg_alphabet), str);
1197 DBG("%s %s (unused property)", m->base.path, prop_name);
1200 static void _notify_ofono_callbacks_modem_list(Eina_Inlist *list)
1202 OFono_Callback_List_Modem_Node *node;
1204 EINA_INLIST_FOREACH(list, node)
1205 node->cb((void *) node->cb_data);
1208 static void _call_volume_property_changed(void *data, DBusMessage *msg)
1210 OFono_Modem *m = data;
1211 DBusMessageIter iter, variant_iter;
1212 const char *prop_name;
1214 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1215 ERR("Could not handle message %p", msg);
1219 dbus_message_iter_get_basic(&iter, &prop_name);
1220 dbus_message_iter_next(&iter);
1221 dbus_message_iter_recurse(&iter, &variant_iter);
1222 _call_volume_property_update(m, prop_name, &variant_iter);
1224 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1227 static void _msg_waiting_property_changed(void *data, DBusMessage *msg)
1229 OFono_Modem *m = data;
1230 DBusMessageIter iter, variant_iter;
1231 const char *prop_name;
1233 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1234 ERR("Could not handle message %p", msg);
1238 dbus_message_iter_get_basic(&iter, &prop_name);
1239 dbus_message_iter_next(&iter);
1240 dbus_message_iter_recurse(&iter, &variant_iter);
1241 _msg_waiting_property_update(m, prop_name, &variant_iter);
1243 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1246 static void _suppl_serv_property_changed(void *data, DBusMessage *msg)
1248 OFono_Modem *m = data;
1249 DBusMessageIter iter, variant_iter;
1250 const char *prop_name;
1252 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1253 ERR("Could not handle message %p", msg);
1257 dbus_message_iter_get_basic(&iter, &prop_name);
1258 dbus_message_iter_next(&iter);
1259 dbus_message_iter_recurse(&iter, &variant_iter);
1260 _suppl_serv_property_update(m, prop_name, &variant_iter);
1262 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1265 static void _suppl_serv_notification_recv(void *data __UNUSED__,
1268 DBusMessageIter iter;
1271 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1272 ERR("Could not handle message %p", msg);
1276 dbus_message_iter_get_basic(&iter, &s);
1278 _notify_ofono_callbacks_ussd_notify_list(
1279 cbs_ussd_notify, EINA_FALSE, s);
1282 static void _suppl_serv_request_recv(void *data __UNUSED__, DBusMessage *msg)
1284 DBusMessageIter iter;
1287 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1288 ERR("Could not handle message %p", msg);
1292 dbus_message_iter_get_basic(&iter, &s);
1294 _notify_ofono_callbacks_ussd_notify_list(cbs_ussd_notify, EINA_TRUE, s);
1297 static void _msg_property_changed(void *data, DBusMessage *msg)
1299 OFono_Modem *m = data;
1300 DBusMessageIter iter, variant_iter;
1301 const char *prop_name;
1303 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1304 ERR("Could not handle message %p", msg);
1308 dbus_message_iter_get_basic(&iter, &prop_name);
1309 dbus_message_iter_next(&iter);
1310 dbus_message_iter_recurse(&iter, &variant_iter);
1311 _msg_property_update(m, prop_name, &variant_iter);
1313 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1316 static OFono_Sent_SMS_State _sent_sms_state_parse(const char *str)
1318 if (strcmp(str, "pending") == 0)
1319 return OFONO_SENT_SMS_STATE_PENDING;
1320 else if (strcmp(str, "failed") == 0)
1321 return OFONO_SENT_SMS_STATE_FAILED;
1322 else if (strcmp(str, "sent") == 0)
1323 return OFONO_SENT_SMS_STATE_SENT;
1325 ERR("unknown message state: %s", str);
1326 return OFONO_SENT_SMS_STATE_FAILED;
1329 static void _sent_sms_property_update(OFono_Sent_SMS *sms, const char *key,
1330 DBusMessageIter *value)
1332 if (strcmp(key, "State") == 0) {
1334 OFono_Sent_SMS_State state;
1335 dbus_message_iter_get_basic(value, &str);
1336 state = _sent_sms_state_parse(str);
1337 DBG("%s State %d %s", sms->base.path, state, str);
1340 DBG("%s %s (unused property)", sms->base.path, key);
1343 static void _notify_ofono_callbacks_sent_sms(OFono_Error err,
1344 OFono_Sent_SMS *sms)
1346 OFono_Callback_List_Sent_SMS_Node *node;
1348 EINA_INLIST_FOREACH(cbs_sent_sms_changed, node)
1349 node->cb((void *) node->cb_data, err, sms);
1352 static void _sent_sms_property_changed(void *data, DBusMessage *msg)
1354 OFono_Sent_SMS *sms = data;
1355 DBusMessageIter iter, value;
1358 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1359 ERR("Could not handle message %p", msg);
1363 DBG("path=%s", sms->base.path);
1365 dbus_message_iter_get_basic(&iter, &key);
1366 dbus_message_iter_next(&iter);
1367 dbus_message_iter_recurse(&iter, &value);
1368 _sent_sms_property_update(sms, key, &value);
1370 _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms);
1373 static void _notify_ofono_callbacks_incoming_sms(unsigned int sms_class,
1376 const char *message)
1378 OFono_Callback_List_Incoming_SMS_Node *node;
1380 EINA_INLIST_FOREACH(cbs_incoming_sms, node) {
1381 node->cb((void *) node->cb_data, sms_class, timestamp, sender,
1386 static void _msg_notify(unsigned int sms_class, DBusMessageIter *iter)
1388 DBusMessageIter info;
1389 const char *message = NULL;
1390 const char *sender = NULL;
1391 const char *orig_timestamp = NULL;
1392 const char *local_timestamp = NULL;
1395 dbus_message_iter_get_basic(iter, &message);
1396 EINA_SAFETY_ON_NULL_RETURN(message);
1397 DBG("Message '%s'", message);
1399 dbus_message_iter_next(iter);
1400 dbus_message_iter_recurse(iter, &info);
1401 for (; dbus_message_iter_get_arg_type(&info) == DBUS_TYPE_DICT_ENTRY;
1402 dbus_message_iter_next(&info)) {
1403 DBusMessageIter entry, value;
1406 dbus_message_iter_recurse(&info, &entry);
1407 dbus_message_iter_get_basic(&entry, &key);
1409 dbus_message_iter_next(&entry);
1410 dbus_message_iter_recurse(&entry, &value);
1412 if (strcmp(key, "Sender") == 0) {
1413 dbus_message_iter_get_basic(&value, &sender);
1414 DBG("Sender %s", sender);
1415 } else if (strcmp(key, "SentTime") == 0) {
1416 dbus_message_iter_get_basic(&value, &orig_timestamp);
1417 DBG("SentTime %s", orig_timestamp);
1418 } else if (strcmp(key, "LocalSentTime") == 0) {
1419 dbus_message_iter_get_basic(&value, &local_timestamp);
1420 DBG("LocalSentTime %s", local_timestamp);
1422 DBG("%s (unused property)", key);
1425 EINA_SAFETY_ON_NULL_RETURN(sender);
1426 EINA_SAFETY_ON_NULL_RETURN(local_timestamp);
1427 timestamp = _ofono_time_parse(local_timestamp);
1429 _notify_ofono_callbacks_incoming_sms(sms_class, timestamp, sender,
1433 static void _msg_immediate(void *data, DBusMessage *msg)
1435 OFono_Modem *m = data;
1436 DBusMessageIter iter;
1438 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1439 ERR("Could not handle message %p", msg);
1443 DBG("path=%s", m->base.path);
1444 _msg_notify(0, &iter);
1447 static void _msg_incoming(void *data, DBusMessage *msg)
1449 OFono_Modem *m = data;
1450 DBusMessageIter iter;
1452 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1453 ERR("Could not handle message %p", msg);
1457 DBG("path=%s", m->base.path);
1458 _msg_notify(1, &iter);
1461 static OFono_Sent_SMS *_sent_sms_common_add(OFono_Modem *m, const char *path)
1463 OFono_Sent_SMS *sms = _sent_sms_new(path);
1464 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
1465 eina_hash_add(m->sent_sms, sms->base.path, sms);
1467 _bus_object_signal_listen(&sms->base,
1468 OFONO_PREFIX "Message",
1470 _sent_sms_property_changed, sms);
1474 static OFono_Sent_SMS *_sent_sms_pending_add(OFono_Modem *m, const char *path,
1475 OFono_Sent_SMS_Cb_Context *ctx)
1477 OFono_Sent_SMS *sms;
1479 DBG("path=%s, ctx=%p", path, ctx);
1481 sms = _sent_sms_common_add(m, path);
1482 sms->pending_send = ctx;
1486 static void _msg_add(OFono_Modem *m, const char *path, DBusMessageIter *prop)
1488 OFono_Sent_SMS *sms;
1490 DBG("path=%s, prop=%p", path, prop);
1492 sms = eina_hash_find(m->sent_sms, path);
1494 DBG("SMS already exists %p (%s)", sms, path);
1496 sms = _sent_sms_common_add(m, path);
1497 EINA_SAFETY_ON_NULL_RETURN(sms);
1500 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
1501 dbus_message_iter_next(prop)) {
1502 DBusMessageIter entry, value;
1505 dbus_message_iter_recurse(prop, &entry);
1506 dbus_message_iter_get_basic(&entry, &key);
1508 dbus_message_iter_next(&entry);
1509 dbus_message_iter_recurse(&entry, &value);
1511 _sent_sms_property_update(sms, key, &value);
1514 if (sms->pending_send) {
1515 OFono_Sent_SMS_Cb_Context *ctx = sms->pending_send;
1517 ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, sms);
1518 sms->destination = ctx->destination;
1519 sms->message = ctx->message;
1520 sms->timestamp = time(NULL);
1522 sms->pending_send = NULL;
1525 _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms);
1528 static void _msg_added(void *data, DBusMessage *msg)
1530 OFono_Modem *m = data;
1531 DBusMessageIter iter, properties;
1534 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1535 ERR("Could not handle message %p", msg);
1539 dbus_message_iter_get_basic(&iter, &path);
1541 dbus_message_iter_next(&iter);
1542 dbus_message_iter_recurse(&iter, &properties);
1544 _msg_add(m, path, &properties);
1547 static void _msg_remove(OFono_Modem *m, const char *path)
1549 DBG("path=%s", path);
1550 eina_hash_del_by_key(m->sent_sms, path);
1553 static void _msg_removed(void *data, DBusMessage *msg)
1555 OFono_Modem *m = data;
1560 ERR("Could not handle message %p", msg);
1564 dbus_error_init(&err);
1565 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
1567 ERR("Could not get MessageRemoved arguments: %s: %s",
1568 err.name, err.message);
1569 dbus_error_free(&err);
1573 _msg_remove(m, path);
1576 static unsigned int _modem_interfaces_extract(DBusMessageIter *array)
1578 DBusMessageIter entry;
1579 unsigned int interfaces = 0;
1581 dbus_message_iter_recurse(array, &entry);
1582 for (; dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING;
1583 dbus_message_iter_next(&entry)) {
1584 const struct API_Interface_Map *itr;
1588 dbus_message_iter_get_basic(&entry, &name);
1590 if (strncmp(name, OFONO_PREFIX, strlen(OFONO_PREFIX)) != 0)
1593 name += strlen(OFONO_PREFIX);
1594 namelen = strlen(name);
1596 DBG("interface: %s", name);
1597 for (itr = api_iface_map; itr->name != NULL; itr++) {
1598 if ((itr->namelen == namelen) &&
1599 (memcmp(itr->name, name, namelen) == 0)) {
1600 interfaces |= itr->bit;
1604 if (itr->name == NULL)
1605 WRN("ignored %s", name);
1611 static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces)
1614 if (((m->interfaces & OFONO_API_CALL_VOL) == 0) &&
1615 (ifaces & OFONO_API_CALL_VOL) == OFONO_API_CALL_VOL)
1616 _ofono_call_volume_properties_get(m);
1618 if (((m->interfaces & OFONO_API_MSG_WAITING) == 0) &&
1619 (ifaces & OFONO_API_MSG_WAITING) == OFONO_API_MSG_WAITING)
1620 _ofono_msg_waiting_properties_get(m);
1622 if (((m->interfaces & OFONO_API_SUPPL_SERV) == 0) &&
1623 (ifaces & OFONO_API_SUPPL_SERV) == OFONO_API_SUPPL_SERV)
1624 _ofono_suppl_serv_properties_get(m);
1626 if (((m->interfaces & OFONO_API_MSG) == 0) &&
1627 (ifaces & OFONO_API_MSG) == OFONO_API_MSG)
1628 _ofono_msg_properties_get(m);
1631 static void _modem_property_update(OFono_Modem *m, const char *key,
1632 DBusMessageIter *value)
1634 if (strcmp(key, "Powered") == 0) {
1635 m->powered = _dbus_bool_get(value);
1636 DBG("%s Powered %d", m->base.path, m->powered);
1637 } else if (strcmp(key, "Online") == 0) {
1638 m->online = _dbus_bool_get(value);
1639 DBG("%s Online %d", m->base.path, m->online);
1640 } else if (strcmp(key, "Interfaces") == 0) {
1641 unsigned int ifaces = _modem_interfaces_extract(value);
1642 DBG("%s Interfaces 0x%02x", m->base.path, ifaces);
1643 if (m->interfaces != ifaces) {
1644 _modem_update_interfaces(m, ifaces);
1645 m->interfaces = ifaces;
1647 if (modem_selected && modem_path_wanted &&
1648 modem_selected->base.path != modem_path_wanted)
1649 modem_selected = NULL;
1651 } else if (strcmp(key, "Serial") == 0) {
1653 dbus_message_iter_get_basic(value, &serial);
1654 DBG("%s Serial %s", m->base.path, serial);
1655 eina_stringshare_replace(&m->serial, serial);
1656 } else if (strcmp(key, "Type") == 0) {
1658 dbus_message_iter_get_basic(value, &type);
1659 DBG("%s Type %s", m->base.path, type);
1662 m->ignored = EINA_FALSE;
1666 m->ignored = EINA_TRUE;
1667 EINA_LIST_FOREACH(modem_types, n, t) {
1668 if (strcmp(t, type) == 0) {
1669 m->ignored = EINA_FALSE;
1674 INF("Modem %s type %s is ignored",
1675 m->base.path, type);
1678 DBG("%s %s (unused property)", m->base.path, key);
1681 static void _ofono_call_volume_properties_get_reply(void *data,
1685 OFono_Modem *m = data;
1686 DBusMessageIter iter, prop;
1688 if (dbus_error_is_set(err)) {
1689 DBG("%s: %s", err->name, err->message);
1693 dbus_message_iter_init(msg, &iter);
1694 dbus_message_iter_recurse(&iter, &prop);
1696 DBG("m=%s", m->base.path);
1697 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1698 dbus_message_iter_next(&prop)) {
1699 DBusMessageIter entry, value;
1702 dbus_message_iter_recurse(&prop, &entry);
1703 dbus_message_iter_get_basic(&entry, &key);
1705 dbus_message_iter_next(&entry);
1706 dbus_message_iter_recurse(&entry, &value);
1707 _call_volume_property_update(m, key, &value);
1710 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1713 static void _ofono_call_volume_properties_get(OFono_Modem *m)
1716 msg = dbus_message_new_method_call(bus_id, m->base.path,
1718 OFONO_CALL_VOL_IFACE,
1720 DBG("m=%s", m->base.path);
1721 EINA_SAFETY_ON_NULL_RETURN(msg);
1723 _bus_object_message_send(&m->base, msg,
1724 _ofono_call_volume_properties_get_reply, m);
1727 static void _ofono_msg_waiting_properties_get_reply(void *data,
1731 OFono_Modem *m = data;
1732 DBusMessageIter iter, prop;
1734 if (dbus_error_is_set(err)) {
1735 DBG("%s: %s", err->name, err->message);
1739 dbus_message_iter_init(msg, &iter);
1740 dbus_message_iter_recurse(&iter, &prop);
1742 DBG("m=%s", m->base.path);
1743 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1744 dbus_message_iter_next(&prop)) {
1745 DBusMessageIter entry, value;
1748 dbus_message_iter_recurse(&prop, &entry);
1749 dbus_message_iter_get_basic(&entry, &key);
1751 dbus_message_iter_next(&entry);
1752 dbus_message_iter_recurse(&entry, &value);
1753 _msg_waiting_property_update(m, key, &value);
1756 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1759 static void _ofono_msg_waiting_properties_get(OFono_Modem *m)
1762 msg = dbus_message_new_method_call(bus_id, m->base.path,
1764 OFONO_MSG_WAITING_IFACE,
1766 DBG("m=%s", m->base.path);
1767 EINA_SAFETY_ON_NULL_RETURN(msg);
1769 _bus_object_message_send(&m->base, msg,
1770 _ofono_msg_waiting_properties_get_reply, m);
1773 static void _ofono_suppl_serv_properties_get_reply(void *data,
1777 OFono_Modem *m = data;
1778 DBusMessageIter iter, prop;
1780 if (dbus_error_is_set(err)) {
1781 DBG("%s: %s", err->name, err->message);
1785 dbus_message_iter_init(msg, &iter);
1786 dbus_message_iter_recurse(&iter, &prop);
1788 DBG("m=%s", m->base.path);
1789 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1790 dbus_message_iter_next(&prop)) {
1791 DBusMessageIter entry, value;
1794 dbus_message_iter_recurse(&prop, &entry);
1795 dbus_message_iter_get_basic(&entry, &key);
1797 dbus_message_iter_next(&entry);
1798 dbus_message_iter_recurse(&entry, &value);
1799 _suppl_serv_property_update(m, key, &value);
1802 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1805 static void _ofono_suppl_serv_properties_get(OFono_Modem *m)
1808 msg = dbus_message_new_method_call(bus_id, m->base.path,
1810 OFONO_SUPPL_SERV_IFACE,
1812 DBG("m=%s", m->base.path);
1813 EINA_SAFETY_ON_NULL_RETURN(msg);
1815 _bus_object_message_send(&m->base, msg,
1816 _ofono_suppl_serv_properties_get_reply, m);
1820 static void _ofono_msg_properties_get_reply(void *data, DBusMessage *msg,
1823 OFono_Modem *m = data;
1824 DBusMessageIter iter, prop;
1826 if (dbus_error_is_set(err)) {
1827 DBG("%s: %s", err->name, err->message);
1831 dbus_message_iter_init(msg, &iter);
1832 dbus_message_iter_recurse(&iter, &prop);
1834 DBG("m=%s", m->base.path);
1835 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1836 dbus_message_iter_next(&prop)) {
1837 DBusMessageIter entry, value;
1840 dbus_message_iter_recurse(&prop, &entry);
1841 dbus_message_iter_get_basic(&entry, &key);
1843 dbus_message_iter_next(&entry);
1844 dbus_message_iter_recurse(&entry, &value);
1845 _msg_property_update(m, key, &value);
1848 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1851 static void _ofono_msg_properties_get(OFono_Modem *m)
1854 msg = dbus_message_new_method_call(bus_id, m->base.path,
1858 DBG("m=%s", m->base.path);
1859 EINA_SAFETY_ON_NULL_RETURN(msg);
1861 _bus_object_message_send(&m->base, msg,
1862 _ofono_msg_properties_get_reply, m);
1865 static void _modem_add(const char *path, DBusMessageIter *prop)
1869 DBG("path=%s", path);
1871 m = eina_hash_find(modems, path);
1873 DBG("Modem already exists %p (%s)", m, path);
1874 goto update_properties;
1877 m = _modem_new(path);
1878 EINA_SAFETY_ON_NULL_RETURN(m);
1879 eina_hash_add(modems, m->base.path, m);
1881 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1882 "CallAdded", _call_added, m);
1883 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1884 "CallRemoved", _call_removed, m);
1885 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1887 _call_volume_property_changed, m);
1888 _bus_object_signal_listen(&m->base,
1889 OFONO_PREFIX OFONO_MSG_WAITING_IFACE,
1891 _msg_waiting_property_changed, m);
1892 _bus_object_signal_listen(&m->base,
1893 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1895 _suppl_serv_property_changed, m);
1896 _bus_object_signal_listen(&m->base,
1897 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1898 "NotificationReceived",
1899 _suppl_serv_notification_recv, m);
1900 _bus_object_signal_listen(&m->base,
1901 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1903 _suppl_serv_request_recv, m);
1905 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1907 _msg_property_changed, m);
1908 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1909 "ImmediateMessage", _msg_immediate, m);
1910 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1911 "IncomingMessage", _msg_incoming, m);
1912 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1913 "MessageAdded", _msg_added, m);
1914 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1915 "MessageRemoved", _msg_removed, m);
1917 /* TODO: do we need to listen to BarringActive or Forwarded? */
1919 if (modem_selected && modem_path_wanted &&
1920 modem_selected->base.path != modem_path_wanted)
1921 modem_selected = NULL;
1926 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
1927 dbus_message_iter_next(prop)) {
1928 DBusMessageIter entry, value;
1931 dbus_message_iter_recurse(prop, &entry);
1932 dbus_message_iter_get_basic(&entry, &key);
1934 dbus_message_iter_next(&entry);
1935 dbus_message_iter_recurse(&entry, &value);
1937 _modem_property_update(m, key, &value);
1940 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1942 if (m->interfaces & OFONO_API_VOICE)
1943 _modem_calls_load(m);
1946 static void _modem_remove(const char *path)
1948 DBG("path=%s", path);
1949 eina_hash_del_by_key(modems, path);
1952 static void _ofono_modems_get_reply(void *data __UNUSED__, DBusMessage *msg,
1955 DBusMessageIter array, dict;
1957 pc_get_modems = NULL;
1961 ERR("%s: %s", err->name, err->message);
1967 EINA_SAFETY_ON_NULL_RETURN(modems);
1968 eina_hash_free_buckets(modems);
1970 if (!dbus_message_iter_init(msg, &array)) {
1971 ERR("Could not get modems");
1975 dbus_message_iter_recurse(&array, &dict);
1976 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
1977 dbus_message_iter_next(&dict)) {
1978 DBusMessageIter value, properties;
1981 dbus_message_iter_recurse(&dict, &value);
1982 dbus_message_iter_get_basic(&value, &path);
1984 dbus_message_iter_next(&value);
1985 dbus_message_iter_recurse(&value, &properties);
1987 _modem_add(path, &properties);
1991 static void _modem_added(void *data __UNUSED__, DBusMessage *msg)
1993 DBusMessageIter iter, properties;
1996 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1997 ERR("Could not handle message %p", msg);
2001 dbus_message_iter_get_basic(&iter, &path);
2003 dbus_message_iter_next(&iter);
2004 dbus_message_iter_recurse(&iter, &properties);
2006 _modem_add(path, &properties);
2009 static void _modem_removed(void *data __UNUSED__, DBusMessage *msg)
2015 ERR("Could not handle message %p", msg);
2019 dbus_error_init(&err);
2020 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
2022 ERR("Could not get ModemRemoved arguments: %s: %s",
2023 err.name, err.message);
2024 dbus_error_free(&err);
2028 _modem_remove(path);
2031 static void _modem_property_changed(void *data __UNUSED__, DBusMessage *msg)
2035 DBusMessageIter iter, value;
2038 if (!msg || !dbus_message_iter_init(msg, &iter)) {
2039 ERR("Could not handle message %p", msg);
2043 path = dbus_message_get_path(msg);
2044 DBG("path=%s", path);
2046 m = eina_hash_find(modems, path);
2048 DBG("Modem is unknown (%s)", path);
2052 dbus_message_iter_get_basic(&iter, &key);
2053 dbus_message_iter_next(&iter);
2054 dbus_message_iter_recurse(&iter, &value);
2055 _modem_property_update(m, key, &value);
2057 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
2060 static void _modems_load(void)
2062 DBusMessage *msg = dbus_message_new_method_call(
2063 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
2066 dbus_pending_call_cancel(pc_get_modems);
2069 pc_get_modems = e_dbus_message_send(
2070 bus_conn, msg, _ofono_modems_get_reply, -1, NULL);
2071 dbus_message_unref(msg);
2074 static void _ofono_connected(const char *id)
2077 bus_id = strdup(id);
2079 sig_modem_added = e_dbus_signal_handler_add(
2080 bus_conn, bus_id, "/",
2081 OFONO_PREFIX OFONO_MANAGER_IFACE,
2083 _modem_added, NULL);
2085 sig_modem_removed = e_dbus_signal_handler_add(
2086 bus_conn, bus_id, "/",
2087 OFONO_PREFIX OFONO_MANAGER_IFACE,
2089 _modem_removed, NULL);
2091 sig_modem_prop_changed = e_dbus_signal_handler_add(
2092 bus_conn, bus_id, NULL,
2093 OFONO_PREFIX OFONO_MODEM_IFACE,
2095 _modem_property_changed, NULL);
2099 _notify_ofono_callbacks_modem_list(cbs_modem_connected);
2102 static void _ofono_disconnected(void)
2104 eina_hash_free_buckets(modems);
2106 if (sig_modem_added) {
2107 e_dbus_signal_handler_del(bus_conn, sig_modem_added);
2108 sig_modem_added = NULL;
2111 if (sig_modem_removed) {
2112 e_dbus_signal_handler_del(bus_conn, sig_modem_removed);
2113 sig_modem_removed = NULL;
2116 if (sig_modem_prop_changed) {
2117 e_dbus_signal_handler_del(bus_conn, sig_modem_prop_changed);
2118 sig_modem_prop_changed = NULL;
2122 _notify_ofono_callbacks_modem_list(cbs_modem_disconnected);
2128 static void _name_owner_changed(void *data __UNUSED__, DBusMessage *msg)
2131 const char *name, *from, *to;
2133 dbus_error_init(&err);
2134 if (!dbus_message_get_args(msg, &err,
2135 DBUS_TYPE_STRING, &name,
2136 DBUS_TYPE_STRING, &from,
2137 DBUS_TYPE_STRING, &to,
2138 DBUS_TYPE_INVALID)) {
2139 ERR("Could not get NameOwnerChanged arguments: %s: %s",
2140 err.name, err.message);
2141 dbus_error_free(&err);
2145 if (strcmp(name, bus_name) != 0)
2148 DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
2150 if (from[0] == '\0' && to[0] != '\0') {
2151 INF("oFono appeared as %s", to);
2152 _ofono_connected(to);
2153 } else if (from[0] != '\0' && to[0] == '\0') {
2154 INF("oFono disappeared from %s", from);
2155 _ofono_disconnected();
2159 static void _ofono_get_name_owner(void *data __UNUSED__, DBusMessage *msg, DBusError *err)
2161 DBusMessageIter itr;
2166 ERR("%s: %s", err->name, err->message);
2172 dbus_message_iter_init(msg, &itr);
2173 dbus_message_iter_get_basic(&itr, &id);
2174 if (!id || id[0] == '\0') {
2175 ERR("No name owner fo %s!", bus_name);
2179 INF("oFono bus id: %s", id);
2180 _ofono_connected(id);
2183 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
2184 const char *new, OFono_Simple_Cb cb,
2187 OFono_Simple_Cb_Context *ctx = NULL;
2188 OFono_Error err = OFONO_ERROR_OFFLINE;
2191 OFono_Modem *m = _modem_selected_get();
2192 EINA_SAFETY_ON_NULL_GOTO(m, error);
2193 EINA_SAFETY_ON_NULL_GOTO(what, error);
2194 EINA_SAFETY_ON_NULL_GOTO(old, error);
2195 EINA_SAFETY_ON_NULL_GOTO(new, error);
2197 if ((m->interfaces & OFONO_API_SIM) == 0)
2199 err = OFONO_ERROR_FAILED;
2202 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2203 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2208 msg = dbus_message_new_method_call(
2209 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
2214 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
2215 DBUS_TYPE_STRING, &old,
2216 DBUS_TYPE_STRING, &new,
2220 INF("ChangePin(%s, %s, %s)", what, old, new);
2221 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2225 dbus_message_unref(msg);
2228 cb((void *)data, err);
2233 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
2234 const char *new, OFono_Simple_Cb cb,
2237 OFono_Simple_Cb_Context *ctx = NULL;
2238 OFono_Error err = OFONO_ERROR_OFFLINE;
2241 OFono_Modem *m = _modem_selected_get();
2242 EINA_SAFETY_ON_NULL_GOTO(m, error);
2243 EINA_SAFETY_ON_NULL_GOTO(what, error);
2244 EINA_SAFETY_ON_NULL_GOTO(puk, error);
2245 EINA_SAFETY_ON_NULL_GOTO(new, error);
2247 if ((m->interfaces & OFONO_API_SIM) == 0)
2249 err = OFONO_ERROR_FAILED;
2252 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2253 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2258 msg = dbus_message_new_method_call(
2259 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
2263 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
2264 DBUS_TYPE_STRING, &puk,
2265 DBUS_TYPE_STRING, &new,
2269 INF("ResetPin(%s, %s, %s)", what, puk, new);
2270 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2274 dbus_message_unref(msg);
2277 cb((void *)data, err);
2282 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
2283 DBusMessageIter *itr)
2285 const char *ussd_response;
2287 if (dbus_message_iter_get_arg_type(itr) != DBUS_TYPE_STRING) {
2288 ERR("Invalid type: %c (expected: %c)",
2289 dbus_message_iter_get_arg_type(itr), DBUS_TYPE_STRING);
2292 dbus_message_iter_get_basic(itr, &ussd_response);
2293 EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
2294 return strdup(ussd_response);
2297 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
2298 DBusMessageIter *dict)
2300 for (; dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY;
2301 dbus_message_iter_next(dict)) {
2302 DBusMessageIter e, v;
2303 const char *key, *value;
2305 dbus_message_iter_recurse(dict, &e);
2306 dbus_message_iter_get_basic(&e, &key);
2308 dbus_message_iter_next(&e);
2309 dbus_message_iter_recurse(&e, &v);
2310 dbus_message_iter_get_basic(&v, &value);
2312 eina_strbuf_append_printf(buf, " %s=%s<br>",
2317 static char *_ss_initiate_convert_call1(const char *type, DBusMessageIter *itr)
2319 DBusMessageIter array, dict;
2320 const char *ss_op, *service;
2324 dbus_message_iter_recurse(itr, &array);
2326 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2327 ERR("Invalid type: %c (expected: %c)",
2328 dbus_message_iter_get_arg_type(&array),
2332 dbus_message_iter_get_basic(&array, &ss_op);
2333 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2335 if (!dbus_message_iter_next(&array)) {
2336 ERR("Missing %s service", type);
2340 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2341 ERR("Invalid type: %c (expected: %c)",
2342 dbus_message_iter_get_arg_type(&array),
2346 dbus_message_iter_get_basic(&array, &service);
2347 EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
2349 if (!dbus_message_iter_next(&array)) {
2350 ERR("Missing %s information", type);
2354 buf = eina_strbuf_new();
2355 eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
2356 type, ss_op, service);
2358 dbus_message_iter_recurse(&array, &dict);
2359 _ss_initiate_cb_dict_convert(buf, &dict);
2361 str = eina_strbuf_string_steal(buf);
2362 eina_strbuf_free(buf);
2366 static char *_ss_initiate_convert_call_waiting(const char *type,
2367 DBusMessageIter *itr)
2369 DBusMessageIter array, dict;
2374 dbus_message_iter_recurse(itr, &array);
2376 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2377 ERR("Invalid type: %c (expected: %c)",
2378 dbus_message_iter_get_arg_type(&array),
2382 dbus_message_iter_get_basic(&array, &ss_op);
2383 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2385 if (!dbus_message_iter_next(&array)) {
2386 ERR("Missing %s information", type);
2390 buf = eina_strbuf_new();
2391 eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
2394 dbus_message_iter_recurse(&array, &dict);
2395 _ss_initiate_cb_dict_convert(buf, &dict);
2397 str = eina_strbuf_string_steal(buf);
2398 eina_strbuf_free(buf);
2402 static char *_ss_initiate_convert_call2(const char *type,
2403 DBusMessageIter *itr)
2405 DBusMessageIter array;
2406 const char *ss_op, *status;
2410 dbus_message_iter_recurse(itr, &array);
2412 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2413 ERR("Invalid type: %c (expected: %c)",
2414 dbus_message_iter_get_arg_type(&array),
2418 dbus_message_iter_get_basic(&array, &ss_op);
2419 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2421 if (!dbus_message_iter_next(&array)) {
2422 ERR("Missing %s status", type);
2426 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2427 ERR("Invalid type: %c (expected: %c)",
2428 dbus_message_iter_get_arg_type(&array),
2432 dbus_message_iter_get_basic(&array, &status);
2433 EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
2435 buf = eina_strbuf_new();
2436 eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
2437 type, ss_op, status);
2439 str = eina_strbuf_string_steal(buf);
2440 eina_strbuf_free(buf);
2444 static const struct SS_Initiate_Convert_Map {
2447 char *(*convert)(const char *type, DBusMessageIter *itr);
2448 } ss_initiate_convert_map[] = {
2449 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
2450 MAP("USSD", _ss_initiate_convert_ussd),
2451 MAP("CallBarring", _ss_initiate_convert_call1),
2452 MAP("CallForwarding", _ss_initiate_convert_call1),
2453 MAP("CallWaiting", _ss_initiate_convert_call_waiting),
2454 MAP("CallingLinePresentation", _ss_initiate_convert_call2),
2455 MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
2456 MAP("CallingLineRestriction", _ss_initiate_convert_call2),
2457 MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
2462 static char *_ss_initiate_convert(DBusMessage *msg)
2464 DBusMessageIter array, variant;
2465 const struct SS_Initiate_Convert_Map *citr;
2466 const char *type = NULL;
2469 if (!dbus_message_iter_init(msg, &array))
2472 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2473 ERR("Invalid type for first argument: %c (expected: %c)",
2474 dbus_message_iter_get_arg_type(&array),
2478 dbus_message_iter_get_basic(&array, &type);
2480 ERR("Couldn't get SupplementaryServices.Initiate type");
2483 DBG("type: %s", type);
2485 if (!dbus_message_iter_next(&array)) {
2486 ERR("Couldn't get SupplementaryServices.Initiate payload");
2489 dbus_message_iter_recurse(&array, &variant);
2491 typelen = strlen(type);
2492 for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
2493 if ((citr->typelen == typelen) &&
2494 (memcmp(citr->type, type, typelen) == 0)) {
2495 return citr->convert(type, &variant);
2498 ERR("Could not convert SupplementaryServices.Initiate type %s", type);
2504 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
2506 OFono_String_Cb_Context *ctx = NULL;
2507 OFono_Error err = OFONO_ERROR_OFFLINE;
2510 OFono_Modem *m = _modem_selected_get();
2511 EINA_SAFETY_ON_NULL_GOTO(m, error);
2512 EINA_SAFETY_ON_NULL_GOTO(command, error);
2514 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2516 err = OFONO_ERROR_FAILED;
2518 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2519 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2522 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2523 ctx->convert = _ss_initiate_convert;
2525 msg = dbus_message_new_method_call(
2526 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2531 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &command,
2535 INF("SupplementaryServices.Initiate(%s)", command);
2536 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2540 dbus_message_unref(msg);
2543 cb((void *)data, err, NULL);
2548 static char *_ussd_respond_convert(DBusMessage *msg)
2550 DBusMessageIter itr;
2553 if (!msg || !dbus_message_iter_init(msg, &itr)) {
2554 ERR("Could not handle message %p", msg);
2558 if (dbus_message_iter_get_arg_type(&itr) != DBUS_TYPE_STRING) {
2559 ERR("Invalid type: %c (expected: %c)",
2560 dbus_message_iter_get_arg_type(&itr), DBUS_TYPE_STRING);
2563 dbus_message_iter_get_basic(&itr, &s);
2564 EINA_SAFETY_ON_NULL_RETURN_VAL(s, NULL);
2568 OFono_Pending *ofono_ussd_respond(const char *string,
2569 OFono_String_Cb cb, const void *data)
2571 OFono_String_Cb_Context *ctx = NULL;
2572 OFono_Error err = OFONO_ERROR_OFFLINE;
2575 OFono_Modem *m = _modem_selected_get();
2576 EINA_SAFETY_ON_NULL_GOTO(m, error);
2577 EINA_SAFETY_ON_NULL_GOTO(string, error);
2579 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2581 err = OFONO_ERROR_FAILED;
2583 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2584 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2587 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2588 ctx->convert = _ussd_respond_convert;
2590 msg = dbus_message_new_method_call(
2591 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2596 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &string,
2600 INF("SupplementaryServices.Respond(%s)", string);
2601 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2605 dbus_message_unref(msg);
2608 cb((void *)data, err, NULL);
2613 OFono_Pending *ofono_ussd_cancel(OFono_Simple_Cb cb, const void *data)
2615 return _ofono_simple_do(OFONO_API_SUPPL_SERV, "Cancel", cb, data);
2618 static void _ofono_dial_reply(void *data, DBusMessage *msg, DBusError *err)
2620 OFono_Call_Cb_Context *ctx = data;
2621 OFono_Call *c = NULL;
2622 OFono_Error oe = OFONO_ERROR_NONE;
2625 DBG("%s: %s", err->name, err->message);
2626 oe = _ofono_error_parse(err->name);
2630 dbus_error_init(&e);
2631 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
2632 &path, DBUS_TYPE_INVALID)) {
2633 ERR("Could not get Dial reply: %s: %s",
2635 dbus_error_free(&e);
2636 oe = OFONO_ERROR_FAILED;
2638 c = eina_hash_find(ctx->modem->calls, path);
2639 DBG("path=%s, existing call=%p", path, c);
2641 c = _call_pending_add(ctx->modem, path, ctx);
2643 /* ctx->cb will be dispatched on
2644 * CallAdded signal handler.
2650 ERR("Could not find call %s", path);
2651 oe = OFONO_ERROR_FAILED;
2656 ctx->cb((void *)ctx->data, oe, c);
2661 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
2662 OFono_Call_Cb cb, const void *data)
2664 OFono_Call_Cb_Context *ctx = NULL;
2665 OFono_Error err = OFONO_ERROR_OFFLINE;
2668 OFono_Modem *m = _modem_selected_get();
2669 EINA_SAFETY_ON_NULL_GOTO(m, error);
2672 if ((m->interfaces & OFONO_API_VOICE) == 0)
2674 err = OFONO_ERROR_FAILED;
2679 ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
2680 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2683 ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
2686 msg = dbus_message_new_method_call(
2687 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
2691 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
2692 DBUS_TYPE_STRING, &hide_callerid,
2696 INF("Dial(%s, %s)", number, hide_callerid);
2697 p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
2701 dbus_message_unref(msg);
2704 cb((void *)data, err, NULL);
2709 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
2710 OFono_Simple_Cb cb, const void *data)
2712 OFono_Simple_Cb_Context *ctx = NULL;
2713 OFono_Error err = OFONO_ERROR_OFFLINE;
2716 char iface[128] = "";
2717 const struct API_Interface_Map *itr;
2718 OFono_Modem *m = _modem_selected_get();
2719 EINA_SAFETY_ON_NULL_GOTO(m, error);
2720 EINA_SAFETY_ON_NULL_GOTO(method, error);
2722 if ((m->interfaces & api) == 0)
2724 err = OFONO_ERROR_FAILED;
2726 for (itr = api_iface_map; itr->name != NULL; itr++) {
2727 if (itr->bit == api) {
2728 snprintf(iface, sizeof(iface), "%s%s",
2729 OFONO_PREFIX, itr->name);
2733 if (iface[0] == '\0') {
2734 ERR("Could not map api %d to interface name!", api);
2739 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2740 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2745 msg = dbus_message_new_method_call(bus_id, m->base.path, iface, method);
2749 INF("%s.%s()", iface, method);
2750 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2755 cb((void *)data, err);
2760 OFono_Pending *ofono_transfer(OFono_Simple_Cb cb, const void *data)
2762 return _ofono_simple_do(OFONO_API_VOICE, "Transfer", cb, data);
2765 OFono_Pending *ofono_swap_calls(OFono_Simple_Cb cb, const void *data)
2767 return _ofono_simple_do(OFONO_API_VOICE, "SwapCalls", cb, data);
2770 OFono_Pending *ofono_release_and_answer(OFono_Simple_Cb cb, const void *data)
2772 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndAnswer", cb, data);
2775 OFono_Pending *ofono_release_and_swap(OFono_Simple_Cb cb, const void *data)
2777 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndSwap", cb, data);
2780 OFono_Pending *ofono_hold_and_answer(OFono_Simple_Cb cb, const void *data)
2782 return _ofono_simple_do(OFONO_API_VOICE, "HoldAndAnswer", cb, data);
2785 OFono_Pending *ofono_hangup_all(OFono_Simple_Cb cb, const void *data)
2787 return _ofono_simple_do(OFONO_API_VOICE, "HangupAll", cb, data);
2790 const char *ofono_modem_serial_get(void)
2792 OFono_Modem *m = _modem_selected_get();
2793 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
2797 void ofono_modem_api_require(const char *spec)
2799 unsigned int api_mask = 0;
2800 const char *name = spec;
2802 EINA_SAFETY_ON_NULL_RETURN(spec);
2805 const struct API_Interface_Map *itr;
2807 unsigned int namelen;
2809 p = strchr(name, ',');
2813 namelen = strlen(name);
2815 for (itr = api_iface_map; itr->name != NULL; itr++) {
2816 if ((itr->namelen == namelen) &&
2817 (memcmp(itr->name, name, namelen) == 0)) {
2818 api_mask |= itr->bit;
2822 if (itr->name == NULL)
2823 WRN("Unknown oFono API: %.*s", namelen, name);
2832 DBG("API parsed: '%s' = %#x", spec, api_mask);
2834 ERR("Could not parse API: %s", spec);
2838 if (modem_api_mask == api_mask)
2840 modem_api_mask = api_mask;
2841 modem_selected = NULL;
2844 void ofono_modem_api_list(FILE *fp, const char *prefix, const char *suffix)
2846 const struct API_Interface_Map *itr;
2847 for (itr = api_iface_map; itr->name != NULL; itr++)
2848 fprintf(fp, "%s%s%s", prefix, itr->name, suffix);
2851 void ofono_modem_type_require(const char *spec)
2853 Eina_List *lst = NULL;
2854 const char *name = spec;
2856 EINA_SAFETY_ON_NULL_RETURN(spec);
2861 unsigned int namelen;
2863 p = strchr(name, ',');
2867 namelen = strlen(name);
2869 for (itr = known_modem_types; *itr != NULL; itr++) {
2870 unsigned int itrlen = strlen(*itr);
2871 if ((itrlen == namelen) &&
2872 (memcmp(*itr, name, namelen) == 0)) {
2873 lst = eina_list_append(lst, *itr);
2878 WRN("Unknown oFono type: %.*s", namelen, name);
2887 DBG("Type parsed: '%s'", spec);
2889 ERR("Could not parse type: %s", spec);
2893 eina_list_free(modem_types);
2895 modem_selected = NULL;
2898 void ofono_modem_type_list(FILE *fp, const char *prefix, const char *suffix)
2901 for (itr = known_modem_types; *itr != NULL; itr++)
2902 fprintf(fp, "%s%s%s", prefix, *itr, suffix);
2905 void ofono_modem_path_wanted_set(const char *path)
2907 if (eina_stringshare_replace(&modem_path_wanted, path))
2908 modem_selected = NULL;
2911 unsigned int ofono_modem_api_get(void)
2913 OFono_Modem *m = _modem_selected_get();
2914 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
2915 return m->interfaces;
2918 Eina_Bool ofono_init(void)
2922 if (!elm_need_e_dbus()) {
2923 CRITICAL("Elementary does not support DBus.");
2927 bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
2929 CRITICAL("Could not get DBus System Bus");
2933 modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
2934 EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
2936 e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
2937 E_DBUS_FDO_INTERFACE,
2939 _name_owner_changed, NULL);
2941 e_dbus_get_name_owner(bus_conn, bus_name, _ofono_get_name_owner, NULL);
2946 void ofono_shutdown(void)
2948 if (pc_get_modems) {
2949 dbus_pending_call_cancel(pc_get_modems);
2950 pc_get_modems = NULL;
2953 _ofono_disconnected();
2954 eina_stringshare_replace(&modem_path_wanted, NULL);
2956 eina_hash_free(modems);
2959 eina_list_free(modem_types);
2962 static OFono_Pending *_ofono_call_volume_property_set(char *property,
2963 int type, void *value,
2968 OFono_Simple_Cb_Context *ctx = NULL;
2970 DBusMessageIter iter, variant;
2971 OFono_Modem *m = _modem_selected_get();
2972 char type_to_send[2] = { type , DBUS_TYPE_INVALID };
2974 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2977 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2978 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2983 msg = dbus_message_new_method_call(bus_id, m->base.path,
2984 OFONO_PREFIX OFONO_CALL_VOL_IFACE,
2987 goto error_no_dbus_message;
2989 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &property,
2991 goto error_message_args;
2993 dbus_message_iter_init_append(msg, &iter);
2995 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2996 type_to_send, &variant))
2997 goto error_message_args;
2999 if (!dbus_message_iter_append_basic(&variant, type, value) ||
3000 !dbus_message_iter_close_container(&iter, &variant)) {
3001 dbus_message_iter_abandon_container(&iter, &variant);
3002 goto error_message_args;
3005 INF("%s.SetProperty(%s)", OFONO_CALL_VOL_IFACE, property);
3006 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3010 dbus_message_unref(msg);
3012 error_no_dbus_message:
3014 cb((void *)data, OFONO_ERROR_FAILED);
3019 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
3022 dbus_bool_t dbus_mute = !!mute;
3024 return _ofono_call_volume_property_set("Muted", DBUS_TYPE_BOOLEAN,
3025 &dbus_mute, cb, data);
3028 Eina_Bool ofono_mute_get(void)
3030 OFono_Modem *m = _modem_selected_get();
3031 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3035 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
3040 return _ofono_call_volume_property_set("SpeakerVolume", DBUS_TYPE_BYTE,
3044 unsigned char ofono_volume_speaker_get(void)
3046 OFono_Modem *m = _modem_selected_get();
3047 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3048 return m->speaker_volume;
3051 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
3055 return _ofono_call_volume_property_set("MicrophoneVolume",
3056 DBUS_TYPE_BYTE, &volume, cb,
3060 unsigned char ofono_volume_microphone_get(void)
3062 OFono_Modem *m = _modem_selected_get();
3063 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3064 return m->microphone_volume;
3067 Eina_Bool ofono_voicemail_waiting_get(void)
3069 OFono_Modem *m = _modem_selected_get();
3070 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3071 return m->voicemail_waiting;
3074 unsigned char ofono_voicemail_count_get(void)
3076 OFono_Modem *m = _modem_selected_get();
3077 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3078 return m->voicemail_count;
3081 const char *ofono_voicemail_number_get(void)
3083 OFono_Modem *m = _modem_selected_get();
3084 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3085 return m->voicemail_number;
3088 OFono_USSD_State ofono_ussd_state_get(void)
3090 OFono_Modem *m = _modem_selected_get();
3091 EINA_SAFETY_ON_NULL_RETURN_VAL(m, OFONO_USSD_STATE_IDLE);
3092 return m->ussd_state;
3095 const char *ofono_service_center_address_get(void)
3097 OFono_Modem *m = _modem_selected_get();
3098 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3099 return m->serv_center_addr;
3102 Eina_Bool ofono_use_delivery_reports_get(void)
3104 OFono_Modem *m = _modem_selected_get();
3105 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3106 return m->use_delivery_reports;
3109 const char *ofono_message_bearer_get(void)
3111 OFono_Modem *m = _modem_selected_get();
3112 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3113 return m->msg_bearer;
3116 const char *ofono_message_alphabet_get(void)
3118 OFono_Modem *m = _modem_selected_get();
3119 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3120 return m->msg_alphabet;
3123 OFono_Sent_SMS_State ofono_sent_sms_state_get(const OFono_Sent_SMS *sms)
3125 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, OFONO_SENT_SMS_STATE_FAILED);
3129 const char *ofono_sent_sms_destination_get(const OFono_Sent_SMS *sms)
3131 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3132 return sms->destination;
3135 const char *ofono_sent_sms_message_get(const OFono_Sent_SMS *sms)
3137 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3138 return sms->message;
3141 time_t ofono_sent_sms_timestamp_get(const OFono_Sent_SMS *sms)
3143 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, 0);
3144 return sms->timestamp;
3147 OFono_Pending *ofono_sent_sms_cancel(OFono_Sent_SMS *sms, OFono_Simple_Cb cb,
3150 OFono_Simple_Cb_Context *ctx = NULL;
3151 OFono_Error err = OFONO_ERROR_OFFLINE;
3156 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3157 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3162 msg = dbus_message_new_method_call(bus_id, sms->base.path,
3163 OFONO_PREFIX "Message",
3168 INF("Cancel(%s)", sms->base.path);
3169 p = _bus_object_message_send(&sms->base, msg, _ofono_simple_reply, ctx);
3174 cb((void *)data, err);
3179 static void _ofono_sms_send_reply(void *data, DBusMessage *msg, DBusError *err)
3181 OFono_Sent_SMS_Cb_Context *ctx = data;
3182 OFono_Sent_SMS *sms = NULL;
3183 OFono_Error oe = OFONO_ERROR_NONE;
3186 DBG("%s: %s", err->name, err->message);
3187 oe = _ofono_error_parse(err->name);
3191 dbus_error_init(&e);
3192 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
3193 &path, DBUS_TYPE_INVALID)) {
3194 ERR("Could not get SendMessage reply: %s: %s",
3196 dbus_error_free(&e);
3197 oe = OFONO_ERROR_FAILED;
3199 sms = eina_hash_find(ctx->modem->sent_sms, path);
3200 DBG("path=%s, existing sms=%p", path, sms);
3202 sms = _sent_sms_pending_add(ctx->modem, path,
3205 /* ctx->cb will be dispatched on
3206 * MessageAdded signal handler.
3212 ERR("Could not find sms %s", path);
3213 oe = OFONO_ERROR_FAILED;
3218 ctx->cb((void *)ctx->data, oe, sms);
3220 eina_stringshare_del(ctx->destination);
3221 eina_stringshare_del(ctx->message);
3225 OFono_Pending *ofono_sms_send(const char *number, const char *message,
3226 OFono_Sent_SMS_Cb cb, const void *data)
3228 OFono_Sent_SMS_Cb_Context *ctx = NULL;
3229 OFono_Error err = OFONO_ERROR_OFFLINE;
3232 OFono_Modem *m = _modem_selected_get();
3233 EINA_SAFETY_ON_NULL_GOTO(m, error);
3234 EINA_SAFETY_ON_NULL_GOTO(number, error);
3235 EINA_SAFETY_ON_NULL_GOTO(message, error);
3237 if ((m->interfaces & OFONO_API_MSG) == 0)
3239 err = OFONO_ERROR_FAILED;
3241 ctx = calloc(1, sizeof(OFono_Sent_SMS_Cb_Context));
3242 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3246 ctx->destination = eina_stringshare_add(number);
3247 ctx->message = eina_stringshare_add(message);
3249 msg = dbus_message_new_method_call(
3250 bus_id, m->base.path, OFONO_PREFIX OFONO_MSG_IFACE,
3255 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
3256 DBUS_TYPE_STRING, &message,
3260 INF("SendMessage(%s, %s)", number, message);
3261 p = _bus_object_message_send(&m->base, msg, _ofono_sms_send_reply, ctx);
3265 dbus_message_unref(msg);
3268 cb((void *)data, err, NULL);
3269 eina_stringshare_del(ctx->destination);
3270 eina_stringshare_del(ctx->message);
3275 OFono_Pending *ofono_tones_send(const char *tones,
3281 OFono_Simple_Cb_Context *ctx = NULL;
3282 OFono_Modem *m = _modem_selected_get();
3284 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
3287 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3288 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
3293 msg = dbus_message_new_method_call(
3294 bus_id, m->base.path,
3295 OFONO_PREFIX OFONO_VOICE_IFACE,
3298 goto error_no_dbus_message;
3300 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &tones,
3302 goto error_message_args;
3304 INF("SendTones(%s)", tones);
3305 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3309 dbus_message_unref(msg);
3311 error_no_dbus_message:
3313 cb((void *)data, OFONO_ERROR_FAILED);
3318 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
3321 return _ofono_multiparty("CreateMultiparty", cb, data);
3324 OFono_Pending *ofono_multiparty_hangup(OFono_Simple_Cb cb, const void *data)
3326 return _ofono_multiparty("HangupMultiparty", cb, data);
3329 OFono_Pending *ofono_private_chat(OFono_Call *c, OFono_Simple_Cb cb,
3334 OFono_Simple_Cb_Context *ctx = NULL;
3335 OFono_Modem *m = _modem_selected_get();
3337 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
3338 EINA_SAFETY_ON_NULL_GOTO(c, error_no_message);
3341 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3342 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
3347 msg = dbus_message_new_method_call(
3348 bus_id, m->base.path,
3349 OFONO_PREFIX OFONO_VOICE_IFACE,
3353 goto error_no_message;
3355 if (!dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
3356 &(c->base.path), DBUS_TYPE_INVALID))
3357 goto error_message_append;
3359 INF("PrivateChat(%s)", c->base.path);
3360 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3363 error_message_append:
3364 dbus_message_unref(msg);
3367 cb((void *)data, OFONO_ERROR_FAILED);
3372 static OFono_Callback_List_Modem_Node * _ofono_callback_modem_node_create(
3373 void (*cb)(void *data),const void *data)
3375 OFono_Callback_List_Modem_Node *node_new;
3377 node_new = calloc(1, sizeof(OFono_Callback_List_Modem_Node));
3378 EINA_SAFETY_ON_NULL_RETURN_VAL(node_new, NULL);
3380 node_new->cb_data = data;
3386 OFono_Callback_List_Modem_Node *
3387 ofono_modem_conected_cb_add(void (*cb)(void *data), const void *data)
3389 OFono_Callback_List_Modem_Node *node;
3391 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3392 node = _ofono_callback_modem_node_create(cb, data);
3393 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3395 cbs_modem_connected = eina_inlist_append(cbs_modem_connected,
3396 EINA_INLIST_GET(node));
3401 OFono_Callback_List_Modem_Node *
3402 ofono_modem_disconnected_cb_add(void (*cb)(void *data), const void *data)
3404 OFono_Callback_List_Modem_Node *node;
3406 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3407 node = _ofono_callback_modem_node_create(cb, data);
3408 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3410 cbs_modem_disconnected = eina_inlist_append(cbs_modem_disconnected,
3411 EINA_INLIST_GET(node));
3416 OFono_Callback_List_Modem_Node *
3417 ofono_modem_changed_cb_add(void (*cb)(void *data), const void *data)
3419 OFono_Callback_List_Modem_Node *node;
3421 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3422 node = _ofono_callback_modem_node_create(cb, data);
3423 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3425 cbs_modem_changed = eina_inlist_append(cbs_modem_changed,
3426 EINA_INLIST_GET(node));
3431 static void _ofono_callback_modem_list_delete(Eina_Inlist **list,
3432 OFono_Callback_List_Modem_Node *node)
3434 EINA_SAFETY_ON_NULL_RETURN(*list);
3435 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3439 void ofono_modem_changed_cb_del(OFono_Callback_List_Modem_Node *node)
3441 EINA_SAFETY_ON_NULL_RETURN(node);
3442 _ofono_callback_modem_list_delete(&cbs_modem_changed, node);
3445 void ofono_modem_disconnected_cb_del(OFono_Callback_List_Modem_Node *node)
3447 EINA_SAFETY_ON_NULL_RETURN(node);
3448 _ofono_callback_modem_list_delete(&cbs_modem_disconnected, node);
3451 void ofono_modem_connected_cb_del(OFono_Callback_List_Modem_Node *node)
3453 EINA_SAFETY_ON_NULL_RETURN(node);
3454 _ofono_callback_modem_list_delete(&cbs_modem_connected, node);
3457 static OFono_Callback_List_Call_Node *_ofono_callback_call_node_create(
3458 void (*cb)(void *data, OFono_Call *call),const void *data)
3460 OFono_Callback_List_Call_Node *node;
3462 node = calloc(1, sizeof(OFono_Callback_List_Call_Node));
3463 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3465 node->cb_data = data;
3471 static OFono_Callback_List_Call_Disconnected_Node *
3472 _ofono_callback_call_disconnected_node_create(
3473 void (*cb)(void *data, OFono_Call *call, const char *reason),
3476 OFono_Callback_List_Call_Disconnected_Node *node;
3478 node = calloc(1, sizeof(OFono_Callback_List_Call_Disconnected_Node));
3479 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3481 node->cb_data = data;
3487 static OFono_Callback_List_USSD_Notify_Node *
3488 _ofono_callback_ussd_notify_node_create(
3489 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3492 OFono_Callback_List_USSD_Notify_Node *node;
3494 node = calloc(1, sizeof(OFono_Callback_List_USSD_Notify_Node));
3495 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3497 node->cb_data = data;
3503 OFono_Callback_List_Call_Node *ofono_call_added_cb_add(
3504 void (*cb)(void *data,OFono_Call *call), const void *data)
3506 OFono_Callback_List_Call_Node *node;
3508 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3509 node = _ofono_callback_call_node_create(cb, data);
3510 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3512 cbs_call_added = eina_inlist_append(cbs_call_added,
3513 EINA_INLIST_GET(node));
3518 OFono_Callback_List_Call_Node *ofono_call_removed_cb_add(
3519 void (*cb)(void *data, OFono_Call *call), const void *data)
3521 OFono_Callback_List_Call_Node *node;
3523 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3524 node = _ofono_callback_call_node_create(cb, data);
3525 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3527 cbs_call_removed = eina_inlist_append(cbs_call_removed,
3528 EINA_INLIST_GET(node));
3533 OFono_Callback_List_Call_Node *ofono_call_changed_cb_add(
3534 void (*cb)(void *data, OFono_Call *call), const void *data)
3536 OFono_Callback_List_Call_Node *node;
3538 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3539 node = _ofono_callback_call_node_create(cb, data);
3540 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3542 cbs_call_changed = eina_inlist_append(cbs_call_changed,
3543 EINA_INLIST_GET(node));
3548 OFono_Callback_List_Call_Disconnected_Node *ofono_call_disconnected_cb_add(
3549 void (*cb)(void *data, OFono_Call *call, const char *reason),
3552 OFono_Callback_List_Call_Disconnected_Node *node;
3554 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3555 node = _ofono_callback_call_disconnected_node_create(cb, data);
3556 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3558 cbs_call_disconnected = eina_inlist_append(cbs_call_disconnected,
3559 EINA_INLIST_GET(node));
3564 OFono_Callback_List_USSD_Notify_Node *ofono_ussd_notify_cb_add(
3565 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3568 OFono_Callback_List_USSD_Notify_Node *node;
3570 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3571 node = _ofono_callback_ussd_notify_node_create(cb, data);
3572 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3574 cbs_ussd_notify = eina_inlist_append(cbs_ussd_notify,
3575 EINA_INLIST_GET(node));
3580 static void _ofono_callback_call_list_delete(Eina_Inlist **list,
3581 OFono_Callback_List_Call_Node *node)
3583 EINA_SAFETY_ON_NULL_RETURN(*list);
3584 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3588 void ofono_call_changed_cb_del(OFono_Callback_List_Call_Node *node)
3590 EINA_SAFETY_ON_NULL_RETURN(node);
3591 _ofono_callback_call_list_delete(&cbs_call_changed, node);
3594 void ofono_call_disconnected_cb_del(
3595 OFono_Callback_List_Call_Disconnected_Node *node)
3597 EINA_SAFETY_ON_NULL_RETURN(node);
3598 EINA_SAFETY_ON_NULL_RETURN(cbs_call_disconnected);
3599 cbs_call_disconnected = eina_inlist_remove(cbs_call_disconnected,
3600 EINA_INLIST_GET(node));
3604 void ofono_ussd_notify_cb_del(OFono_Callback_List_USSD_Notify_Node *node)
3606 EINA_SAFETY_ON_NULL_RETURN(node);
3607 EINA_SAFETY_ON_NULL_RETURN(cbs_ussd_notify);
3608 cbs_ussd_notify = eina_inlist_remove(cbs_ussd_notify,
3609 EINA_INLIST_GET(node));
3613 void ofono_call_added_cb_del(OFono_Callback_List_Call_Node *node)
3615 EINA_SAFETY_ON_NULL_RETURN(node);
3616 _ofono_callback_call_list_delete(&cbs_call_added, node);
3619 void ofono_call_removed_cb_del(OFono_Callback_List_Call_Node *node)
3621 EINA_SAFETY_ON_NULL_RETURN(node);
3622 _ofono_callback_call_list_delete(&cbs_call_removed, node);
3625 OFono_Callback_List_Sent_SMS_Node *
3626 ofono_sent_sms_changed_cb_add(OFono_Sent_SMS_Cb cb, const void *data)
3628 OFono_Callback_List_Sent_SMS_Node *node;
3630 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3631 node = calloc(1, sizeof(OFono_Callback_List_Sent_SMS_Node));
3632 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3634 node->cb_data = data;
3636 cbs_sent_sms_changed = eina_inlist_append(cbs_sent_sms_changed,
3637 EINA_INLIST_GET(node));
3642 void ofono_sent_sms_changed_cb_del(OFono_Callback_List_Sent_SMS_Node *node)
3644 EINA_SAFETY_ON_NULL_RETURN(node);
3645 cbs_sent_sms_changed = eina_inlist_remove(cbs_sent_sms_changed,
3646 EINA_INLIST_GET(node));
3650 OFono_Callback_List_Incoming_SMS_Node *
3651 ofono_incoming_sms_cb_add(OFono_Incoming_SMS_Cb cb, const void *data)
3653 OFono_Callback_List_Incoming_SMS_Node *node;
3655 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3656 node = calloc(1, sizeof(OFono_Callback_List_Incoming_SMS_Node));
3657 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3659 node->cb_data = data;
3661 cbs_incoming_sms = eina_inlist_append(cbs_incoming_sms,
3662 EINA_INLIST_GET(node));
3667 void ofono_incoming_sms_cb_del(OFono_Callback_List_Incoming_SMS_Node *node)
3669 EINA_SAFETY_ON_NULL_RETURN(node);
3670 cbs_incoming_sms = eina_inlist_remove(cbs_incoming_sms,
3671 EINA_INLIST_GET(node));
3675 Eina_Bool ofono_voice_is_online(void)
3677 OFono_Modem *m = _modem_selected_get();
3679 /* The modem is expected to be NULL here, because maybe
3680 * OFono isn't up yet.
3685 if (m->interfaces & OFONO_API_VOICE)