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);
34 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
35 OFono_Simple_Cb cb, const void *data);
37 struct _OFono_Callback_List_Modem_Node
40 void (*cb)(void *data);
44 struct _OFono_Callback_List_Call_Node
47 void (*cb)(void *data, OFono_Call *call);
51 struct _OFono_Callback_List_Call_Disconnected_Node
54 void (*cb)(void *data, OFono_Call *call, const char *reason);
58 struct _OFono_Callback_List_USSD_Notify_Node
61 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg);
65 static Eina_Inlist *cbs_modem_changed = NULL;
66 static Eina_Inlist *cbs_modem_connected = NULL;
67 static Eina_Inlist *cbs_modem_disconnected = NULL;
68 static Eina_Inlist *cbs_ussd_notify = NULL;
70 static Eina_Inlist *cbs_call_changed = NULL;
71 static Eina_Inlist *cbs_call_added = NULL;
72 static Eina_Inlist *cbs_call_disconnected = NULL;
73 static Eina_Inlist *cbs_call_removed = NULL;
75 #define OFONO_SERVICE "org.ofono"
77 #define OFONO_PREFIX OFONO_SERVICE "."
78 #define OFONO_PREFIX_ERROR OFONO_SERVICE ".Error."
79 #define OFONO_MODEM_IFACE "Modem"
80 #define OFONO_MANAGER_IFACE "Manager"
81 #define OFONO_SIM_IFACE "SimManager"
82 #define OFONO_NETREG_IFACE "NetworkRegistration"
83 #define OFONO_VOICE_IFACE "VoiceCallManager"
84 #define OFONO_MSG_IFACE "MessageManager"
85 #define OFONO_MSG_WAITING_IFACE "MessageWaiting"
86 #define OFONO_SMART_MSG_IFACE "SmartMessaging"
87 #define OFONO_STK_IFACE "SimToolkit"
89 #define OFONO_CALL_FW_IFACE "CallForwarding"
90 #define OFONO_CALL_VOL_IFACE "CallVolume"
91 #define OFONO_CALL_METER_IFACE "CallMeter"
92 #define OFONO_CALL_SET_IFACE "CallSettings"
93 #define OFONO_CALL_BAR_IFACE "CallBarring"
94 #define OFONO_SUPPL_SERV_IFACE "SupplementaryServices"
95 #define OFONO_TXT_TEL_IFACE "TextTelephony"
96 #define OFONO_CELL_BROAD_IFACE "CellBroadcast"
97 #define OFONO_CONNMAN_IFACE "ConnectionManager"
98 #define OFONO_PUSH_NOTIF_IFACE "PushNotification"
99 #define OFONO_PHONEBOOK_IFACE "Phonebook"
100 #define OFONO_ASN_IFACE "AssistedSatelliteNavigation"
102 static const struct API_Interface_Map {
106 } api_iface_map[] = {
107 #define MAP(bit, name) {bit, name, sizeof(name) - 1}
108 MAP(OFONO_API_SIM, OFONO_SIM_IFACE),
109 MAP(OFONO_API_NETREG, OFONO_NETREG_IFACE),
110 MAP(OFONO_API_VOICE, OFONO_VOICE_IFACE),
111 MAP(OFONO_API_MSG, OFONO_MSG_IFACE),
112 MAP(OFONO_API_MSG_WAITING, OFONO_MSG_WAITING_IFACE),
113 MAP(OFONO_API_SMART_MSG, OFONO_SMART_MSG_IFACE),
114 MAP(OFONO_API_STK, OFONO_STK_IFACE),
115 MAP(OFONO_API_CALL_FW, OFONO_CALL_FW_IFACE),
116 MAP(OFONO_API_CALL_VOL, OFONO_CALL_VOL_IFACE),
117 MAP(OFONO_API_CALL_METER, OFONO_CALL_METER_IFACE),
118 MAP(OFONO_API_CALL_SET, OFONO_CALL_SET_IFACE),
119 MAP(OFONO_API_CALL_BAR, OFONO_CALL_BAR_IFACE),
120 MAP(OFONO_API_SUPPL_SERV, OFONO_SUPPL_SERV_IFACE),
121 MAP(OFONO_API_TXT_TEL, OFONO_TXT_TEL_IFACE),
122 MAP(OFONO_API_CELL_BROAD, OFONO_CELL_BROAD_IFACE),
123 MAP(OFONO_API_CONNMAN, OFONO_CONNMAN_IFACE),
124 MAP(OFONO_API_PUSH_NOTIF, OFONO_PUSH_NOTIF_IFACE),
125 MAP(OFONO_API_PHONEBOOK, OFONO_PHONEBOOK_IFACE),
126 MAP(OFONO_API_ASN, OFONO_ASN_IFACE),
131 static Eina_Bool _dbus_bool_get(DBusMessageIter *itr)
134 dbus_message_iter_get_basic(itr, &val);
138 static const struct Error_Map {
144 #define MAP(id, name, msg) {id, name, msg, sizeof(name) - 1}
145 MAP(OFONO_ERROR_FAILED, "Failed", "Failed"),
146 MAP(OFONO_ERROR_DOES_NOT_EXIST, "DoesNotExist", "Does not exist"),
147 MAP(OFONO_ERROR_IN_PROGRESS, "InProgress", "Operation in progress"),
148 MAP(OFONO_ERROR_IN_USE, "InUse", "Already in use"),
149 MAP(OFONO_ERROR_INVALID_ARGS, "InvalidArguments", "Invalid arguments"),
150 MAP(OFONO_ERROR_INVALID_FORMAT, "InvalidFormat", "Invalid format"),
151 MAP(OFONO_ERROR_ACCESS_DENIED, "AccessDenied", "Access Denied"),
152 MAP(OFONO_ERROR_ATTACH_IN_PROGRESS, "AttachInProgress",
153 "Attach is already in progress"),
154 MAP(OFONO_ERROR_INCORRECT_PASSWORD, "IncorrectPassword",
155 "Incorrect password"),
156 MAP(OFONO_ERROR_NOT_ACTIVE, "NotActive", "Not active"),
157 MAP(OFONO_ERROR_NOT_ALLOWED, "NotAllowed", "Not allowed"),
158 MAP(OFONO_ERROR_NOT_ATTACHED, "NotAttached", "Not attached"),
159 MAP(OFONO_ERROR_NOT_AVAILABLE, "NotAvailable", "Not available"),
160 MAP(OFONO_ERROR_NOT_FOUND, "NotFound", "Not found"),
161 MAP(OFONO_ERROR_NOT_IMPLEMENTED, "NotImplemented", "Not implemented"),
162 MAP(OFONO_ERROR_NOT_RECOGNIZED, "NotRecognized", "Not recognized"),
163 MAP(OFONO_ERROR_NOT_REGISTERED, "NotRegistered", "Not registered"),
164 MAP(OFONO_ERROR_NOT_SUPPORTED, "NotSupported", "Not supported"),
165 MAP(OFONO_ERROR_SIM_NOT_READY, "SimNotReady", "SIM not ready"),
166 MAP(OFONO_ERROR_STK, "SimToolkit", "SIM Toolkit Failed"),
167 MAP(OFONO_ERROR_TIMEDOUT, "Timedout", "Timed out"),
172 const char *ofono_error_message_get(OFono_Error e)
174 const struct Error_Map *itr;
176 if (e == OFONO_ERROR_NONE)
179 for (itr = error_map; itr->name != NULL; itr++)
183 return "Unknown error";
186 static OFono_Error _ofono_error_parse(const char *name)
188 size_t namelen, prefixlen = sizeof(OFONO_PREFIX_ERROR) - 1;
189 const struct Error_Map *itr;
191 /* whenever interfaces are not there due modem being offline */
192 if (strcmp(name, "org.freedesktop.DBus.Error.UnknownMethod") == 0)
193 return OFONO_ERROR_OFFLINE;
195 if (strncmp(name, OFONO_PREFIX_ERROR, prefixlen) != 0)
196 return OFONO_ERROR_FAILED;
199 namelen = strlen(name);
200 for (itr = error_map; itr->name != NULL; itr++)
201 if ((itr->namelen == namelen) &&
202 (memcmp(name, itr->name, namelen) == 0))
205 return OFONO_ERROR_FAILED;
208 typedef struct _OFono_Simple_Cb_Context
212 } OFono_Simple_Cb_Context;
214 static void _ofono_simple_reply(void *data, DBusMessage *msg __UNUSED__,
217 OFono_Simple_Cb_Context *ctx = data;
218 OFono_Error e = OFONO_ERROR_NONE;
220 if (dbus_error_is_set(err)) {
221 DBG("%s: %s", err->name, err->message);
222 e = _ofono_error_parse(err->name);
226 ctx->cb((void *)ctx->data, e);
231 typedef struct _OFono_String_Cb_Context
236 char *(*convert)(DBusMessage *msg);
237 } OFono_String_Cb_Context;
239 static void _ofono_string_reply(void *data, DBusMessage *msg, DBusError *err)
241 OFono_String_Cb_Context *ctx = data;
242 OFono_Error e = OFONO_ERROR_NONE;
245 if (dbus_error_is_set(err)) {
246 DBG("%s: %s", err->name, err->message);
247 e = _ofono_error_parse(err->name);
249 str = ctx->convert(msg);
251 e = OFONO_ERROR_NOT_SUPPORTED;
255 ctx->cb((void *)ctx->data, e, str);
257 DBG("%s %s", ctx->name, str);
263 struct _OFono_Pending
266 DBusPendingCall *pending;
267 E_DBus_Method_Return_Cb cb;
272 struct _OFono_Bus_Object
275 Eina_Inlist *dbus_pending; /* of OFono_Pending */
276 Eina_List *dbus_signals; /* of E_DBus_Signal_Handler */
279 static void _notify_ofono_callbacks_call_list(Eina_Inlist *list,
282 OFono_Callback_List_Call_Node *node;
284 EINA_INLIST_FOREACH(list, node)
285 node->cb((void *) node->cb_data, call);
288 static void _notify_ofono_callbacks_call_disconnected_list(Eina_Inlist *list,
292 OFono_Callback_List_Call_Disconnected_Node *node;
294 DBG("call=%p, reason=%s", call, reason);
296 EINA_INLIST_FOREACH(list, node)
297 node->cb((void *) node->cb_data, call, reason);
300 static void _notify_ofono_callbacks_ussd_notify_list(Eina_Inlist *list,
301 Eina_Bool needs_reply,
304 OFono_Callback_List_USSD_Notify_Node *node;
306 DBG("needs_reply=%hhu, msg=%s", needs_reply, msg);
308 EINA_INLIST_FOREACH(list, node)
309 node->cb((void *) node->cb_data, needs_reply, msg);
312 static void _bus_object_free(OFono_Bus_Object *o)
314 E_DBus_Signal_Handler *sh;
316 eina_stringshare_del(o->path);
318 while (o->dbus_pending) {
319 ofono_pending_cancel(
320 EINA_INLIST_CONTAINER_GET(o->dbus_pending,
324 EINA_LIST_FREE(o->dbus_signals, sh)
325 e_dbus_signal_handler_del(bus_conn, sh);
330 static void _bus_object_message_send_reply(void *data, DBusMessage *reply,
333 OFono_Pending *p = data;
334 OFono_Bus_Object *o = p->owner;
337 p->cb(p->data, reply, err);
339 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
344 static OFono_Pending *_bus_object_message_send(OFono_Bus_Object *o,
346 E_DBus_Method_Return_Cb cb,
350 EINA_SAFETY_ON_NULL_GOTO(o, error);
351 EINA_SAFETY_ON_NULL_GOTO(msg, error);
353 p = calloc(1, sizeof(OFono_Pending));
354 EINA_SAFETY_ON_NULL_GOTO(p, error);
360 p->pending = e_dbus_message_send(
361 bus_conn, msg, _bus_object_message_send_reply, -1, p);
362 EINA_SAFETY_ON_NULL_GOTO(p->pending, error_send);
364 o->dbus_pending = eina_inlist_append(o->dbus_pending,
366 dbus_message_unref(msg);
374 dbus_error_init(&err);
375 dbus_set_error(&err, "Failed", "call setup failed.");
376 cb(data, NULL, &err);
378 dbus_message_unref(msg);
382 void ofono_pending_cancel(OFono_Pending *p)
386 EINA_SAFETY_ON_NULL_RETURN(p);
389 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
395 dbus_error_init(&err);
396 dbus_set_error(&err, "Canceled",
397 "Pending method call was canceled.");
398 p->cb(p->data, NULL, &err);
400 dbus_pending_call_cancel(p->pending);
404 static void _bus_object_signal_listen(OFono_Bus_Object *o, const char *iface,
405 const char *name, E_DBus_Signal_Cb cb,
408 E_DBus_Signal_Handler *sh = e_dbus_signal_handler_add(
409 bus_conn, bus_id, o->path, iface, name, cb, data);
410 EINA_SAFETY_ON_NULL_RETURN(sh);
412 o->dbus_signals = eina_list_append(o->dbus_signals, sh);
415 typedef struct _OFono_Call_Cb_Context
421 } OFono_Call_Cb_Context;
425 OFono_Bus_Object base;
427 const char *incoming_line;
430 time_t full_start_time;
431 OFono_Call_State state;
432 Eina_Bool multiparty : 1;
433 Eina_Bool emergency : 1;
434 OFono_Call_Cb_Context *pending_dial;
439 OFono_Bus_Object base;
442 const char *voicemail_number;
444 unsigned int interfaces;
445 unsigned char strength;
446 unsigned char data_strength;
447 unsigned char speaker_volume;
448 unsigned char microphone_volume;
449 unsigned char voicemail_count;
450 OFono_USSD_State ussd_state;
451 Eina_Bool ignored : 1;
452 Eina_Bool powered : 1;
453 Eina_Bool online : 1;
454 Eina_Bool roaming : 1;
456 Eina_Bool voicemail_waiting : 1;
459 static OFono_Call *_call_new(const char *path)
461 OFono_Call *c = calloc(1, sizeof(OFono_Call));
462 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
464 c->base.path = eina_stringshare_add(path);
465 EINA_SAFETY_ON_NULL_GOTO(c->base.path, error_path);
467 c->start_time = -1.0;
476 static void _call_free(OFono_Call *c)
478 DBG("c=%p %s", c, c->base.path);
480 _notify_ofono_callbacks_call_list(cbs_call_removed, c);
482 eina_stringshare_del(c->line_id);
483 eina_stringshare_del(c->incoming_line);
484 eina_stringshare_del(c->name);
486 _bus_object_free(&c->base);
489 static OFono_Call_State _call_state_parse(const char *str)
491 if (strcmp(str, "active") == 0)
492 return OFONO_CALL_STATE_ACTIVE;
493 else if (strcmp(str, "held") == 0)
494 return OFONO_CALL_STATE_HELD;
495 else if (strcmp(str, "dialing") == 0)
496 return OFONO_CALL_STATE_DIALING;
497 else if (strcmp(str, "alerting") == 0)
498 return OFONO_CALL_STATE_ALERTING;
499 else if (strcmp(str, "incoming") == 0)
500 return OFONO_CALL_STATE_INCOMING;
501 else if (strcmp(str, "waiting") == 0)
502 return OFONO_CALL_STATE_WAITING;
503 else if (strcmp(str, "disconnected") == 0)
504 return OFONO_CALL_STATE_DISCONNECTED;
506 ERR("unknown call state: %s", str);
507 return OFONO_CALL_STATE_DISCONNECTED;
510 static time_t _ofono_time_parse(const char *str)
515 memset(&tm, 0, sizeof(tm));
517 strptime(str, "%Y-%m-%dT%H:%M:%S%z", &tm);
518 zonediff = tm.tm_gmtoff; /* mktime resets it */
520 return mktime(&tm) - zonediff - timezone;
523 static void _call_property_update(OFono_Call *c, const char *key,
524 DBusMessageIter *value)
526 if (strcmp(key, "LineIdentification") == 0) {
528 dbus_message_iter_get_basic(value, &str);
529 DBG("%s LineIdentification %s", c->base.path, str);
530 eina_stringshare_replace(&c->line_id, str);
531 } else if (strcmp(key, "IncomingLine") == 0) {
533 dbus_message_iter_get_basic(value, &str);
534 DBG("%s IncomingLine %s", c->base.path, str);
535 eina_stringshare_replace(&c->incoming_line, str);
536 } else if (strcmp(key, "State") == 0) {
538 OFono_Call_State state;
539 dbus_message_iter_get_basic(value, &str);
540 state = _call_state_parse(str);
541 DBG("%s State %s (%d)", c->base.path, str, state);
543 if (state == OFONO_CALL_STATE_ACTIVE) {
544 if (c->start_time < 0.0)
545 c->start_time = ecore_loop_time_get();
546 if (c->full_start_time == 0)
547 c->full_start_time = time(NULL);
549 } else if (strcmp(key, "Name") == 0) {
551 dbus_message_iter_get_basic(value, &str);
552 DBG("%s Name %s", c->base.path, str);
553 eina_stringshare_replace(&c->name, str);
554 } else if (strcmp(key, "Multiparty") == 0) {
556 dbus_message_iter_get_basic(value, &v);
557 DBG("%s Multiparty %d", c->base.path, v);
559 } else if (strcmp(key, "Emergency") == 0) {
561 dbus_message_iter_get_basic(value, &v);
562 DBG("%s Emergency %d", c->base.path, v);
564 } else if (strcmp(key, "StartTime") == 0) {
565 const char *ts = NULL;
568 dbus_message_iter_get_basic(value, &ts);
570 st = _ofono_time_parse(ts);
572 lt = ecore_loop_time_get();
573 c->start_time = st - ut + lt;
574 c->full_start_time = st;
575 DBG("%s StartTime %f (%s)", c->base.path, c->start_time, ts);
577 DBG("%s %s (unused property)", c->base.path, key);
580 static void _call_property_changed(void *data, DBusMessage *msg)
582 OFono_Call *c = data;
583 DBusMessageIter iter, value;
586 if (!msg || !dbus_message_iter_init(msg, &iter)) {
587 ERR("Could not handle message %p", msg);
591 DBG("path=%s", c->base.path);
593 dbus_message_iter_get_basic(&iter, &key);
594 dbus_message_iter_next(&iter);
595 dbus_message_iter_recurse(&iter, &value);
596 _call_property_update(c, key, &value);
598 _notify_ofono_callbacks_call_list(cbs_call_changed, c);
601 static void _call_disconnect_reason(void *data, DBusMessage *msg)
603 OFono_Call *c = data;
612 DBG("path=%s", c->base.path);
613 c->state = OFONO_CALL_STATE_DISCONNECTED;
615 dbus_error_init(&err);
616 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &reason,
617 DBUS_TYPE_INVALID)) {
618 ERR("Could not get DisconnectReason arguments: %s: %s",
619 err.name, err.message);
620 dbus_error_free(&err);
624 _notify_ofono_callbacks_call_disconnected_list(cbs_call_disconnected,
628 static OFono_Call *_call_common_add(OFono_Modem *m, const char *path)
630 OFono_Call *c = _call_new(path);
631 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
632 eina_hash_add(m->calls, c->base.path, c);
634 _bus_object_signal_listen(&c->base,
635 OFONO_PREFIX "VoiceCall",
637 _call_disconnect_reason, c);
638 _bus_object_signal_listen(&c->base,
639 OFONO_PREFIX "VoiceCall",
641 _call_property_changed, c);
645 static OFono_Call *_call_pending_add(OFono_Modem *m, const char *path,
646 OFono_Call_Cb_Context *ctx)
650 DBG("path=%s, ctx=%p", path, ctx);
652 c = _call_common_add(m, path);
653 c->pending_dial = ctx;
657 static void _call_add(OFono_Modem *m, const char *path, DBusMessageIter *prop)
660 Eina_Bool needs_cb_added;
662 DBG("path=%s, prop=%p", path, prop);
664 c = eina_hash_find(m->calls, path);
667 DBG("Call already exists %p (%s)", c, path);
669 c = _call_common_add(m, path);
670 EINA_SAFETY_ON_NULL_RETURN(c);
673 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
674 dbus_message_iter_next(prop)) {
675 DBusMessageIter entry, value;
678 dbus_message_iter_recurse(prop, &entry);
679 dbus_message_iter_get_basic(&entry, &key);
681 dbus_message_iter_next(&entry);
682 dbus_message_iter_recurse(&entry, &value);
684 _call_property_update(c, key, &value);
687 if (c->pending_dial) {
688 OFono_Call_Cb_Context *ctx = c->pending_dial;
690 ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, c);
692 c->pending_dial = NULL;
693 needs_cb_added = EINA_TRUE;
697 _notify_ofono_callbacks_call_list(cbs_call_added, c);
699 _notify_ofono_callbacks_call_list(cbs_call_changed, c);
702 static void _call_remove(OFono_Modem *m, const char *path)
704 DBG("path=%s", path);
705 eina_hash_del_by_key(m->calls, path);
708 static void _call_added(void *data, DBusMessage *msg)
710 OFono_Modem *m = data;
711 DBusMessageIter iter, properties;
714 if (!msg || !dbus_message_iter_init(msg, &iter)) {
715 ERR("Could not handle message %p", msg);
719 dbus_message_iter_get_basic(&iter, &path);
721 dbus_message_iter_next(&iter);
722 dbus_message_iter_recurse(&iter, &properties);
724 _call_add(m, path, &properties);
727 static void _call_removed(void *data, DBusMessage *msg)
729 OFono_Modem *m = data;
734 ERR("Could not handle message %p", msg);
738 dbus_error_init(&err);
739 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
741 ERR("Could not get CallRemoved arguments: %s: %s",
742 err.name, err.message);
743 dbus_error_free(&err);
747 _call_remove(m, path);
750 static OFono_Modem *_modem_selected_get(void)
752 OFono_Modem *found_path = NULL, *found_api = NULL, *m;
753 unsigned int online = 0, powered = 0;
757 return modem_selected;
759 itr = eina_hash_iterator_data_new(modems);
760 EINA_ITERATOR_FOREACH(itr, m) {
769 if ((modem_path_wanted) && (!found_path)) {
770 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
771 if (m->base.path == modem_path_wanted) {
778 DBG("m=%#x, mask=%#x", m->interfaces, modem_api_mask);
779 if ((m->interfaces & modem_api_mask) == modem_api_mask)
783 eina_iterator_free(itr);
785 INF("found_path=%s, found_api=%s, wanted_path=%s, api_mask=%#x",
786 found_path ? found_path->base.path : "",
787 found_api ? found_api->base.path: "",
788 modem_path_wanted ? modem_path_wanted : "",
792 ERR("No modems powered! Run connman or test/enable-modem");
794 WRN("No modems online! Run connman or test/online-modem");
796 modem_selected = found_path ? found_path : found_api;
797 return modem_selected;
800 static OFono_Pending *_ofono_multiparty(const char *method,
801 OFono_Simple_Cb cb, const void *data)
806 OFono_Simple_Cb_Context *ctx = NULL;
807 OFono_Modem *m = _modem_selected_get();
809 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
812 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
813 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
818 msg = dbus_message_new_method_call(
819 bus_id, m->base.path,
820 OFONO_PREFIX OFONO_VOICE_IFACE,
824 goto error_no_message;
826 if (!dbus_message_append_args(msg, DBUS_TYPE_INVALID))
827 goto error_message_append;
830 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
834 error_message_append:
835 dbus_message_unref(msg);
838 cb((void *)data, OFONO_ERROR_FAILED);
843 OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb,
846 OFono_Simple_Cb_Context *ctx = NULL;
850 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
853 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
854 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
859 msg = dbus_message_new_method_call(
860 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Hangup");
864 INF("Hangup(%s)", c->base.path);
865 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
870 cb((void *)data, OFONO_ERROR_FAILED);
875 OFono_Pending *ofono_call_answer(OFono_Call *c, OFono_Simple_Cb cb,
878 OFono_Simple_Cb_Context *ctx = NULL;
882 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
885 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
886 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
891 msg = dbus_message_new_method_call(
892 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Answer");
896 INF("Answer(%s)", c->base.path);
897 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
902 cb((void *)data, OFONO_ERROR_FAILED);
907 OFono_Call_State ofono_call_state_get(const OFono_Call *c)
909 EINA_SAFETY_ON_NULL_RETURN_VAL(c, OFONO_CALL_STATE_DISCONNECTED);
913 const char *ofono_call_name_get(const OFono_Call *c)
915 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
919 const char *ofono_call_line_id_get(const OFono_Call *c)
921 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
925 Eina_Bool ofono_call_multiparty_get(const OFono_Call *c)
927 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
928 return c->multiparty;
931 double ofono_call_start_time_get(const OFono_Call *c)
933 EINA_SAFETY_ON_NULL_RETURN_VAL(c, -1.0);
934 return c->start_time;
937 time_t ofono_call_full_start_time_get(const OFono_Call *c)
939 EINA_SAFETY_ON_NULL_RETURN_VAL(c, 0);
940 return c->full_start_time;
943 static void _ofono_calls_get_reply(void *data, DBusMessage *msg,
946 OFono_Modem *m = data;
947 DBusMessageIter array, dict;
951 ERR("%s: %s", err->name, err->message);
957 eina_hash_free_buckets(m->calls);
959 if (!dbus_message_iter_init(msg, &array)) {
960 ERR("Could not get calls");
964 dbus_message_iter_recurse(&array, &dict);
965 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
966 dbus_message_iter_next(&dict)) {
967 DBusMessageIter value, properties;
970 dbus_message_iter_recurse(&dict, &value);
971 dbus_message_iter_get_basic(&value, &path);
973 dbus_message_iter_next(&value);
974 dbus_message_iter_recurse(&value, &properties);
976 _call_add(m, path, &properties);
980 static void _modem_calls_load(OFono_Modem *m)
982 DBusMessage *msg = dbus_message_new_method_call(
983 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE,
986 DBG("Get calls of %s", m->base.path);
987 _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m);
990 static OFono_Modem *_modem_new(const char *path)
992 OFono_Modem *m = calloc(1, sizeof(OFono_Modem));
993 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
995 m->base.path = eina_stringshare_add(path);
996 EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
998 m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free));
999 EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls);
1004 eina_stringshare_del(m->base.path);
1010 static void _modem_free(OFono_Modem *m)
1012 DBG("m=%p %s", m, m->base.path);
1014 if (modem_selected == m)
1015 modem_selected = NULL;
1017 eina_stringshare_del(m->name);
1018 eina_stringshare_del(m->serial);
1019 eina_stringshare_del(m->voicemail_number);
1021 eina_hash_free(m->calls);
1023 _bus_object_free(&m->base);
1027 static void _call_volume_property_update(OFono_Modem *m, const char *prop_name,
1028 DBusMessageIter *iter)
1031 if (strcmp(prop_name, "Muted") == 0) {
1032 m->muted = _dbus_bool_get(iter);
1033 DBG("%s Muted %d", m->base.path, m->muted);
1034 } else if (strcmp(prop_name, "SpeakerVolume") == 0) {
1035 dbus_message_iter_get_basic(iter, &m->speaker_volume);
1036 DBG("%s Speaker Volume %hhu", m->base.path, m->speaker_volume);
1037 } else if (strcmp(prop_name, "MicrophoneVolume") == 0) {
1038 dbus_message_iter_get_basic(iter, &m->microphone_volume);
1039 DBG("%s Microphone Volume %hhu", m->base.path, m->speaker_volume);
1041 DBG("%s %s (unused property)", m->base.path, prop_name);
1044 static void _msg_waiting_property_update(OFono_Modem *m, const char *prop_name,
1045 DBusMessageIter *iter)
1048 if (strcmp(prop_name, "VoicemailWaiting") == 0) {
1049 m->voicemail_waiting = _dbus_bool_get(iter);
1050 DBG("%s VoicemailWaiting %d",
1051 m->base.path, m->voicemail_waiting);
1052 } else if (strcmp(prop_name, "VoicemailMessageCount") == 0) {
1053 dbus_message_iter_get_basic(iter, &m->voicemail_count);
1054 DBG("%s VoicemailMessageCount %hhu",
1055 m->base.path, m->voicemail_count);
1056 } else if (strcmp(prop_name, "VoicemailMailboxNumber") == 0) {
1058 dbus_message_iter_get_basic(iter, &s);
1059 eina_stringshare_replace(&(m->voicemail_number), s);
1060 DBG("%s VoicemailMailboxNumber %s",
1061 m->base.path, m->voicemail_number);
1063 DBG("%s %s (unused property)", m->base.path, prop_name);
1066 static OFono_USSD_State _suppl_serv_state_parse(const char *s)
1068 EINA_SAFETY_ON_NULL_RETURN_VAL(s, OFONO_USSD_STATE_IDLE);
1069 if (strcmp(s, "idle") == 0)
1070 return OFONO_USSD_STATE_IDLE;
1071 else if (strcmp(s, "active") == 0)
1072 return OFONO_USSD_STATE_ACTIVE;
1073 else if (strcmp(s, "user-response") == 0)
1074 return OFONO_USSD_STATE_USER_RESPONSE;
1076 ERR("unknown state: %s", s);
1077 return OFONO_USSD_STATE_IDLE;
1080 static void _suppl_serv_property_update(OFono_Modem *m, const char *prop_name,
1081 DBusMessageIter *iter)
1084 if (strcmp(prop_name, "State") == 0) {
1086 dbus_message_iter_get_basic(iter, &s);
1087 m->ussd_state = _suppl_serv_state_parse(s);
1088 DBG("%s USSD.State %d", m->base.path, m->ussd_state);
1090 DBG("%s %s (unused property)", m->base.path, prop_name);
1093 static void _notify_ofono_callbacks_modem_list(Eina_Inlist *list)
1095 OFono_Callback_List_Modem_Node *node;
1097 EINA_INLIST_FOREACH(list, node)
1098 node->cb((void *) node->cb_data);
1101 static void _call_volume_property_changed(void *data, DBusMessage *msg)
1103 OFono_Modem *m = data;
1104 DBusMessageIter iter, variant_iter;
1105 const char *prop_name;
1107 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1108 ERR("Could not handle message %p", msg);
1112 dbus_message_iter_get_basic(&iter, &prop_name);
1113 dbus_message_iter_next(&iter);
1114 dbus_message_iter_recurse(&iter, &variant_iter);
1115 _call_volume_property_update(m, prop_name, &variant_iter);
1117 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1120 static void _msg_waiting_property_changed(void *data, DBusMessage *msg)
1122 OFono_Modem *m = data;
1123 DBusMessageIter iter, variant_iter;
1124 const char *prop_name;
1126 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1127 ERR("Could not handle message %p", msg);
1131 dbus_message_iter_get_basic(&iter, &prop_name);
1132 dbus_message_iter_next(&iter);
1133 dbus_message_iter_recurse(&iter, &variant_iter);
1134 _msg_waiting_property_update(m, prop_name, &variant_iter);
1136 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1139 static void _suppl_serv_property_changed(void *data, DBusMessage *msg)
1141 OFono_Modem *m = data;
1142 DBusMessageIter iter, variant_iter;
1143 const char *prop_name;
1145 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1146 ERR("Could not handle message %p", msg);
1150 dbus_message_iter_get_basic(&iter, &prop_name);
1151 dbus_message_iter_next(&iter);
1152 dbus_message_iter_recurse(&iter, &variant_iter);
1153 _suppl_serv_property_update(m, prop_name, &variant_iter);
1155 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1158 static void _suppl_serv_notification_recv(void *data __UNUSED__,
1161 DBusMessageIter iter;
1164 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1165 ERR("Could not handle message %p", msg);
1169 dbus_message_iter_get_basic(&iter, &s);
1171 _notify_ofono_callbacks_ussd_notify_list(
1172 cbs_ussd_notify, EINA_FALSE, s);
1175 static void _suppl_serv_request_recv(void *data __UNUSED__, DBusMessage *msg)
1177 DBusMessageIter iter;
1180 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1181 ERR("Could not handle message %p", msg);
1185 dbus_message_iter_get_basic(&iter, &s);
1187 _notify_ofono_callbacks_ussd_notify_list(cbs_ussd_notify, EINA_TRUE, s);
1190 static unsigned int _modem_interfaces_extract(DBusMessageIter *array)
1192 DBusMessageIter entry;
1193 unsigned int interfaces = 0;
1195 dbus_message_iter_recurse(array, &entry);
1196 for (; dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING;
1197 dbus_message_iter_next(&entry)) {
1198 const struct API_Interface_Map *itr;
1202 dbus_message_iter_get_basic(&entry, &name);
1204 if (strncmp(name, OFONO_PREFIX, strlen(OFONO_PREFIX)) != 0)
1207 name += strlen(OFONO_PREFIX);
1208 namelen = strlen(name);
1210 DBG("interface: %s", name);
1211 for (itr = api_iface_map; itr->name != NULL; itr++) {
1212 if ((itr->namelen == namelen) &&
1213 (memcmp(itr->name, name, namelen) == 0)) {
1214 interfaces |= itr->bit;
1218 if (itr->name == NULL)
1219 WRN("ignored %s", name);
1225 static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces)
1228 if (((m->interfaces & OFONO_API_CALL_VOL) == 0) &&
1229 (ifaces & OFONO_API_CALL_VOL) == OFONO_API_CALL_VOL)
1230 _ofono_call_volume_properties_get(m);
1232 if (((m->interfaces & OFONO_API_MSG_WAITING) == 0) &&
1233 (ifaces & OFONO_API_MSG_WAITING) == OFONO_API_MSG_WAITING)
1234 _ofono_msg_waiting_properties_get(m);
1236 if (((m->interfaces & OFONO_API_SUPPL_SERV) == 0) &&
1237 (ifaces & OFONO_API_SUPPL_SERV) == OFONO_API_SUPPL_SERV)
1238 _ofono_suppl_serv_properties_get(m);
1241 static void _modem_property_update(OFono_Modem *m, const char *key,
1242 DBusMessageIter *value)
1244 if (strcmp(key, "Powered") == 0) {
1245 m->powered = _dbus_bool_get(value);
1246 DBG("%s Powered %d", m->base.path, m->powered);
1247 } else if (strcmp(key, "Online") == 0) {
1248 m->online = _dbus_bool_get(value);
1249 DBG("%s Online %d", m->base.path, m->online);
1250 } else if (strcmp(key, "Interfaces") == 0) {
1251 unsigned int ifaces = _modem_interfaces_extract(value);
1252 DBG("%s Interfaces 0x%02x", m->base.path, ifaces);
1253 if (m->interfaces != ifaces) {
1254 _modem_update_interfaces(m, ifaces);
1255 m->interfaces = ifaces;
1257 if (modem_selected && modem_path_wanted &&
1258 modem_selected->base.path != modem_path_wanted)
1259 modem_selected = NULL;
1261 } else if (strcmp(key, "Serial") == 0) {
1263 dbus_message_iter_get_basic(value, &serial);
1264 DBG("%s Serial %s", m->base.path, serial);
1265 eina_stringshare_replace(&m->serial, serial);
1266 } else if (strcmp(key, "Type") == 0) {
1268 dbus_message_iter_get_basic(value, &type);
1269 DBG("%s Type %s", m->base.path, type);
1272 m->ignored = EINA_FALSE;
1276 m->ignored = EINA_TRUE;
1277 EINA_LIST_FOREACH(modem_types, n, t) {
1278 if (strcmp(t, type) == 0) {
1279 m->ignored = EINA_FALSE;
1284 INF("Modem %s type %s is ignored",
1285 m->base.path, type);
1288 DBG("%s %s (unused property)", m->base.path, key);
1291 static void _ofono_call_volume_properties_get_reply(void *data,
1295 OFono_Modem *m = data;
1296 DBusMessageIter iter, prop;
1298 if (dbus_error_is_set(err)) {
1299 DBG("%s: %s", err->name, err->message);
1303 dbus_message_iter_init(msg, &iter);
1304 dbus_message_iter_recurse(&iter, &prop);
1306 DBG("m=%s", m->base.path);
1307 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1308 dbus_message_iter_next(&prop)) {
1309 DBusMessageIter entry, value;
1312 dbus_message_iter_recurse(&prop, &entry);
1313 dbus_message_iter_get_basic(&entry, &key);
1315 dbus_message_iter_next(&entry);
1316 dbus_message_iter_recurse(&entry, &value);
1317 _call_volume_property_update(m, key, &value);
1320 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1323 static void _ofono_call_volume_properties_get(OFono_Modem *m)
1326 msg = dbus_message_new_method_call(bus_id, m->base.path,
1328 OFONO_CALL_VOL_IFACE,
1330 DBG("m=%s", m->base.path);
1331 EINA_SAFETY_ON_NULL_RETURN(msg);
1333 _bus_object_message_send(&m->base, msg,
1334 _ofono_call_volume_properties_get_reply, m);
1337 static void _ofono_msg_waiting_properties_get_reply(void *data,
1341 OFono_Modem *m = data;
1342 DBusMessageIter iter, prop;
1344 if (dbus_error_is_set(err)) {
1345 DBG("%s: %s", err->name, err->message);
1349 dbus_message_iter_init(msg, &iter);
1350 dbus_message_iter_recurse(&iter, &prop);
1352 DBG("m=%s", m->base.path);
1353 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1354 dbus_message_iter_next(&prop)) {
1355 DBusMessageIter entry, value;
1358 dbus_message_iter_recurse(&prop, &entry);
1359 dbus_message_iter_get_basic(&entry, &key);
1361 dbus_message_iter_next(&entry);
1362 dbus_message_iter_recurse(&entry, &value);
1363 _msg_waiting_property_update(m, key, &value);
1366 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1369 static void _ofono_msg_waiting_properties_get(OFono_Modem *m)
1372 msg = dbus_message_new_method_call(bus_id, m->base.path,
1374 OFONO_MSG_WAITING_IFACE,
1376 DBG("m=%s", m->base.path);
1377 EINA_SAFETY_ON_NULL_RETURN(msg);
1379 _bus_object_message_send(&m->base, msg,
1380 _ofono_msg_waiting_properties_get_reply, m);
1383 static void _ofono_suppl_serv_properties_get_reply(void *data,
1387 OFono_Modem *m = data;
1388 DBusMessageIter iter, prop;
1390 if (dbus_error_is_set(err)) {
1391 DBG("%s: %s", err->name, err->message);
1395 dbus_message_iter_init(msg, &iter);
1396 dbus_message_iter_recurse(&iter, &prop);
1398 DBG("m=%s", m->base.path);
1399 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1400 dbus_message_iter_next(&prop)) {
1401 DBusMessageIter entry, value;
1404 dbus_message_iter_recurse(&prop, &entry);
1405 dbus_message_iter_get_basic(&entry, &key);
1407 dbus_message_iter_next(&entry);
1408 dbus_message_iter_recurse(&entry, &value);
1409 _suppl_serv_property_update(m, key, &value);
1412 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1415 static void _ofono_suppl_serv_properties_get(OFono_Modem *m)
1418 msg = dbus_message_new_method_call(bus_id, m->base.path,
1420 OFONO_SUPPL_SERV_IFACE,
1422 DBG("m=%s", m->base.path);
1423 EINA_SAFETY_ON_NULL_RETURN(msg);
1425 _bus_object_message_send(&m->base, msg,
1426 _ofono_suppl_serv_properties_get_reply, m);
1429 static void _modem_add(const char *path, DBusMessageIter *prop)
1433 DBG("path=%s", path);
1435 m = eina_hash_find(modems, path);
1437 DBG("Modem already exists %p (%s)", m, path);
1438 goto update_properties;
1441 m = _modem_new(path);
1442 EINA_SAFETY_ON_NULL_RETURN(m);
1443 eina_hash_add(modems, m->base.path, m);
1445 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1446 "CallAdded", _call_added, m);
1447 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1448 "CallRemoved", _call_removed, m);
1449 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1451 _call_volume_property_changed, m);
1452 _bus_object_signal_listen(&m->base,
1453 OFONO_PREFIX OFONO_MSG_WAITING_IFACE,
1455 _msg_waiting_property_changed, m);
1456 _bus_object_signal_listen(&m->base,
1457 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1459 _suppl_serv_property_changed, m);
1460 _bus_object_signal_listen(&m->base,
1461 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1462 "NotificationReceived",
1463 _suppl_serv_notification_recv, m);
1464 _bus_object_signal_listen(&m->base,
1465 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1467 _suppl_serv_request_recv, m);
1469 /* TODO: do we need to listen to BarringActive or Forwarded? */
1471 if (modem_selected && modem_path_wanted &&
1472 modem_selected->base.path != modem_path_wanted)
1473 modem_selected = NULL;
1478 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
1479 dbus_message_iter_next(prop)) {
1480 DBusMessageIter entry, value;
1483 dbus_message_iter_recurse(prop, &entry);
1484 dbus_message_iter_get_basic(&entry, &key);
1486 dbus_message_iter_next(&entry);
1487 dbus_message_iter_recurse(&entry, &value);
1489 _modem_property_update(m, key, &value);
1492 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1494 if (m->interfaces & OFONO_API_VOICE)
1495 _modem_calls_load(m);
1498 static void _modem_remove(const char *path)
1500 DBG("path=%s", path);
1501 eina_hash_del_by_key(modems, path);
1504 static void _ofono_modems_get_reply(void *data __UNUSED__, DBusMessage *msg,
1507 DBusMessageIter array, dict;
1509 pc_get_modems = NULL;
1513 ERR("%s: %s", err->name, err->message);
1519 EINA_SAFETY_ON_NULL_RETURN(modems);
1520 eina_hash_free_buckets(modems);
1522 if (!dbus_message_iter_init(msg, &array)) {
1523 ERR("Could not get modems");
1527 dbus_message_iter_recurse(&array, &dict);
1528 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
1529 dbus_message_iter_next(&dict)) {
1530 DBusMessageIter value, properties;
1533 dbus_message_iter_recurse(&dict, &value);
1534 dbus_message_iter_get_basic(&value, &path);
1536 dbus_message_iter_next(&value);
1537 dbus_message_iter_recurse(&value, &properties);
1539 _modem_add(path, &properties);
1543 static void _modem_added(void *data __UNUSED__, DBusMessage *msg)
1545 DBusMessageIter iter, properties;
1548 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1549 ERR("Could not handle message %p", msg);
1553 dbus_message_iter_get_basic(&iter, &path);
1555 dbus_message_iter_next(&iter);
1556 dbus_message_iter_recurse(&iter, &properties);
1558 _modem_add(path, &properties);
1561 static void _modem_removed(void *data __UNUSED__, DBusMessage *msg)
1567 ERR("Could not handle message %p", msg);
1571 dbus_error_init(&err);
1572 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
1574 ERR("Could not get ModemRemoved arguments: %s: %s",
1575 err.name, err.message);
1576 dbus_error_free(&err);
1580 _modem_remove(path);
1583 static void _modem_property_changed(void *data __UNUSED__, DBusMessage *msg)
1587 DBusMessageIter iter, value;
1590 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1591 ERR("Could not handle message %p", msg);
1595 path = dbus_message_get_path(msg);
1596 DBG("path=%s", path);
1598 m = eina_hash_find(modems, path);
1600 DBG("Modem is unknown (%s)", path);
1604 dbus_message_iter_get_basic(&iter, &key);
1605 dbus_message_iter_next(&iter);
1606 dbus_message_iter_recurse(&iter, &value);
1607 _modem_property_update(m, key, &value);
1609 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1612 static void _modems_load(void)
1614 DBusMessage *msg = dbus_message_new_method_call(
1615 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
1618 dbus_pending_call_cancel(pc_get_modems);
1621 pc_get_modems = e_dbus_message_send(
1622 bus_conn, msg, _ofono_modems_get_reply, -1, NULL);
1623 dbus_message_unref(msg);
1626 static void _ofono_connected(const char *id)
1629 bus_id = strdup(id);
1631 sig_modem_added = e_dbus_signal_handler_add(
1632 bus_conn, bus_id, "/",
1633 OFONO_PREFIX OFONO_MANAGER_IFACE,
1635 _modem_added, NULL);
1637 sig_modem_removed = e_dbus_signal_handler_add(
1638 bus_conn, bus_id, "/",
1639 OFONO_PREFIX OFONO_MANAGER_IFACE,
1641 _modem_removed, NULL);
1643 sig_modem_prop_changed = e_dbus_signal_handler_add(
1644 bus_conn, bus_id, NULL,
1645 OFONO_PREFIX OFONO_MODEM_IFACE,
1647 _modem_property_changed, NULL);
1651 _notify_ofono_callbacks_modem_list(cbs_modem_connected);
1654 static void _ofono_disconnected(void)
1656 eina_hash_free_buckets(modems);
1658 if (sig_modem_added) {
1659 e_dbus_signal_handler_del(bus_conn, sig_modem_added);
1660 sig_modem_added = NULL;
1663 if (sig_modem_removed) {
1664 e_dbus_signal_handler_del(bus_conn, sig_modem_removed);
1665 sig_modem_removed = NULL;
1668 if (sig_modem_prop_changed) {
1669 e_dbus_signal_handler_del(bus_conn, sig_modem_prop_changed);
1670 sig_modem_prop_changed = NULL;
1674 _notify_ofono_callbacks_modem_list(cbs_modem_disconnected);
1680 static void _name_owner_changed(void *data __UNUSED__, DBusMessage *msg)
1683 const char *name, *from, *to;
1685 dbus_error_init(&err);
1686 if (!dbus_message_get_args(msg, &err,
1687 DBUS_TYPE_STRING, &name,
1688 DBUS_TYPE_STRING, &from,
1689 DBUS_TYPE_STRING, &to,
1690 DBUS_TYPE_INVALID)) {
1691 ERR("Could not get NameOwnerChanged arguments: %s: %s",
1692 err.name, err.message);
1693 dbus_error_free(&err);
1697 if (strcmp(name, bus_name) != 0)
1700 DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
1702 if (from[0] == '\0' && to[0] != '\0') {
1703 INF("oFono appeared as %s", to);
1704 _ofono_connected(to);
1705 } else if (from[0] != '\0' && to[0] == '\0') {
1706 INF("oFono disappeared from %s", from);
1707 _ofono_disconnected();
1711 static void _ofono_get_name_owner(void *data __UNUSED__, DBusMessage *msg, DBusError *err)
1713 DBusMessageIter itr;
1718 ERR("%s: %s", err->name, err->message);
1724 dbus_message_iter_init(msg, &itr);
1725 dbus_message_iter_get_basic(&itr, &id);
1726 if (!id || id[0] == '\0') {
1727 ERR("No name owner fo %s!", bus_name);
1731 INF("oFono bus id: %s", id);
1732 _ofono_connected(id);
1735 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
1736 const char *new, OFono_Simple_Cb cb,
1739 OFono_Simple_Cb_Context *ctx = NULL;
1740 OFono_Error err = OFONO_ERROR_OFFLINE;
1743 OFono_Modem *m = _modem_selected_get();
1744 EINA_SAFETY_ON_NULL_GOTO(m, error);
1745 EINA_SAFETY_ON_NULL_GOTO(what, error);
1746 EINA_SAFETY_ON_NULL_GOTO(old, error);
1747 EINA_SAFETY_ON_NULL_GOTO(new, error);
1749 if ((m->interfaces & OFONO_API_SIM) == 0)
1751 err = OFONO_ERROR_FAILED;
1754 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1755 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1760 msg = dbus_message_new_method_call(
1761 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
1766 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1767 DBUS_TYPE_STRING, &old,
1768 DBUS_TYPE_STRING, &new,
1772 INF("ChangePin(%s, %s, %s)", what, old, new);
1773 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1777 dbus_message_unref(msg);
1780 cb((void *)data, err);
1785 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
1786 const char *new, OFono_Simple_Cb cb,
1789 OFono_Simple_Cb_Context *ctx = NULL;
1790 OFono_Error err = OFONO_ERROR_OFFLINE;
1793 OFono_Modem *m = _modem_selected_get();
1794 EINA_SAFETY_ON_NULL_GOTO(m, error);
1795 EINA_SAFETY_ON_NULL_GOTO(what, error);
1796 EINA_SAFETY_ON_NULL_GOTO(puk, error);
1797 EINA_SAFETY_ON_NULL_GOTO(new, error);
1799 if ((m->interfaces & OFONO_API_SIM) == 0)
1801 err = OFONO_ERROR_FAILED;
1804 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1805 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1810 msg = dbus_message_new_method_call(
1811 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
1815 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1816 DBUS_TYPE_STRING, &puk,
1817 DBUS_TYPE_STRING, &new,
1821 INF("ResetPin(%s, %s, %s)", what, puk, new);
1822 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1826 dbus_message_unref(msg);
1829 cb((void *)data, err);
1834 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
1835 DBusMessageIter *itr)
1837 const char *ussd_response;
1839 if (dbus_message_iter_get_arg_type(itr) != DBUS_TYPE_STRING) {
1840 ERR("Invalid type: %c (expected: %c)",
1841 dbus_message_iter_get_arg_type(itr), DBUS_TYPE_STRING);
1844 dbus_message_iter_get_basic(itr, &ussd_response);
1845 EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
1846 return strdup(ussd_response);
1849 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
1850 DBusMessageIter *dict)
1852 for (; dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY;
1853 dbus_message_iter_next(dict)) {
1854 DBusMessageIter e, v;
1855 const char *key, *value;
1857 dbus_message_iter_recurse(dict, &e);
1858 dbus_message_iter_get_basic(&e, &key);
1860 dbus_message_iter_next(&e);
1861 dbus_message_iter_recurse(&e, &v);
1862 dbus_message_iter_get_basic(&v, &value);
1864 eina_strbuf_append_printf(buf, " %s=%s<br>",
1869 static char *_ss_initiate_convert_call1(const char *type, DBusMessageIter *itr)
1871 DBusMessageIter array, dict;
1872 const char *ss_op, *service;
1876 dbus_message_iter_recurse(itr, &array);
1878 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1879 ERR("Invalid type: %c (expected: %c)",
1880 dbus_message_iter_get_arg_type(&array),
1884 dbus_message_iter_get_basic(&array, &ss_op);
1885 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1887 if (!dbus_message_iter_next(&array)) {
1888 ERR("Missing %s service", type);
1892 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1893 ERR("Invalid type: %c (expected: %c)",
1894 dbus_message_iter_get_arg_type(&array),
1898 dbus_message_iter_get_basic(&array, &service);
1899 EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
1901 if (!dbus_message_iter_next(&array)) {
1902 ERR("Missing %s information", type);
1906 buf = eina_strbuf_new();
1907 eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
1908 type, ss_op, service);
1910 dbus_message_iter_recurse(&array, &dict);
1911 _ss_initiate_cb_dict_convert(buf, &dict);
1913 str = eina_strbuf_string_steal(buf);
1914 eina_strbuf_free(buf);
1918 static char *_ss_initiate_convert_call_waiting(const char *type,
1919 DBusMessageIter *itr)
1921 DBusMessageIter array, dict;
1926 dbus_message_iter_recurse(itr, &array);
1928 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1929 ERR("Invalid type: %c (expected: %c)",
1930 dbus_message_iter_get_arg_type(&array),
1934 dbus_message_iter_get_basic(&array, &ss_op);
1935 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1937 if (!dbus_message_iter_next(&array)) {
1938 ERR("Missing %s information", type);
1942 buf = eina_strbuf_new();
1943 eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
1946 dbus_message_iter_recurse(&array, &dict);
1947 _ss_initiate_cb_dict_convert(buf, &dict);
1949 str = eina_strbuf_string_steal(buf);
1950 eina_strbuf_free(buf);
1954 static char *_ss_initiate_convert_call2(const char *type,
1955 DBusMessageIter *itr)
1957 DBusMessageIter array;
1958 const char *ss_op, *status;
1962 dbus_message_iter_recurse(itr, &array);
1964 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1965 ERR("Invalid type: %c (expected: %c)",
1966 dbus_message_iter_get_arg_type(&array),
1970 dbus_message_iter_get_basic(&array, &ss_op);
1971 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1973 if (!dbus_message_iter_next(&array)) {
1974 ERR("Missing %s status", type);
1978 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1979 ERR("Invalid type: %c (expected: %c)",
1980 dbus_message_iter_get_arg_type(&array),
1984 dbus_message_iter_get_basic(&array, &status);
1985 EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
1987 buf = eina_strbuf_new();
1988 eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
1989 type, ss_op, status);
1991 str = eina_strbuf_string_steal(buf);
1992 eina_strbuf_free(buf);
1996 static const struct SS_Initiate_Convert_Map {
1999 char *(*convert)(const char *type, DBusMessageIter *itr);
2000 } ss_initiate_convert_map[] = {
2001 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
2002 MAP("USSD", _ss_initiate_convert_ussd),
2003 MAP("CallBarring", _ss_initiate_convert_call1),
2004 MAP("CallForwarding", _ss_initiate_convert_call1),
2005 MAP("CallWaiting", _ss_initiate_convert_call_waiting),
2006 MAP("CallingLinePresentation", _ss_initiate_convert_call2),
2007 MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
2008 MAP("CallingLineRestriction", _ss_initiate_convert_call2),
2009 MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
2014 static char *_ss_initiate_convert(DBusMessage *msg)
2016 DBusMessageIter array, variant;
2017 const struct SS_Initiate_Convert_Map *citr;
2018 const char *type = NULL;
2021 if (!dbus_message_iter_init(msg, &array))
2024 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
2025 ERR("Invalid type for first argument: %c (expected: %c)",
2026 dbus_message_iter_get_arg_type(&array),
2030 dbus_message_iter_get_basic(&array, &type);
2032 ERR("Couldn't get SupplementaryServices.Initiate type");
2035 DBG("type: %s", type);
2037 if (!dbus_message_iter_next(&array)) {
2038 ERR("Couldn't get SupplementaryServices.Initiate payload");
2041 dbus_message_iter_recurse(&array, &variant);
2043 typelen = strlen(type);
2044 for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
2045 if ((citr->typelen == typelen) &&
2046 (memcmp(citr->type, type, typelen) == 0)) {
2047 return citr->convert(type, &variant);
2050 ERR("Could not convert SupplementaryServices.Initiate type %s", type);
2056 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
2058 OFono_String_Cb_Context *ctx = NULL;
2059 OFono_Error err = OFONO_ERROR_OFFLINE;
2062 OFono_Modem *m = _modem_selected_get();
2063 EINA_SAFETY_ON_NULL_GOTO(m, error);
2064 EINA_SAFETY_ON_NULL_GOTO(command, error);
2066 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2068 err = OFONO_ERROR_FAILED;
2070 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2071 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2074 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2075 ctx->convert = _ss_initiate_convert;
2077 msg = dbus_message_new_method_call(
2078 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2083 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &command,
2087 INF("SupplementaryServices.Initiate(%s)", command);
2088 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2092 dbus_message_unref(msg);
2095 cb((void *)data, err, NULL);
2100 static char *_ussd_respond_convert(DBusMessage *msg)
2102 DBusMessageIter itr;
2105 if (!msg || !dbus_message_iter_init(msg, &itr)) {
2106 ERR("Could not handle message %p", msg);
2110 if (dbus_message_iter_get_arg_type(&itr) != DBUS_TYPE_STRING) {
2111 ERR("Invalid type: %c (expected: %c)",
2112 dbus_message_iter_get_arg_type(&itr), DBUS_TYPE_STRING);
2115 dbus_message_iter_get_basic(&itr, &s);
2116 EINA_SAFETY_ON_NULL_RETURN_VAL(s, NULL);
2120 OFono_Pending *ofono_ussd_respond(const char *string,
2121 OFono_String_Cb cb, const void *data)
2123 OFono_String_Cb_Context *ctx = NULL;
2124 OFono_Error err = OFONO_ERROR_OFFLINE;
2127 OFono_Modem *m = _modem_selected_get();
2128 EINA_SAFETY_ON_NULL_GOTO(m, error);
2129 EINA_SAFETY_ON_NULL_GOTO(string, error);
2131 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2133 err = OFONO_ERROR_FAILED;
2135 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2136 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2139 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2140 ctx->convert = _ussd_respond_convert;
2142 msg = dbus_message_new_method_call(
2143 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2148 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &string,
2152 INF("SupplementaryServices.Respond(%s)", string);
2153 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2157 dbus_message_unref(msg);
2160 cb((void *)data, err, NULL);
2165 OFono_Pending *ofono_ussd_cancel(OFono_Simple_Cb cb, const void *data)
2167 return _ofono_simple_do(OFONO_API_SUPPL_SERV, "Cancel", cb, data);
2170 static void _ofono_dial_reply(void *data, DBusMessage *msg, DBusError *err)
2172 OFono_Call_Cb_Context *ctx = data;
2173 OFono_Call *c = NULL;
2174 OFono_Error oe = OFONO_ERROR_NONE;
2177 DBG("%s: %s", err->name, err->message);
2178 oe = _ofono_error_parse(err->name);
2182 dbus_error_init(&e);
2183 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
2184 &path, DBUS_TYPE_INVALID)) {
2185 ERR("Could not get Dial reply: %s: %s",
2187 dbus_error_free(&e);
2188 oe = OFONO_ERROR_FAILED;
2190 c = eina_hash_find(ctx->modem->calls, path);
2191 DBG("path=%s, existing call=%p", path, c);
2193 c = _call_pending_add(ctx->modem, path, ctx);
2195 /* ctx->cb will be dispatched on
2196 * CallAdded signal handler.
2202 ERR("Could not find call %s", path);
2203 oe = OFONO_ERROR_FAILED;
2208 ctx->cb((void *)ctx->data, oe, c);
2213 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
2214 OFono_Call_Cb cb, const void *data)
2216 OFono_Call_Cb_Context *ctx = NULL;
2217 OFono_Error err = OFONO_ERROR_OFFLINE;
2220 OFono_Modem *m = _modem_selected_get();
2221 EINA_SAFETY_ON_NULL_GOTO(m, error);
2224 if ((m->interfaces & OFONO_API_VOICE) == 0)
2226 err = OFONO_ERROR_FAILED;
2231 ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
2232 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2235 ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
2238 msg = dbus_message_new_method_call(
2239 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
2243 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
2244 DBUS_TYPE_STRING, &hide_callerid,
2248 INF("Dial(%s, %s)", number, hide_callerid);
2249 p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
2253 dbus_message_unref(msg);
2256 cb((void *)data, err, NULL);
2261 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
2262 OFono_Simple_Cb cb, const void *data)
2264 OFono_Simple_Cb_Context *ctx = NULL;
2265 OFono_Error err = OFONO_ERROR_OFFLINE;
2268 char iface[128] = "";
2269 const struct API_Interface_Map *itr;
2270 OFono_Modem *m = _modem_selected_get();
2271 EINA_SAFETY_ON_NULL_GOTO(m, error);
2272 EINA_SAFETY_ON_NULL_GOTO(method, error);
2274 if ((m->interfaces & api) == 0)
2276 err = OFONO_ERROR_FAILED;
2278 for (itr = api_iface_map; itr->name != NULL; itr++) {
2279 if (itr->bit == api) {
2280 snprintf(iface, sizeof(iface), "%s%s",
2281 OFONO_PREFIX, itr->name);
2285 if (iface[0] == '\0') {
2286 ERR("Could not map api %d to interface name!", api);
2291 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2292 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2297 msg = dbus_message_new_method_call(bus_id, m->base.path, iface, method);
2301 INF("%s.%s()", iface, method);
2302 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2307 cb((void *)data, err);
2312 OFono_Pending *ofono_transfer(OFono_Simple_Cb cb, const void *data)
2314 return _ofono_simple_do(OFONO_API_VOICE, "Transfer", cb, data);
2317 OFono_Pending *ofono_swap_calls(OFono_Simple_Cb cb, const void *data)
2319 return _ofono_simple_do(OFONO_API_VOICE, "SwapCalls", cb, data);
2322 OFono_Pending *ofono_release_and_answer(OFono_Simple_Cb cb, const void *data)
2324 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndAnswer", cb, data);
2327 OFono_Pending *ofono_release_and_swap(OFono_Simple_Cb cb, const void *data)
2329 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndSwap", cb, data);
2332 OFono_Pending *ofono_hold_and_answer(OFono_Simple_Cb cb, const void *data)
2334 return _ofono_simple_do(OFONO_API_VOICE, "HoldAndAnswer", cb, data);
2337 OFono_Pending *ofono_hangup_all(OFono_Simple_Cb cb, const void *data)
2339 return _ofono_simple_do(OFONO_API_VOICE, "HangupAll", cb, data);
2342 const char *ofono_modem_serial_get(void)
2344 OFono_Modem *m = _modem_selected_get();
2345 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
2349 void ofono_modem_api_require(const char *spec)
2351 unsigned int api_mask = 0;
2352 const char *name = spec;
2354 EINA_SAFETY_ON_NULL_RETURN(spec);
2357 const struct API_Interface_Map *itr;
2359 unsigned int namelen;
2361 p = strchr(name, ',');
2365 namelen = strlen(name);
2367 for (itr = api_iface_map; itr->name != NULL; itr++) {
2368 if ((itr->namelen == namelen) &&
2369 (memcmp(itr->name, name, namelen) == 0)) {
2370 api_mask |= itr->bit;
2374 if (itr->name == NULL)
2375 WRN("Unknown oFono API: %.*s", namelen, name);
2384 DBG("API parsed: '%s' = %#x", spec, api_mask);
2386 ERR("Could not parse API: %s", spec);
2390 if (modem_api_mask == api_mask)
2392 modem_api_mask = api_mask;
2393 modem_selected = NULL;
2396 void ofono_modem_api_list(FILE *fp, const char *prefix, const char *suffix)
2398 const struct API_Interface_Map *itr;
2399 for (itr = api_iface_map; itr->name != NULL; itr++)
2400 fprintf(fp, "%s%s%s", prefix, itr->name, suffix);
2403 void ofono_modem_type_require(const char *spec)
2405 Eina_List *lst = NULL;
2406 const char *name = spec;
2408 EINA_SAFETY_ON_NULL_RETURN(spec);
2413 unsigned int namelen;
2415 p = strchr(name, ',');
2419 namelen = strlen(name);
2421 for (itr = known_modem_types; *itr != NULL; itr++) {
2422 unsigned int itrlen = strlen(*itr);
2423 if ((itrlen == namelen) &&
2424 (memcmp(*itr, name, namelen) == 0)) {
2425 lst = eina_list_append(lst, *itr);
2430 WRN("Unknown oFono type: %.*s", namelen, name);
2439 DBG("Type parsed: '%s'", spec);
2441 ERR("Could not parse type: %s", spec);
2445 eina_list_free(modem_types);
2447 modem_selected = NULL;
2450 void ofono_modem_type_list(FILE *fp, const char *prefix, const char *suffix)
2453 for (itr = known_modem_types; *itr != NULL; itr++)
2454 fprintf(fp, "%s%s%s", prefix, *itr, suffix);
2457 void ofono_modem_path_wanted_set(const char *path)
2459 if (eina_stringshare_replace(&modem_path_wanted, path))
2460 modem_selected = NULL;
2463 unsigned int ofono_modem_api_get(void)
2465 OFono_Modem *m = _modem_selected_get();
2466 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
2467 return m->interfaces;
2470 Eina_Bool ofono_init(void)
2474 if (!elm_need_e_dbus()) {
2475 CRITICAL("Elementary does not support DBus.");
2479 bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
2481 CRITICAL("Could not get DBus System Bus");
2485 modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
2486 EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
2488 e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
2489 E_DBUS_FDO_INTERFACE,
2491 _name_owner_changed, NULL);
2493 e_dbus_get_name_owner(bus_conn, bus_name, _ofono_get_name_owner, NULL);
2498 void ofono_shutdown(void)
2500 if (pc_get_modems) {
2501 dbus_pending_call_cancel(pc_get_modems);
2502 pc_get_modems = NULL;
2505 _ofono_disconnected();
2506 eina_stringshare_replace(&modem_path_wanted, NULL);
2508 eina_hash_free(modems);
2511 eina_list_free(modem_types);
2514 static OFono_Pending *_ofono_call_volume_property_set(char *property,
2515 int type, void *value,
2520 OFono_Simple_Cb_Context *ctx = NULL;
2522 DBusMessageIter iter, variant;
2523 OFono_Modem *m = _modem_selected_get();
2524 char type_to_send[2] = { type , DBUS_TYPE_INVALID };
2526 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2529 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2530 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2535 msg = dbus_message_new_method_call(bus_id, m->base.path,
2536 OFONO_PREFIX OFONO_CALL_VOL_IFACE,
2539 goto error_no_dbus_message;
2541 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &property,
2543 goto error_message_args;
2545 dbus_message_iter_init_append(msg, &iter);
2547 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
2548 type_to_send, &variant))
2549 goto error_message_args;
2551 if (!dbus_message_iter_append_basic(&variant, type, value) ||
2552 !dbus_message_iter_close_container(&iter, &variant)) {
2553 dbus_message_iter_abandon_container(&iter, &variant);
2554 goto error_message_args;
2557 INF("%s.SetProperty(%s)", OFONO_CALL_VOL_IFACE, property);
2558 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2562 dbus_message_unref(msg);
2564 error_no_dbus_message:
2566 cb((void *)data, OFONO_ERROR_FAILED);
2571 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
2574 dbus_bool_t dbus_mute = !!mute;
2576 return _ofono_call_volume_property_set("Muted", DBUS_TYPE_BOOLEAN,
2577 &dbus_mute, cb, data);
2580 Eina_Bool ofono_mute_get(void)
2582 OFono_Modem *m = _modem_selected_get();
2583 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
2587 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
2592 return _ofono_call_volume_property_set("SpeakerVolume", DBUS_TYPE_BYTE,
2596 unsigned char ofono_volume_speaker_get(void)
2598 OFono_Modem *m = _modem_selected_get();
2599 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
2600 return m->speaker_volume;
2603 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
2607 return _ofono_call_volume_property_set("MicrophoneVolume",
2608 DBUS_TYPE_BYTE, &volume, cb,
2612 unsigned char ofono_volume_microphone_get(void)
2614 OFono_Modem *m = _modem_selected_get();
2615 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
2616 return m->microphone_volume;
2619 Eina_Bool ofono_voicemail_waiting_get(void)
2621 OFono_Modem *m = _modem_selected_get();
2622 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
2623 return m->voicemail_waiting;
2626 unsigned char ofono_voicemail_count_get(void)
2628 OFono_Modem *m = _modem_selected_get();
2629 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
2630 return m->voicemail_count;
2633 const char *ofono_voicemail_number_get(void)
2635 OFono_Modem *m = _modem_selected_get();
2636 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
2637 return m->voicemail_number;
2640 OFono_USSD_State ofono_ussd_state_get(void)
2642 OFono_Modem *m = _modem_selected_get();
2643 EINA_SAFETY_ON_NULL_RETURN_VAL(m, OFONO_USSD_STATE_IDLE);
2644 return m->ussd_state;
2647 OFono_Pending *ofono_tones_send(const char *tones,
2653 OFono_Simple_Cb_Context *ctx = NULL;
2654 OFono_Modem *m = _modem_selected_get();
2656 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2659 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2660 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2665 msg = dbus_message_new_method_call(
2666 bus_id, m->base.path,
2667 OFONO_PREFIX OFONO_VOICE_IFACE,
2670 goto error_no_dbus_message;
2672 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &tones,
2674 goto error_message_args;
2676 INF("SendTones(%s)", tones);
2677 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2681 dbus_message_unref(msg);
2683 error_no_dbus_message:
2685 cb((void *)data, OFONO_ERROR_FAILED);
2690 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
2693 return _ofono_multiparty("CreateMultiparty", cb, data);
2696 OFono_Pending *ofono_multiparty_hangup(OFono_Simple_Cb cb, const void *data)
2698 return _ofono_multiparty("HangupMultiparty", cb, data);
2701 OFono_Pending *ofono_private_chat(OFono_Call *c, OFono_Simple_Cb cb,
2706 OFono_Simple_Cb_Context *ctx = NULL;
2707 OFono_Modem *m = _modem_selected_get();
2709 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
2710 EINA_SAFETY_ON_NULL_GOTO(c, error_no_message);
2713 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2714 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
2719 msg = dbus_message_new_method_call(
2720 bus_id, m->base.path,
2721 OFONO_PREFIX OFONO_VOICE_IFACE,
2725 goto error_no_message;
2727 if (!dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH,
2728 &(c->base.path), DBUS_TYPE_INVALID))
2729 goto error_message_append;
2731 INF("PrivateChat(%s)", c->base.path);
2732 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2735 error_message_append:
2736 dbus_message_unref(msg);
2739 cb((void *)data, OFONO_ERROR_FAILED);
2744 static OFono_Callback_List_Modem_Node * _ofono_callback_modem_node_create(
2745 void (*cb)(void *data),const void *data)
2747 OFono_Callback_List_Modem_Node *node_new;
2749 node_new = calloc(1, sizeof(OFono_Callback_List_Modem_Node));
2750 EINA_SAFETY_ON_NULL_RETURN_VAL(node_new, NULL);
2752 node_new->cb_data = data;
2758 OFono_Callback_List_Modem_Node *
2759 ofono_modem_conected_cb_add(void (*cb)(void *data), const void *data)
2761 OFono_Callback_List_Modem_Node *node;
2763 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2764 node = _ofono_callback_modem_node_create(cb, data);
2765 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2767 cbs_modem_connected = eina_inlist_append(cbs_modem_connected,
2768 EINA_INLIST_GET(node));
2773 OFono_Callback_List_Modem_Node *
2774 ofono_modem_disconnected_cb_add(void (*cb)(void *data), const void *data)
2776 OFono_Callback_List_Modem_Node *node;
2778 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2779 node = _ofono_callback_modem_node_create(cb, data);
2780 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2782 cbs_modem_disconnected = eina_inlist_append(cbs_modem_disconnected,
2783 EINA_INLIST_GET(node));
2788 OFono_Callback_List_Modem_Node *
2789 ofono_modem_changed_cb_add(void (*cb)(void *data), const void *data)
2791 OFono_Callback_List_Modem_Node *node;
2793 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2794 node = _ofono_callback_modem_node_create(cb, data);
2795 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2797 cbs_modem_changed = eina_inlist_append(cbs_modem_changed,
2798 EINA_INLIST_GET(node));
2803 static void _ofono_callback_modem_list_delete(Eina_Inlist **list,
2804 OFono_Callback_List_Modem_Node *node)
2806 EINA_SAFETY_ON_NULL_RETURN(*list);
2807 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
2811 void ofono_modem_changed_cb_del(OFono_Callback_List_Modem_Node *node)
2813 EINA_SAFETY_ON_NULL_RETURN(node);
2814 _ofono_callback_modem_list_delete(&cbs_modem_changed, node);
2817 void ofono_modem_disconnected_cb_del(OFono_Callback_List_Modem_Node *node)
2819 EINA_SAFETY_ON_NULL_RETURN(node);
2820 _ofono_callback_modem_list_delete(&cbs_modem_disconnected, node);
2823 void ofono_modem_connected_cb_del(OFono_Callback_List_Modem_Node *node)
2825 EINA_SAFETY_ON_NULL_RETURN(node);
2826 _ofono_callback_modem_list_delete(&cbs_modem_connected, node);
2829 static OFono_Callback_List_Call_Node *_ofono_callback_call_node_create(
2830 void (*cb)(void *data, OFono_Call *call),const void *data)
2832 OFono_Callback_List_Call_Node *node;
2834 node = calloc(1, sizeof(OFono_Callback_List_Call_Node));
2835 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2837 node->cb_data = data;
2843 static OFono_Callback_List_Call_Disconnected_Node *
2844 _ofono_callback_call_disconnected_node_create(
2845 void (*cb)(void *data, OFono_Call *call, const char *reason),
2848 OFono_Callback_List_Call_Disconnected_Node *node;
2850 node = calloc(1, sizeof(OFono_Callback_List_Call_Disconnected_Node));
2851 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2853 node->cb_data = data;
2859 static OFono_Callback_List_USSD_Notify_Node *
2860 _ofono_callback_ussd_notify_node_create(
2861 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
2864 OFono_Callback_List_USSD_Notify_Node *node;
2866 node = calloc(1, sizeof(OFono_Callback_List_USSD_Notify_Node));
2867 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2869 node->cb_data = data;
2875 OFono_Callback_List_Call_Node *ofono_call_added_cb_add(
2876 void (*cb)(void *data,OFono_Call *call), const void *data)
2878 OFono_Callback_List_Call_Node *node;
2880 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2881 node = _ofono_callback_call_node_create(cb, data);
2882 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2884 cbs_call_added = eina_inlist_append(cbs_call_added,
2885 EINA_INLIST_GET(node));
2890 OFono_Callback_List_Call_Node *ofono_call_removed_cb_add(
2891 void (*cb)(void *data, OFono_Call *call), const void *data)
2893 OFono_Callback_List_Call_Node *node;
2895 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2896 node = _ofono_callback_call_node_create(cb, data);
2897 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2899 cbs_call_removed = eina_inlist_append(cbs_call_removed,
2900 EINA_INLIST_GET(node));
2905 OFono_Callback_List_Call_Node *ofono_call_changed_cb_add(
2906 void (*cb)(void *data, OFono_Call *call), const void *data)
2908 OFono_Callback_List_Call_Node *node;
2910 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2911 node = _ofono_callback_call_node_create(cb, data);
2912 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2914 cbs_call_changed = eina_inlist_append(cbs_call_changed,
2915 EINA_INLIST_GET(node));
2920 OFono_Callback_List_Call_Disconnected_Node *ofono_call_disconnected_cb_add(
2921 void (*cb)(void *data, OFono_Call *call, const char *reason),
2924 OFono_Callback_List_Call_Disconnected_Node *node;
2926 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2927 node = _ofono_callback_call_disconnected_node_create(cb, data);
2928 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2930 cbs_call_disconnected = eina_inlist_append(cbs_call_disconnected,
2931 EINA_INLIST_GET(node));
2936 OFono_Callback_List_USSD_Notify_Node *ofono_ussd_notify_cb_add(
2937 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
2940 OFono_Callback_List_USSD_Notify_Node *node;
2942 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
2943 node = _ofono_callback_ussd_notify_node_create(cb, data);
2944 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
2946 cbs_ussd_notify = eina_inlist_append(cbs_ussd_notify,
2947 EINA_INLIST_GET(node));
2952 static void _ofono_callback_call_list_delete(Eina_Inlist **list,
2953 OFono_Callback_List_Call_Node *node)
2955 EINA_SAFETY_ON_NULL_RETURN(*list);
2956 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
2960 void ofono_call_changed_cb_del(OFono_Callback_List_Call_Node *node)
2962 EINA_SAFETY_ON_NULL_RETURN(node);
2963 _ofono_callback_call_list_delete(&cbs_call_changed, node);
2966 void ofono_call_disconnected_cb_del(
2967 OFono_Callback_List_Call_Disconnected_Node *node)
2969 EINA_SAFETY_ON_NULL_RETURN(node);
2970 EINA_SAFETY_ON_NULL_RETURN(cbs_call_disconnected);
2971 cbs_call_disconnected = eina_inlist_remove(cbs_call_disconnected,
2972 EINA_INLIST_GET(node));
2976 void ofono_ussd_notify_cb_del(OFono_Callback_List_USSD_Notify_Node *node)
2978 EINA_SAFETY_ON_NULL_RETURN(node);
2979 EINA_SAFETY_ON_NULL_RETURN(cbs_ussd_notify);
2980 cbs_ussd_notify = eina_inlist_remove(cbs_ussd_notify,
2981 EINA_INLIST_GET(node));
2985 void ofono_call_added_cb_del(OFono_Callback_List_Call_Node *node)
2987 EINA_SAFETY_ON_NULL_RETURN(node);
2988 _ofono_callback_call_list_delete(&cbs_call_added, node);
2991 void ofono_call_removed_cb_del(OFono_Callback_List_Call_Node *node)
2993 EINA_SAFETY_ON_NULL_RETURN(node);
2994 _ofono_callback_call_list_delete(&cbs_call_removed, node);
2997 Eina_Bool ofono_voice_is_online(void)
2999 OFono_Modem *m = _modem_selected_get();
3001 /* The modem is expected to be NULL here, because maybe
3002 * OFono isn't up yet.
3007 if (m->interfaces & OFONO_API_VOICE)