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;
1516 sms->destination = ctx->destination;
1517 sms->message = ctx->message;
1518 sms->timestamp = time(NULL);
1520 ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, sms);
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);
1990 if (!ofono_voice_is_online()) {
1991 ofono_powered_set(EINA_TRUE, NULL, NULL);
1996 static void _modem_added(void *data __UNUSED__, DBusMessage *msg)
1998 DBusMessageIter iter, properties;
2001 if (!msg || !dbus_message_iter_init(msg, &iter)) {
2002 ERR("Could not handle message %p", msg);
2006 dbus_message_iter_get_basic(&iter, &path);
2008 dbus_message_iter_next(&iter);
2009 dbus_message_iter_recurse(&iter, &properties);
2011 _modem_add(path, &properties);
2014 static void _modem_removed(void *data __UNUSED__, DBusMessage *msg)
2020 ERR("Could not handle message %p", msg);
2024 dbus_error_init(&err);
2025 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
2027 ERR("Could not get ModemRemoved arguments: %s: %s",
2028 err.name, err.message);
2029 dbus_error_free(&err);
2033 _modem_remove(path);
2036 static void _modem_property_changed(void *data __UNUSED__, DBusMessage *msg)
2040 DBusMessageIter iter, value;
2043 if (!msg || !dbus_message_iter_init(msg, &iter)) {
2044 ERR("Could not handle message %p", msg);
2048 path = dbus_message_get_path(msg);
2049 DBG("path=%s", path);
2051 m = eina_hash_find(modems, path);
2053 DBG("Modem is unknown (%s)", path);
2057 dbus_message_iter_get_basic(&iter, &key);
2058 dbus_message_iter_next(&iter);
2059 dbus_message_iter_recurse(&iter, &value);
2060 _modem_property_update(m, key, &value);
2062 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
2065 static void _modems_load(void)
2067 DBusMessage *msg = dbus_message_new_method_call(
2068 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
2071 dbus_pending_call_cancel(pc_get_modems);
2074 pc_get_modems = e_dbus_message_send(
2075 bus_conn, msg, _ofono_modems_get_reply, -1, NULL);
2076 dbus_message_unref(msg);
2079 static void _ofono_connected(const char *id)
2082 bus_id = strdup(id);
2084 sig_modem_added = e_dbus_signal_handler_add(
2085 bus_conn, bus_id, "/",
2086 OFONO_PREFIX OFONO_MANAGER_IFACE,
2088 _modem_added, NULL);
2090 sig_modem_removed = e_dbus_signal_handler_add(
2091 bus_conn, bus_id, "/",
2092 OFONO_PREFIX OFONO_MANAGER_IFACE,
2094 _modem_removed, NULL);
2096 sig_modem_prop_changed = e_dbus_signal_handler_add(
2097 bus_conn, bus_id, NULL,
2098 OFONO_PREFIX OFONO_MODEM_IFACE,
2100 _modem_property_changed, NULL);
2104 _notify_ofono_callbacks_modem_list(cbs_modem_connected);
2107 static void _ofono_disconnected(void)
2109 eina_hash_free_buckets(modems);
2111 if (sig_modem_added) {
2112 e_dbus_signal_handler_del(bus_conn, sig_modem_added);
2113 sig_modem_added = NULL;
2116 if (sig_modem_removed) {
2117 e_dbus_signal_handler_del(bus_conn, sig_modem_removed);
2118 sig_modem_removed = NULL;
2121 if (sig_modem_prop_changed) {
2122 e_dbus_signal_handler_del(bus_conn, sig_modem_prop_changed);
2123 sig_modem_prop_changed = NULL;
2127 _notify_ofono_callbacks_modem_list(cbs_modem_disconnected);
2133 static void _name_owner_changed(void *data __UNUSED__, DBusMessage *msg)
2136 const char *name, *from, *to;
2138 dbus_error_init(&err);
2139 if (!dbus_message_get_args(msg, &err,
2140 DBUS_TYPE_STRING, &name,
2141 DBUS_TYPE_STRING, &from,
2142 DBUS_TYPE_STRING, &to,
2143 DBUS_TYPE_INVALID)) {
2144 ERR("Could not get NameOwnerChanged arguments: %s: %s",
2145 err.name, err.message);
2146 dbus_error_free(&err);
2150 if (strcmp(name, bus_name) != 0)
2153 DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
2155 if (from[0] == '\0' && to[0] != '\0') {
2156 INF("oFono appeared as %s", to);
2157 _ofono_connected(to);
2158 } else if (from[0] != '\0' && to[0] == '\0') {
2159 INF("oFono disappeared from %s", from);
2160 _ofono_disconnected();
2164 static void _ofono_get_name_owner(void *data __UNUSED__, DBusMessage *msg, DBusError *err)
2166 DBusMessageIter itr;
2171 ERR("%s: %s", err->name, err->message);
2177 dbus_message_iter_init(msg, &itr);
2178 dbus_message_iter_get_basic(&itr, &id);
2179 if (!id || id[0] == '\0') {
2180 ERR("No name owner fo %s!", bus_name);
2184 INF("oFono bus id: %s", id);
2185 _ofono_connected(id);
2188 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
2189 const char *new, OFono_Simple_Cb cb,
2192 OFono_Simple_Cb_Context *ctx = NULL;
2193 OFono_Error err = OFONO_ERROR_OFFLINE;
2196 OFono_Modem *m = _modem_selected_get();
2197 EINA_SAFETY_ON_NULL_GOTO(m, error);
2198 EINA_SAFETY_ON_NULL_GOTO(what, error);
2199 EINA_SAFETY_ON_NULL_GOTO(old, error);
2200 EINA_SAFETY_ON_NULL_GOTO(new, error);
2202 if ((m->interfaces & OFONO_API_SIM) == 0)
2204 err = OFONO_ERROR_FAILED;
2207 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2208 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2213 msg = dbus_message_new_method_call(
2214 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
2219 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
2220 DBUS_TYPE_STRING, &old,
2221 DBUS_TYPE_STRING, &new,
2225 INF("ChangePin(%s, %s, %s)", what, old, new);
2226 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2230 dbus_message_unref(msg);
2233 cb((void *)data, err);
2238 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
2239 const char *new, OFono_Simple_Cb cb,
2242 OFono_Simple_Cb_Context *ctx = NULL;
2243 OFono_Error err = OFONO_ERROR_OFFLINE;
2246 OFono_Modem *m = _modem_selected_get();
2247 EINA_SAFETY_ON_NULL_GOTO(m, error);
2248 EINA_SAFETY_ON_NULL_GOTO(what, error);
2249 EINA_SAFETY_ON_NULL_GOTO(puk, error);
2250 EINA_SAFETY_ON_NULL_GOTO(new, error);
2252 if ((m->interfaces & OFONO_API_SIM) == 0)
2254 err = OFONO_ERROR_FAILED;
2257 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2258 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2263 msg = dbus_message_new_method_call(
2264 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
2268 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
2269 DBUS_TYPE_STRING, &puk,
2270 DBUS_TYPE_STRING, &new,
2274 INF("ResetPin(%s, %s, %s)", what, puk, new);
2275 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2279 dbus_message_unref(msg);
2282 cb((void *)data, err);
2287 static OFono_Pending *_ofono_modem_property_set(char *property,
2288 int type, void *value,
2293 OFono_Simple_Cb_Context *ctx = NULL;
2295 DBusMessageIter iter, variant;
2296 OFono_Modem *found_path = NULL, *found_hfp = NULL, *m;
2302 itr = eina_hash_iterator_data_new(modems);
2303 EINA_ITERATOR_FOREACH(itr, m) {
2307 if ((modem_path_wanted) && (!found_path)) {
2308 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
2309 if (m->base.path == modem_path_wanted) {
2316 DBG("m=%#x, mask=%#x, previous=%s "
2317 "(online=%d, powered=%d)",
2318 m->interfaces, modem_api_mask,
2319 found_hfp ? found_hfp->base.path : "",
2320 found_hfp ? found_hfp->online : 0,
2321 found_hfp ? found_hfp->powered : 0);
2322 if (strncmp(m->base.path, "/hfp", 4) == 0)
2326 eina_iterator_free(itr);
2327 m = found_path ? found_path : found_hfp;
2333 char type_to_send[2] = { type , DBUS_TYPE_INVALID };
2335 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2338 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2339 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2344 msg = dbus_message_new_method_call(bus_id, m->base.path,
2345 OFONO_PREFIX OFONO_MODEM_IFACE,
2348 goto error_no_dbus_message;
2350 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &property,
2352 goto error_message_args;
2354 dbus_message_iter_init_append(msg, &iter);
2356 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2357 type_to_send, &variant))
2358 goto error_message_args;
2360 if (!dbus_message_iter_append_basic(&variant, type, value) ||
2361 !dbus_message_iter_close_container(&iter, &variant)) {
2362 dbus_message_iter_abandon_container(&iter, &variant);
2363 goto error_message_args;
2366 INF("%s.SetProperty(%s)", OFONO_MODEM_IFACE, property);
2367 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2371 dbus_message_unref(msg);
2373 error_no_dbus_message:
2375 cb((void *)data, OFONO_ERROR_FAILED);
2380 OFono_Pending *ofono_powered_set(Eina_Bool powered, OFono_Simple_Cb cb,
2383 dbus_bool_t dbus_powered = !!powered;
2385 return _ofono_modem_property_set("Powered", DBUS_TYPE_BOOLEAN,
2386 &dbus_powered, cb, data);
2389 Eina_Bool ofono_powered_get(void)
2391 OFono_Modem *m = _modem_selected_get();
2392 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
2396 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
2397 DBusMessageIter *itr)
2399 const char *ussd_response;
2401 if (dbus_message_iter_get_arg_type(itr) != DBUS_TYPE_STRING) {
2402 ERR("Invalid type: %c (expected: %c)",
2403 dbus_message_iter_get_arg_type(itr), DBUS_TYPE_STRING);
2406 dbus_message_iter_get_basic(itr, &ussd_response);
2407 EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
2408 return strdup(ussd_response);
2411 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
2412 DBusMessageIter *dict)
2414 for (; dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY;
2415 dbus_message_iter_next(dict)) {
2416 DBusMessageIter e, v;
2417 const char *key, *value;
2419 dbus_message_iter_recurse(dict, &e);
2420 dbus_message_iter_get_basic(&e, &key);
2422 dbus_message_iter_next(&e);
2423 dbus_message_iter_recurse(&e, &v);
2424 dbus_message_iter_get_basic(&v, &value);
2426 eina_strbuf_append_printf(buf, " %s=%s<br>",
2431 static char *_ss_initiate_convert_call1(const char *type, DBusMessageIter *itr)
2433 DBusMessageIter array, dict;
2434 const char *ss_op, *service;
2438 dbus_message_iter_recurse(itr, &array);
2440 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2441 ERR("Invalid type: %c (expected: %c)",
2442 dbus_message_iter_get_arg_type(&array),
2446 dbus_message_iter_get_basic(&array, &ss_op);
2447 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2449 if (!dbus_message_iter_next(&array)) {
2450 ERR("Missing %s service", type);
2454 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2455 ERR("Invalid type: %c (expected: %c)",
2456 dbus_message_iter_get_arg_type(&array),
2460 dbus_message_iter_get_basic(&array, &service);
2461 EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
2463 if (!dbus_message_iter_next(&array)) {
2464 ERR("Missing %s information", type);
2468 buf = eina_strbuf_new();
2469 eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
2470 type, ss_op, service);
2472 dbus_message_iter_recurse(&array, &dict);
2473 _ss_initiate_cb_dict_convert(buf, &dict);
2475 str = eina_strbuf_string_steal(buf);
2476 eina_strbuf_free(buf);
2480 static char *_ss_initiate_convert_call_waiting(const char *type,
2481 DBusMessageIter *itr)
2483 DBusMessageIter array, dict;
2488 dbus_message_iter_recurse(itr, &array);
2490 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2491 ERR("Invalid type: %c (expected: %c)",
2492 dbus_message_iter_get_arg_type(&array),
2496 dbus_message_iter_get_basic(&array, &ss_op);
2497 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2499 if (!dbus_message_iter_next(&array)) {
2500 ERR("Missing %s information", type);
2504 buf = eina_strbuf_new();
2505 eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
2508 dbus_message_iter_recurse(&array, &dict);
2509 _ss_initiate_cb_dict_convert(buf, &dict);
2511 str = eina_strbuf_string_steal(buf);
2512 eina_strbuf_free(buf);
2516 static char *_ss_initiate_convert_call2(const char *type,
2517 DBusMessageIter *itr)
2519 DBusMessageIter array;
2520 const char *ss_op, *status;
2524 dbus_message_iter_recurse(itr, &array);
2526 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2527 ERR("Invalid type: %c (expected: %c)",
2528 dbus_message_iter_get_arg_type(&array),
2532 dbus_message_iter_get_basic(&array, &ss_op);
2533 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2535 if (!dbus_message_iter_next(&array)) {
2536 ERR("Missing %s status", type);
2540 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2541 ERR("Invalid type: %c (expected: %c)",
2542 dbus_message_iter_get_arg_type(&array),
2546 dbus_message_iter_get_basic(&array, &status);
2547 EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
2549 buf = eina_strbuf_new();
2550 eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
2551 type, ss_op, status);
2553 str = eina_strbuf_string_steal(buf);
2554 eina_strbuf_free(buf);
2558 static const struct SS_Initiate_Convert_Map {
2561 char *(*convert)(const char *type, DBusMessageIter *itr);
2562 } ss_initiate_convert_map[] = {
2563 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
2564 MAP("USSD", _ss_initiate_convert_ussd),
2565 MAP("CallBarring", _ss_initiate_convert_call1),
2566 MAP("CallForwarding", _ss_initiate_convert_call1),
2567 MAP("CallWaiting", _ss_initiate_convert_call_waiting),
2568 MAP("CallingLinePresentation", _ss_initiate_convert_call2),
2569 MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
2570 MAP("CallingLineRestriction", _ss_initiate_convert_call2),
2571 MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
2576 static char *_ss_initiate_convert(DBusMessage *msg)
2578 DBusMessageIter array, variant;
2579 const struct SS_Initiate_Convert_Map *citr;
2580 const char *type = NULL;
2583 if (!dbus_message_iter_init(msg, &array))
2586 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2587 ERR("Invalid type for first argument: %c (expected: %c)",
2588 dbus_message_iter_get_arg_type(&array),
2592 dbus_message_iter_get_basic(&array, &type);
2594 ERR("Couldn't get SupplementaryServices.Initiate type");
2597 DBG("type: %s", type);
2599 if (!dbus_message_iter_next(&array)) {
2600 ERR("Couldn't get SupplementaryServices.Initiate payload");
2603 dbus_message_iter_recurse(&array, &variant);
2605 typelen = strlen(type);
2606 for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
2607 if ((citr->typelen == typelen) &&
2608 (memcmp(citr->type, type, typelen) == 0)) {
2609 return citr->convert(type, &variant);
2612 ERR("Could not convert SupplementaryServices.Initiate type %s", type);
2618 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
2620 OFono_String_Cb_Context *ctx = NULL;
2621 OFono_Error err = OFONO_ERROR_OFFLINE;
2624 OFono_Modem *m = _modem_selected_get();
2625 EINA_SAFETY_ON_NULL_GOTO(m, error);
2626 EINA_SAFETY_ON_NULL_GOTO(command, error);
2628 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2630 err = OFONO_ERROR_FAILED;
2632 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2633 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2636 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2637 ctx->convert = _ss_initiate_convert;
2639 msg = dbus_message_new_method_call(
2640 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2645 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &command,
2649 INF("SupplementaryServices.Initiate(%s)", command);
2650 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2654 dbus_message_unref(msg);
2657 cb((void *)data, err, NULL);
2662 static char *_ussd_respond_convert(DBusMessage *msg)
2664 DBusMessageIter itr;
2667 if (!msg || !dbus_message_iter_init(msg, &itr)) {
2668 ERR("Could not handle message %p", msg);
2672 if (dbus_message_iter_get_arg_type(&itr) != DBUS_TYPE_STRING) {
2673 ERR("Invalid type: %c (expected: %c)",
2674 dbus_message_iter_get_arg_type(&itr), DBUS_TYPE_STRING);
2677 dbus_message_iter_get_basic(&itr, &s);
2678 EINA_SAFETY_ON_NULL_RETURN_VAL(s, NULL);
2682 OFono_Pending *ofono_ussd_respond(const char *string,
2683 OFono_String_Cb cb, const void *data)
2685 OFono_String_Cb_Context *ctx = NULL;
2686 OFono_Error err = OFONO_ERROR_OFFLINE;
2689 OFono_Modem *m = _modem_selected_get();
2690 EINA_SAFETY_ON_NULL_GOTO(m, error);
2691 EINA_SAFETY_ON_NULL_GOTO(string, error);
2693 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2695 err = OFONO_ERROR_FAILED;
2697 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2698 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2701 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2702 ctx->convert = _ussd_respond_convert;
2704 msg = dbus_message_new_method_call(
2705 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2710 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &string,
2714 INF("SupplementaryServices.Respond(%s)", string);
2715 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2719 dbus_message_unref(msg);
2722 cb((void *)data, err, NULL);
2727 OFono_Pending *ofono_ussd_cancel(OFono_Simple_Cb cb, const void *data)
2729 return _ofono_simple_do(OFONO_API_SUPPL_SERV, "Cancel", cb, data);
2732 static void _ofono_dial_reply(void *data, DBusMessage *msg, DBusError *err)
2734 OFono_Call_Cb_Context *ctx = data;
2735 OFono_Call *c = NULL;
2736 OFono_Error oe = OFONO_ERROR_NONE;
2739 DBG("%s: %s", err->name, err->message);
2740 oe = _ofono_error_parse(err->name);
2744 dbus_error_init(&e);
2745 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
2746 &path, DBUS_TYPE_INVALID)) {
2747 ERR("Could not get Dial reply: %s: %s",
2749 dbus_error_free(&e);
2750 oe = OFONO_ERROR_FAILED;
2752 c = eina_hash_find(ctx->modem->calls, path);
2753 DBG("path=%s, existing call=%p", path, c);
2755 c = _call_pending_add(ctx->modem, path, ctx);
2757 /* ctx->cb will be dispatched on
2758 * CallAdded signal handler.
2764 ERR("Could not find call %s", path);
2765 oe = OFONO_ERROR_FAILED;
2770 ctx->cb((void *)ctx->data, oe, c);
2775 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
2776 OFono_Call_Cb cb, const void *data)
2778 OFono_Call_Cb_Context *ctx = NULL;
2779 OFono_Error err = OFONO_ERROR_OFFLINE;
2782 OFono_Modem *m = _modem_selected_get();
2783 EINA_SAFETY_ON_NULL_GOTO(m, error);
2786 if ((m->interfaces & OFONO_API_VOICE) == 0)
2788 err = OFONO_ERROR_FAILED;
2793 ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
2794 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2797 ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
2800 msg = dbus_message_new_method_call(
2801 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
2805 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
2806 DBUS_TYPE_STRING, &hide_callerid,
2810 INF("Dial(%s, %s)", number, hide_callerid);
2811 p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
2815 dbus_message_unref(msg);
2818 cb((void *)data, err, NULL);
2823 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
2824 OFono_Simple_Cb cb, const void *data)
2826 OFono_Simple_Cb_Context *ctx = NULL;
2827 OFono_Error err = OFONO_ERROR_OFFLINE;
2830 char iface[128] = "";
2831 const struct API_Interface_Map *itr;
2832 OFono_Modem *m = _modem_selected_get();
2833 EINA_SAFETY_ON_NULL_GOTO(m, error);
2834 EINA_SAFETY_ON_NULL_GOTO(method, error);
2836 if ((m->interfaces & api) == 0)
2838 err = OFONO_ERROR_FAILED;
2840 for (itr = api_iface_map; itr->name != NULL; itr++) {
2841 if (itr->bit == api) {
2842 snprintf(iface, sizeof(iface), "%s%s",
2843 OFONO_PREFIX, itr->name);
2847 if (iface[0] == '\0') {
2848 ERR("Could not map api %d to interface name!", api);
2853 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2854 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2859 msg = dbus_message_new_method_call(bus_id, m->base.path, iface, method);
2863 INF("%s.%s()", iface, method);
2864 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2869 cb((void *)data, err);
2874 OFono_Pending *ofono_transfer(OFono_Simple_Cb cb, const void *data)
2876 return _ofono_simple_do(OFONO_API_VOICE, "Transfer", cb, data);
2879 OFono_Pending *ofono_swap_calls(OFono_Simple_Cb cb, const void *data)
2881 return _ofono_simple_do(OFONO_API_VOICE, "SwapCalls", cb, data);
2884 OFono_Pending *ofono_release_and_answer(OFono_Simple_Cb cb, const void *data)
2886 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndAnswer", cb, data);
2889 OFono_Pending *ofono_release_and_swap(OFono_Simple_Cb cb, const void *data)
2891 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndSwap", cb, data);
2894 OFono_Pending *ofono_hold_and_answer(OFono_Simple_Cb cb, const void *data)
2896 return _ofono_simple_do(OFONO_API_VOICE, "HoldAndAnswer", cb, data);
2899 OFono_Pending *ofono_hangup_all(OFono_Simple_Cb cb, const void *data)
2901 return _ofono_simple_do(OFONO_API_VOICE, "HangupAll", cb, data);
2904 const char *ofono_modem_serial_get(void)
2906 OFono_Modem *m = _modem_selected_get();
2907 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
2911 void ofono_modem_api_require(const char *spec)
2913 unsigned int api_mask = 0;
2914 const char *name = spec;
2916 EINA_SAFETY_ON_NULL_RETURN(spec);
2919 const struct API_Interface_Map *itr;
2921 unsigned int namelen;
2923 p = strchr(name, ',');
2927 namelen = strlen(name);
2929 for (itr = api_iface_map; itr->name != NULL; itr++) {
2930 if ((itr->namelen == namelen) &&
2931 (memcmp(itr->name, name, namelen) == 0)) {
2932 api_mask |= itr->bit;
2936 if (itr->name == NULL)
2937 WRN("Unknown oFono API: %.*s", namelen, name);
2946 DBG("API parsed: '%s' = %#x", spec, api_mask);
2948 ERR("Could not parse API: %s", spec);
2952 if (modem_api_mask == api_mask)
2954 modem_api_mask = api_mask;
2955 modem_selected = NULL;
2958 void ofono_modem_api_list(FILE *fp, const char *prefix, const char *suffix)
2960 const struct API_Interface_Map *itr;
2961 for (itr = api_iface_map; itr->name != NULL; itr++)
2962 fprintf(fp, "%s%s%s", prefix, itr->name, suffix);
2965 void ofono_modem_type_require(const char *spec)
2967 Eina_List *lst = NULL;
2968 const char *name = spec;
2970 EINA_SAFETY_ON_NULL_RETURN(spec);
2975 unsigned int namelen;
2977 p = strchr(name, ',');
2981 namelen = strlen(name);
2983 for (itr = known_modem_types; *itr != NULL; itr++) {
2984 unsigned int itrlen = strlen(*itr);
2985 if ((itrlen == namelen) &&
2986 (memcmp(*itr, name, namelen) == 0)) {
2987 lst = eina_list_append(lst, *itr);
2992 WRN("Unknown oFono type: %.*s", namelen, name);
3001 DBG("Type parsed: '%s'", spec);
3003 ERR("Could not parse type: %s", spec);
3007 eina_list_free(modem_types);
3009 modem_selected = NULL;
3012 void ofono_modem_type_list(FILE *fp, const char *prefix, const char *suffix)
3015 for (itr = known_modem_types; *itr != NULL; itr++)
3016 fprintf(fp, "%s%s%s", prefix, *itr, suffix);
3019 void ofono_modem_path_wanted_set(const char *path)
3021 if (eina_stringshare_replace(&modem_path_wanted, path))
3022 modem_selected = NULL;
3025 unsigned int ofono_modem_api_get(void)
3027 OFono_Modem *m = _modem_selected_get();
3028 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3029 return m->interfaces;
3032 Eina_Bool ofono_init(void)
3036 if (!elm_need_e_dbus()) {
3037 CRITICAL("Elementary does not support DBus.");
3041 bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
3043 CRITICAL("Could not get DBus System Bus");
3047 modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
3048 EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
3050 e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
3051 E_DBUS_FDO_INTERFACE,
3053 _name_owner_changed, NULL);
3055 e_dbus_get_name_owner(bus_conn, bus_name, _ofono_get_name_owner, NULL);
3060 void ofono_shutdown(void)
3062 if (pc_get_modems) {
3063 dbus_pending_call_cancel(pc_get_modems);
3064 pc_get_modems = NULL;
3067 _ofono_disconnected();
3068 eina_stringshare_replace(&modem_path_wanted, NULL);
3070 eina_hash_free(modems);
3073 eina_list_free(modem_types);
3076 static OFono_Pending *_ofono_call_volume_property_set(char *property,
3077 int type, void *value,
3082 OFono_Simple_Cb_Context *ctx = NULL;
3084 DBusMessageIter iter, variant;
3085 OFono_Modem *m = _modem_selected_get();
3086 char type_to_send[2] = { type , DBUS_TYPE_INVALID };
3088 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
3091 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3092 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
3097 msg = dbus_message_new_method_call(bus_id, m->base.path,
3098 OFONO_PREFIX OFONO_CALL_VOL_IFACE,
3101 goto error_no_dbus_message;
3103 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &property,
3105 goto error_message_args;
3107 dbus_message_iter_init_append(msg, &iter);
3109 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
3110 type_to_send, &variant))
3111 goto error_message_args;
3113 if (!dbus_message_iter_append_basic(&variant, type, value) ||
3114 !dbus_message_iter_close_container(&iter, &variant)) {
3115 dbus_message_iter_abandon_container(&iter, &variant);
3116 goto error_message_args;
3119 INF("%s.SetProperty(%s)", OFONO_CALL_VOL_IFACE, property);
3120 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3124 dbus_message_unref(msg);
3126 error_no_dbus_message:
3128 cb((void *)data, OFONO_ERROR_FAILED);
3133 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
3136 dbus_bool_t dbus_mute = !!mute;
3138 return _ofono_call_volume_property_set("Muted", DBUS_TYPE_BOOLEAN,
3139 &dbus_mute, cb, data);
3142 Eina_Bool ofono_mute_get(void)
3144 OFono_Modem *m = _modem_selected_get();
3145 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3149 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
3154 return _ofono_call_volume_property_set("SpeakerVolume", DBUS_TYPE_BYTE,
3158 unsigned char ofono_volume_speaker_get(void)
3160 OFono_Modem *m = _modem_selected_get();
3161 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3162 return m->speaker_volume;
3165 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
3169 return _ofono_call_volume_property_set("MicrophoneVolume",
3170 DBUS_TYPE_BYTE, &volume, cb,
3174 unsigned char ofono_volume_microphone_get(void)
3176 OFono_Modem *m = _modem_selected_get();
3177 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3178 return m->microphone_volume;
3181 Eina_Bool ofono_voicemail_waiting_get(void)
3183 OFono_Modem *m = _modem_selected_get();
3184 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3185 return m->voicemail_waiting;
3188 unsigned char ofono_voicemail_count_get(void)
3190 OFono_Modem *m = _modem_selected_get();
3191 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3192 return m->voicemail_count;
3195 const char *ofono_voicemail_number_get(void)
3197 OFono_Modem *m = _modem_selected_get();
3198 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3199 return m->voicemail_number;
3202 OFono_USSD_State ofono_ussd_state_get(void)
3204 OFono_Modem *m = _modem_selected_get();
3205 EINA_SAFETY_ON_NULL_RETURN_VAL(m, OFONO_USSD_STATE_IDLE);
3206 return m->ussd_state;
3209 const char *ofono_service_center_address_get(void)
3211 OFono_Modem *m = _modem_selected_get();
3212 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3213 return m->serv_center_addr;
3216 Eina_Bool ofono_use_delivery_reports_get(void)
3218 OFono_Modem *m = _modem_selected_get();
3219 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3220 return m->use_delivery_reports;
3223 const char *ofono_message_bearer_get(void)
3225 OFono_Modem *m = _modem_selected_get();
3226 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3227 return m->msg_bearer;
3230 const char *ofono_message_alphabet_get(void)
3232 OFono_Modem *m = _modem_selected_get();
3233 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3234 return m->msg_alphabet;
3237 OFono_Sent_SMS_State ofono_sent_sms_state_get(const OFono_Sent_SMS *sms)
3239 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, OFONO_SENT_SMS_STATE_FAILED);
3243 const char *ofono_sent_sms_destination_get(const OFono_Sent_SMS *sms)
3245 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3246 return sms->destination;
3249 const char *ofono_sent_sms_message_get(const OFono_Sent_SMS *sms)
3251 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3252 return sms->message;
3255 time_t ofono_sent_sms_timestamp_get(const OFono_Sent_SMS *sms)
3257 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, 0);
3258 return sms->timestamp;
3261 OFono_Pending *ofono_sent_sms_cancel(OFono_Sent_SMS *sms, OFono_Simple_Cb cb,
3264 OFono_Simple_Cb_Context *ctx = NULL;
3265 OFono_Error err = OFONO_ERROR_OFFLINE;
3270 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3271 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3276 msg = dbus_message_new_method_call(bus_id, sms->base.path,
3277 OFONO_PREFIX "Message",
3282 INF("Cancel(%s)", sms->base.path);
3283 p = _bus_object_message_send(&sms->base, msg, _ofono_simple_reply, ctx);
3288 cb((void *)data, err);
3293 static void _ofono_sms_send_reply(void *data, DBusMessage *msg, DBusError *err)
3295 OFono_Sent_SMS_Cb_Context *ctx = data;
3296 OFono_Sent_SMS *sms = NULL;
3297 OFono_Error oe = OFONO_ERROR_NONE;
3300 DBG("%s: %s", err->name, err->message);
3301 oe = _ofono_error_parse(err->name);
3305 dbus_error_init(&e);
3306 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
3307 &path, DBUS_TYPE_INVALID)) {
3308 ERR("Could not get SendMessage reply: %s: %s",
3310 dbus_error_free(&e);
3311 oe = OFONO_ERROR_FAILED;
3313 sms = eina_hash_find(ctx->modem->sent_sms, path);
3314 DBG("path=%s, existing sms=%p", path, sms);
3316 sms = _sent_sms_pending_add(ctx->modem, path,
3319 /* ctx->cb will be dispatched on
3320 * MessageAdded signal handler.
3326 ERR("Could not find sms %s", path);
3327 oe = OFONO_ERROR_FAILED;
3332 ctx->cb((void *)ctx->data, oe, sms);
3334 eina_stringshare_del(ctx->destination);
3335 eina_stringshare_del(ctx->message);
3339 OFono_Pending *ofono_sms_send(const char *number, const char *message,
3340 OFono_Sent_SMS_Cb cb, const void *data)
3342 OFono_Sent_SMS_Cb_Context *ctx = NULL;
3343 OFono_Error err = OFONO_ERROR_OFFLINE;
3346 OFono_Modem *m = _modem_selected_get();
3347 EINA_SAFETY_ON_NULL_GOTO(m, error);
3348 EINA_SAFETY_ON_NULL_GOTO(number, error);
3349 EINA_SAFETY_ON_NULL_GOTO(message, error);
3351 if ((m->interfaces & OFONO_API_MSG) == 0)
3353 err = OFONO_ERROR_FAILED;
3355 ctx = calloc(1, sizeof(OFono_Sent_SMS_Cb_Context));
3356 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3360 ctx->destination = eina_stringshare_add(number);
3361 ctx->message = eina_stringshare_add(message);
3363 msg = dbus_message_new_method_call(
3364 bus_id, m->base.path, OFONO_PREFIX OFONO_MSG_IFACE,
3369 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
3370 DBUS_TYPE_STRING, &message,
3374 INF("SendMessage(%s, %s)", number, message);
3375 p = _bus_object_message_send(&m->base, msg, _ofono_sms_send_reply, ctx);
3379 dbus_message_unref(msg);
3381 eina_stringshare_del(ctx->destination);
3382 eina_stringshare_del(ctx->message);
3385 cb((void *)data, err, NULL);
3390 OFono_Pending *ofono_tones_send(const char *tones,
3396 OFono_Simple_Cb_Context *ctx = NULL;
3397 OFono_Modem *m = _modem_selected_get();
3399 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
3402 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3403 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
3408 msg = dbus_message_new_method_call(
3409 bus_id, m->base.path,
3410 OFONO_PREFIX OFONO_VOICE_IFACE,
3413 goto error_no_dbus_message;
3415 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &tones,
3417 goto error_message_args;
3419 INF("SendTones(%s)", tones);
3420 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3424 dbus_message_unref(msg);
3426 error_no_dbus_message:
3428 cb((void *)data, OFONO_ERROR_FAILED);
3433 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
3436 return _ofono_multiparty("CreateMultiparty", cb, data);
3439 OFono_Pending *ofono_multiparty_hangup(OFono_Simple_Cb cb, const void *data)
3441 return _ofono_multiparty("HangupMultiparty", cb, data);
3444 OFono_Pending *ofono_private_chat(OFono_Call *c, OFono_Simple_Cb cb,
3449 OFono_Simple_Cb_Context *ctx = NULL;
3450 OFono_Modem *m = _modem_selected_get();
3452 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
3453 EINA_SAFETY_ON_NULL_GOTO(c, error_no_message);
3456 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3457 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
3462 msg = dbus_message_new_method_call(
3463 bus_id, m->base.path,
3464 OFONO_PREFIX OFONO_VOICE_IFACE,
3468 goto error_no_message;
3470 if (!dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
3471 &(c->base.path), DBUS_TYPE_INVALID))
3472 goto error_message_append;
3474 INF("PrivateChat(%s)", c->base.path);
3475 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3478 error_message_append:
3479 dbus_message_unref(msg);
3482 cb((void *)data, OFONO_ERROR_FAILED);
3487 static OFono_Callback_List_Modem_Node * _ofono_callback_modem_node_create(
3488 void (*cb)(void *data),const void *data)
3490 OFono_Callback_List_Modem_Node *node_new;
3492 node_new = calloc(1, sizeof(OFono_Callback_List_Modem_Node));
3493 EINA_SAFETY_ON_NULL_RETURN_VAL(node_new, NULL);
3495 node_new->cb_data = data;
3501 OFono_Callback_List_Modem_Node *
3502 ofono_modem_conected_cb_add(void (*cb)(void *data), const void *data)
3504 OFono_Callback_List_Modem_Node *node;
3506 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3507 node = _ofono_callback_modem_node_create(cb, data);
3508 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3510 cbs_modem_connected = eina_inlist_append(cbs_modem_connected,
3511 EINA_INLIST_GET(node));
3516 OFono_Callback_List_Modem_Node *
3517 ofono_modem_disconnected_cb_add(void (*cb)(void *data), const void *data)
3519 OFono_Callback_List_Modem_Node *node;
3521 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3522 node = _ofono_callback_modem_node_create(cb, data);
3523 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3525 cbs_modem_disconnected = eina_inlist_append(cbs_modem_disconnected,
3526 EINA_INLIST_GET(node));
3531 OFono_Callback_List_Modem_Node *
3532 ofono_modem_changed_cb_add(void (*cb)(void *data), const void *data)
3534 OFono_Callback_List_Modem_Node *node;
3536 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3537 node = _ofono_callback_modem_node_create(cb, data);
3538 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3540 cbs_modem_changed = eina_inlist_append(cbs_modem_changed,
3541 EINA_INLIST_GET(node));
3546 static void _ofono_callback_modem_list_delete(Eina_Inlist **list,
3547 OFono_Callback_List_Modem_Node *node)
3549 EINA_SAFETY_ON_NULL_RETURN(*list);
3550 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3554 void ofono_modem_changed_cb_del(OFono_Callback_List_Modem_Node *node)
3556 EINA_SAFETY_ON_NULL_RETURN(node);
3557 _ofono_callback_modem_list_delete(&cbs_modem_changed, node);
3560 void ofono_modem_disconnected_cb_del(OFono_Callback_List_Modem_Node *node)
3562 EINA_SAFETY_ON_NULL_RETURN(node);
3563 _ofono_callback_modem_list_delete(&cbs_modem_disconnected, node);
3566 void ofono_modem_connected_cb_del(OFono_Callback_List_Modem_Node *node)
3568 EINA_SAFETY_ON_NULL_RETURN(node);
3569 _ofono_callback_modem_list_delete(&cbs_modem_connected, node);
3572 static OFono_Callback_List_Call_Node *_ofono_callback_call_node_create(
3573 void (*cb)(void *data, OFono_Call *call),const void *data)
3575 OFono_Callback_List_Call_Node *node;
3577 node = calloc(1, sizeof(OFono_Callback_List_Call_Node));
3578 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3580 node->cb_data = data;
3586 static OFono_Callback_List_Call_Disconnected_Node *
3587 _ofono_callback_call_disconnected_node_create(
3588 void (*cb)(void *data, OFono_Call *call, const char *reason),
3591 OFono_Callback_List_Call_Disconnected_Node *node;
3593 node = calloc(1, sizeof(OFono_Callback_List_Call_Disconnected_Node));
3594 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3596 node->cb_data = data;
3602 static OFono_Callback_List_USSD_Notify_Node *
3603 _ofono_callback_ussd_notify_node_create(
3604 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3607 OFono_Callback_List_USSD_Notify_Node *node;
3609 node = calloc(1, sizeof(OFono_Callback_List_USSD_Notify_Node));
3610 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3612 node->cb_data = data;
3618 OFono_Callback_List_Call_Node *ofono_call_added_cb_add(
3619 void (*cb)(void *data,OFono_Call *call), const void *data)
3621 OFono_Callback_List_Call_Node *node;
3623 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3624 node = _ofono_callback_call_node_create(cb, data);
3625 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3627 cbs_call_added = eina_inlist_append(cbs_call_added,
3628 EINA_INLIST_GET(node));
3633 OFono_Callback_List_Call_Node *ofono_call_removed_cb_add(
3634 void (*cb)(void *data, OFono_Call *call), const void *data)
3636 OFono_Callback_List_Call_Node *node;
3638 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3639 node = _ofono_callback_call_node_create(cb, data);
3640 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3642 cbs_call_removed = eina_inlist_append(cbs_call_removed,
3643 EINA_INLIST_GET(node));
3648 OFono_Callback_List_Call_Node *ofono_call_changed_cb_add(
3649 void (*cb)(void *data, OFono_Call *call), const void *data)
3651 OFono_Callback_List_Call_Node *node;
3653 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3654 node = _ofono_callback_call_node_create(cb, data);
3655 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3657 cbs_call_changed = eina_inlist_append(cbs_call_changed,
3658 EINA_INLIST_GET(node));
3663 OFono_Callback_List_Call_Disconnected_Node *ofono_call_disconnected_cb_add(
3664 void (*cb)(void *data, OFono_Call *call, const char *reason),
3667 OFono_Callback_List_Call_Disconnected_Node *node;
3669 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3670 node = _ofono_callback_call_disconnected_node_create(cb, data);
3671 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3673 cbs_call_disconnected = eina_inlist_append(cbs_call_disconnected,
3674 EINA_INLIST_GET(node));
3679 OFono_Callback_List_USSD_Notify_Node *ofono_ussd_notify_cb_add(
3680 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3683 OFono_Callback_List_USSD_Notify_Node *node;
3685 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3686 node = _ofono_callback_ussd_notify_node_create(cb, data);
3687 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3689 cbs_ussd_notify = eina_inlist_append(cbs_ussd_notify,
3690 EINA_INLIST_GET(node));
3695 static void _ofono_callback_call_list_delete(Eina_Inlist **list,
3696 OFono_Callback_List_Call_Node *node)
3698 EINA_SAFETY_ON_NULL_RETURN(*list);
3699 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3703 void ofono_call_changed_cb_del(OFono_Callback_List_Call_Node *node)
3705 EINA_SAFETY_ON_NULL_RETURN(node);
3706 _ofono_callback_call_list_delete(&cbs_call_changed, node);
3709 void ofono_call_disconnected_cb_del(
3710 OFono_Callback_List_Call_Disconnected_Node *node)
3712 EINA_SAFETY_ON_NULL_RETURN(node);
3713 EINA_SAFETY_ON_NULL_RETURN(cbs_call_disconnected);
3714 cbs_call_disconnected = eina_inlist_remove(cbs_call_disconnected,
3715 EINA_INLIST_GET(node));
3719 void ofono_ussd_notify_cb_del(OFono_Callback_List_USSD_Notify_Node *node)
3721 EINA_SAFETY_ON_NULL_RETURN(node);
3722 EINA_SAFETY_ON_NULL_RETURN(cbs_ussd_notify);
3723 cbs_ussd_notify = eina_inlist_remove(cbs_ussd_notify,
3724 EINA_INLIST_GET(node));
3728 void ofono_call_added_cb_del(OFono_Callback_List_Call_Node *node)
3730 EINA_SAFETY_ON_NULL_RETURN(node);
3731 _ofono_callback_call_list_delete(&cbs_call_added, node);
3734 void ofono_call_removed_cb_del(OFono_Callback_List_Call_Node *node)
3736 EINA_SAFETY_ON_NULL_RETURN(node);
3737 _ofono_callback_call_list_delete(&cbs_call_removed, node);
3740 OFono_Callback_List_Sent_SMS_Node *
3741 ofono_sent_sms_changed_cb_add(OFono_Sent_SMS_Cb cb, const void *data)
3743 OFono_Callback_List_Sent_SMS_Node *node;
3745 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3746 node = calloc(1, sizeof(OFono_Callback_List_Sent_SMS_Node));
3747 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3749 node->cb_data = data;
3751 cbs_sent_sms_changed = eina_inlist_append(cbs_sent_sms_changed,
3752 EINA_INLIST_GET(node));
3757 void ofono_sent_sms_changed_cb_del(OFono_Callback_List_Sent_SMS_Node *node)
3759 EINA_SAFETY_ON_NULL_RETURN(node);
3760 cbs_sent_sms_changed = eina_inlist_remove(cbs_sent_sms_changed,
3761 EINA_INLIST_GET(node));
3765 OFono_Callback_List_Incoming_SMS_Node *
3766 ofono_incoming_sms_cb_add(OFono_Incoming_SMS_Cb cb, const void *data)
3768 OFono_Callback_List_Incoming_SMS_Node *node;
3770 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3771 node = calloc(1, sizeof(OFono_Callback_List_Incoming_SMS_Node));
3772 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3774 node->cb_data = data;
3776 cbs_incoming_sms = eina_inlist_append(cbs_incoming_sms,
3777 EINA_INLIST_GET(node));
3782 void ofono_incoming_sms_cb_del(OFono_Callback_List_Incoming_SMS_Node *node)
3784 EINA_SAFETY_ON_NULL_RETURN(node);
3785 cbs_incoming_sms = eina_inlist_remove(cbs_incoming_sms,
3786 EINA_INLIST_GET(node));
3790 Eina_Bool ofono_voice_is_online(void)
3792 OFono_Modem *m = _modem_selected_get();
3794 /* The modem is expected to be NULL here, because maybe
3795 * OFono isn't up yet.
3800 if (m->interfaces & OFONO_API_VOICE)