4 #include <Elementary.h>
9 typedef struct _OFono_Modem OFono_Modem;
10 typedef struct _OFono_Bus_Object OFono_Bus_Object;
12 static const char bus_name[] = "org.ofono";
14 static E_DBus_Connection *bus_conn = NULL;
15 static char *bus_id = NULL;
16 static Eina_Hash *modems = NULL;
17 static OFono_Modem *modem_selected = NULL;
18 static const char *modem_path_wanted = NULL;
19 static unsigned int modem_api_mask = (OFONO_API_SIM |
24 static E_DBus_Signal_Handler *sig_modem_added = NULL;
25 static E_DBus_Signal_Handler *sig_modem_removed = NULL;
26 static E_DBus_Signal_Handler *sig_modem_prop_changed = NULL;
27 static DBusPendingCall *pc_get_modems = NULL;
29 static void (*connected_cb)(void *) = NULL;
30 static const void *connected_cb_data = NULL;
32 static void (*disconnected_cb)(void *) = NULL;
33 static const void *disconnected_cb_data = NULL;
35 static void (*changed_cb)(void *) = NULL;
36 static const void *changed_cb_data = NULL;
38 static void (*call_added_cb)(void *, OFono_Call *) = NULL;
39 static const void *call_added_cb_data = NULL;
41 static void (*call_removed_cb)(void *, OFono_Call *) = NULL;
42 static const void *call_removed_cb_data = NULL;
44 static void (*call_changed_cb)(void *, OFono_Call *) = NULL;
45 static const void *call_changed_cb_data = NULL;
47 static void (*call_disconnected_cb)(void *, OFono_Call *, const char *) = NULL;
48 static const void *call_disconnected_cb_data = NULL;
50 static void _ofono_call_volume_properties_get(OFono_Modem *m);
52 #define OFONO_SERVICE "org.ofono"
54 #define OFONO_PREFIX OFONO_SERVICE "."
55 #define OFONO_MODEM_IFACE "Modem"
56 #define OFONO_MANAGER_IFACE "Manager"
57 #define OFONO_SIM_IFACE "SimManager"
58 #define OFONO_NETREG_IFACE "NetworkRegistration"
59 #define OFONO_VOICE_IFACE "VoiceCallManager"
60 #define OFONO_MSG_IFACE "MessageManager"
61 #define OFONO_MSG_WAITING_IFACE "MessageWaiting"
62 #define OFONO_SMART_MSG_IFACE "SmartMessaging"
63 #define OFONO_STK_IFACE "SimToolkit"
65 #define OFONO_CALL_FW_IFACE "CallForwarding"
66 #define OFONO_CALL_VOL_IFACE "CallVolume"
67 #define OFONO_CALL_METER_IFACE "CallMeter"
68 #define OFONO_CALL_SET_IFACE "CallSettings"
69 #define OFONO_CALL_BAR_IFACE "CallBarring"
70 #define OFONO_SUPPL_SERV_IFACE "SupplementaryServices"
71 #define OFONO_TXT_TEL_IFACE "TextTelephony"
72 #define OFONO_CELL_BROAD_IFACE "CellBroadcast"
73 #define OFONO_CONNMAN_IFACE "ConnectionManager"
74 #define OFONO_PUSH_NOTIF_IFACE "PushNotification"
75 #define OFONO_PHONEBOOK_IFACE "Phonebook"
76 #define OFONO_ASN_IFACE "AssistedSatelliteNavigation"
78 static const struct API_Interface_Map {
83 #define MAP(bit, name) {bit, name, sizeof(name) - 1}
84 MAP(OFONO_API_SIM, OFONO_SIM_IFACE),
85 MAP(OFONO_API_NETREG, OFONO_NETREG_IFACE),
86 MAP(OFONO_API_VOICE, OFONO_VOICE_IFACE),
87 MAP(OFONO_API_MSG, OFONO_MSG_IFACE),
88 MAP(OFONO_API_MSG_WAITING, OFONO_MSG_WAITING_IFACE),
89 MAP(OFONO_API_SMART_MSG, OFONO_SMART_MSG_IFACE),
90 MAP(OFONO_API_STK, OFONO_STK_IFACE),
91 MAP(OFONO_API_CALL_FW, OFONO_CALL_FW_IFACE),
92 MAP(OFONO_API_CALL_VOL, OFONO_CALL_VOL_IFACE),
93 MAP(OFONO_API_CALL_METER, OFONO_CALL_METER_IFACE),
94 MAP(OFONO_API_CALL_SET, OFONO_CALL_SET_IFACE),
95 MAP(OFONO_API_CALL_BAR, OFONO_CALL_BAR_IFACE),
96 MAP(OFONO_API_SUPPL_SERV, OFONO_SUPPL_SERV_IFACE),
97 MAP(OFONO_API_TXT_TEL, OFONO_TXT_TEL_IFACE),
98 MAP(OFONO_API_CELL_BROAD, OFONO_CELL_BROAD_IFACE),
99 MAP(OFONO_API_CONNMAN, OFONO_CONNMAN_IFACE),
100 MAP(OFONO_API_PUSH_NOTIF, OFONO_PUSH_NOTIF_IFACE),
101 MAP(OFONO_API_PHONEBOOK, OFONO_PHONEBOOK_IFACE),
102 MAP(OFONO_API_ASN, OFONO_ASN_IFACE),
107 static Eina_Bool _dbus_bool_get(DBusMessageIter *itr)
110 dbus_message_iter_get_basic(itr, &val);
114 static const struct Error_Map {
119 #define MAP(id, name) {id, name, sizeof(name) - 1}
120 MAP(OFONO_ERROR_FAILED, "Failed"),
121 MAP(OFONO_ERROR_DOES_NOT_EXIST, "DoesNotExist"),
122 MAP(OFONO_ERROR_IN_PROGRESS, "InProgress"),
123 MAP(OFONO_ERROR_IN_USE, "InUse"),
124 MAP(OFONO_ERROR_INVALID_ARGS, "InvalidArguments"),
125 MAP(OFONO_ERROR_INVALID_FORMAT, "InvalidFormat"),
126 MAP(OFONO_ERROR_ACCESS_DENIED, "AccessDenied"),
127 MAP(OFONO_ERROR_ATTACH_IN_PROGRESS, "AttachInProgress"),
128 MAP(OFONO_ERROR_INCORRECT_PASSWORD, "IncorrectPassword"),
129 MAP(OFONO_ERROR_NOT_ACTIVE, "NotActive"),
130 MAP(OFONO_ERROR_NOT_ALLOWED, "NotAllowed"),
131 MAP(OFONO_ERROR_NOT_ATTACHED, "NotAttached"),
132 MAP(OFONO_ERROR_NOT_AVAILABLE, "NotAvailable"),
133 MAP(OFONO_ERROR_NOT_FOUND, "NotFound"),
134 MAP(OFONO_ERROR_NOT_IMPLEMENTED, "NotImplemented"),
135 MAP(OFONO_ERROR_NOT_RECOGNIZED, "NotRecognized"),
136 MAP(OFONO_ERROR_NOT_REGISTERED, "NotRegistered"),
137 MAP(OFONO_ERROR_NOT_SUPPORTED, "NotSupported"),
138 MAP(OFONO_ERROR_SIM_NOT_READY, "SimNotReady"),
139 MAP(OFONO_ERROR_STK, "SimToolkit"),
140 MAP(OFONO_ERROR_TIMEDOUT, "Timedout"),
145 static OFono_Error _ofono_error_parse(const char *name)
147 size_t namelen, prefixlen = sizeof(OFONO_PREFIX) - 1;
148 const struct Error_Map *itr;
150 /* whenever interfaces are not there due modem being offline */
151 if (strcmp(name, "org.freedesktop.DBus.Error.UnknownMethod") == 0)
152 return OFONO_ERROR_OFFLINE;
154 if (strncmp(name, OFONO_PREFIX, prefixlen) != 0)
155 return OFONO_ERROR_FAILED;
158 namelen = strlen(name);
159 for (itr = error_map; itr->name != NULL; itr++)
160 if ((itr->namelen == namelen) &&
161 (memcmp(name, itr->name, namelen) == 0))
164 return OFONO_ERROR_FAILED;
167 typedef struct _OFono_Simple_Cb_Context
171 } OFono_Simple_Cb_Context;
173 static void _ofono_simple_reply(void *data, DBusMessage *msg __UNUSED__,
176 OFono_Simple_Cb_Context *ctx = data;
177 OFono_Error e = OFONO_ERROR_NONE;
179 if (dbus_error_is_set(err)) {
180 DBG("%s: %s", err->name, err->message);
181 e = _ofono_error_parse(err->name);
185 ctx->cb((void *)ctx->data, e);
188 typedef struct _OFono_String_Cb_Context
193 char *(*convert)(DBusMessage *msg);
194 } OFono_String_Cb_Context;
196 static void _ofono_string_reply(void *data, DBusMessage *msg, DBusError *err)
198 OFono_String_Cb_Context *ctx = data;
199 OFono_Error e = OFONO_ERROR_NONE;
202 if (dbus_error_is_set(err)) {
203 DBG("%s: %s", err->name, err->message);
204 e = _ofono_error_parse(err->name);
206 str = ctx->convert(msg);
208 e = OFONO_ERROR_NOT_SUPPORTED;
212 ctx->cb((void *)ctx->data, e, str);
214 DBG("%s %s", ctx->name, str);
219 struct _OFono_Pending
222 DBusPendingCall *pending;
223 E_DBus_Method_Return_Cb cb;
228 struct _OFono_Bus_Object
231 Eina_Inlist *dbus_pending; /* of OFono_Pending */
232 Eina_List *dbus_signals; /* of E_DBus_Signal_Handler */
235 static void _bus_object_free(OFono_Bus_Object *o)
237 E_DBus_Signal_Handler *sh;
239 eina_stringshare_del(o->path);
241 while (o->dbus_pending) {
242 ofono_pending_cancel(
243 EINA_INLIST_CONTAINER_GET(o->dbus_pending,
247 EINA_LIST_FREE(o->dbus_signals, sh)
248 e_dbus_signal_handler_del(bus_conn, sh);
253 static void _bus_object_message_send_reply(void *data, DBusMessage *reply,
256 OFono_Pending *p = data;
257 OFono_Bus_Object *o = p->owner;
260 p->cb(p->data, reply, err);
262 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
267 static OFono_Pending *_bus_object_message_send(OFono_Bus_Object *o,
269 E_DBus_Method_Return_Cb cb,
273 EINA_SAFETY_ON_NULL_GOTO(o, error);
274 EINA_SAFETY_ON_NULL_GOTO(msg, error);
276 p = calloc(1, sizeof(OFono_Pending));
277 EINA_SAFETY_ON_NULL_GOTO(p, error);
283 p->pending = e_dbus_message_send(
284 bus_conn, msg, _bus_object_message_send_reply, -1, p);
285 EINA_SAFETY_ON_NULL_GOTO(p->pending, error_send);
287 o->dbus_pending = eina_inlist_append(o->dbus_pending,
289 dbus_message_unref(msg);
297 dbus_error_init(&err);
298 dbus_set_error(&err, "Failed", "call setup failed.");
299 cb(data, NULL, &err);
301 dbus_message_unref(msg);
305 void ofono_pending_cancel(OFono_Pending *p)
309 EINA_SAFETY_ON_NULL_RETURN(p);
312 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
318 dbus_error_init(&err);
319 dbus_set_error(&err, "Canceled",
320 "Pending method call was canceled.");
321 p->cb(p->data, NULL, &err);
323 dbus_pending_call_cancel(p->pending);
327 static void _bus_object_signal_listen(OFono_Bus_Object *o, const char *iface,
328 const char *name, E_DBus_Signal_Cb cb,
331 E_DBus_Signal_Handler *sh = e_dbus_signal_handler_add(
332 bus_conn, bus_id, o->path, iface, name, cb, data);
333 EINA_SAFETY_ON_NULL_RETURN(sh);
335 o->dbus_signals = eina_list_append(o->dbus_signals, sh);
340 OFono_Bus_Object base;
342 const char *incoming_line;
344 OFono_Call_State state;
345 Eina_Bool multiparty : 1;
346 Eina_Bool emergency : 1;
351 OFono_Bus_Object base;
355 unsigned int interfaces;
356 unsigned char strength;
357 unsigned char data_strength;
358 unsigned char speaker_volume;
359 unsigned char microphone_volume;
360 Eina_Bool ignored : 1;
361 Eina_Bool powered : 1;
362 Eina_Bool online : 1;
363 Eina_Bool roaming : 1;
367 static OFono_Call *_call_new(const char *path)
369 OFono_Call *c = calloc(1, sizeof(OFono_Call));
370 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
372 c->base.path = eina_stringshare_add(path);
373 EINA_SAFETY_ON_NULL_GOTO(c->base.path, error_path);
382 static void _call_free(OFono_Call *c)
384 DBG("c=%p %s", c, c->base.path);
387 call_removed_cb((void *)call_removed_cb_data, c);
389 eina_stringshare_del(c->line_id);
390 eina_stringshare_del(c->incoming_line);
391 eina_stringshare_del(c->name);
393 _bus_object_free(&c->base);
396 static OFono_Call_State _call_state_parse(const char *str)
398 if (strcmp(str, "active") == 0)
399 return OFONO_CALL_STATE_ACTIVE;
400 else if (strcmp(str, "held") == 0)
401 return OFONO_CALL_STATE_HELD;
402 else if (strcmp(str, "dialing") == 0)
403 return OFONO_CALL_STATE_DIALING;
404 else if (strcmp(str, "alerting") == 0)
405 return OFONO_CALL_STATE_ALERTING;
406 else if (strcmp(str, "incoming") == 0)
407 return OFONO_CALL_STATE_INCOMING;
408 else if (strcmp(str, "waiting") == 0)
409 return OFONO_CALL_STATE_WAITING;
410 else if (strcmp(str, "disconnected") == 0)
411 return OFONO_CALL_STATE_DISCONNECTED;
413 ERR("unknown call state: %s", str);
414 return OFONO_CALL_STATE_DISCONNECTED;
417 static void _call_property_update(OFono_Call *c, const char *key,
418 DBusMessageIter *value)
420 if (strcmp(key, "LineIdentification") == 0) {
422 dbus_message_iter_get_basic(value, &str);
423 DBG("%s LineIdentification %s", c->base.path, str);
424 eina_stringshare_replace(&c->line_id, str);
425 } else if (strcmp(key, "IncomingLine") == 0) {
427 dbus_message_iter_get_basic(value, &str);
428 DBG("%s IncomingLine %s", c->base.path, str);
429 eina_stringshare_replace(&c->incoming_line, str);
430 } else if (strcmp(key, "State") == 0) {
432 OFono_Call_State state;
433 dbus_message_iter_get_basic(value, &str);
434 state = _call_state_parse(str);
435 DBG("%s State %s (%d)", c->base.path, str, state);
437 } else if (strcmp(key, "Name") == 0) {
439 dbus_message_iter_get_basic(value, &str);
440 DBG("%s Name %s", c->base.path, str);
441 eina_stringshare_replace(&c->name, str);
442 } else if (strcmp(key, "Multiparty") == 0) {
444 dbus_message_iter_get_basic(value, &v);
445 DBG("%s Multiparty %d", c->base.path, v);
447 } else if (strcmp(key, "Emergency") == 0) {
449 dbus_message_iter_get_basic(value, &v);
450 DBG("%s Emergency %d", c->base.path, v);
453 DBG("%s %s (unused property)", c->base.path, key);
456 static void _call_property_changed(void *data, DBusMessage *msg)
458 OFono_Call *c = data;
459 DBusMessageIter iter, value;
462 if (!msg || !dbus_message_iter_init(msg, &iter)) {
463 ERR("Could not handle message %p", msg);
467 DBG("path=%s", c->base.path);
469 dbus_message_iter_get_basic(&iter, &key);
470 dbus_message_iter_next(&iter);
471 dbus_message_iter_recurse(&iter, &value);
472 _call_property_update(c, key, &value);
475 call_changed_cb((void *)call_changed_cb_data, c);
478 static void _call_disconnect_reason(void *data, DBusMessage *msg)
480 OFono_Call *c = data;
489 DBG("path=%s", c->base.path);
491 dbus_error_init(&err);
492 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &reason,
493 DBUS_TYPE_INVALID)) {
494 ERR("Could not get DisconnectReason arguments: %s: %s",
495 err.name, err.message);
496 dbus_error_free(&err);
500 if (call_disconnected_cb)
501 call_disconnected_cb((void *)call_disconnected_cb_data, c,
505 static void _call_add(OFono_Modem *m, const char *path, DBusMessageIter *prop)
509 DBG("path=%s", path);
511 c = eina_hash_find(m->calls, path);
513 DBG("Call already exists %p (%s)", c, path);
514 goto update_properties;
518 EINA_SAFETY_ON_NULL_RETURN(c);
519 eina_hash_add(m->calls, c->base.path, c);
521 _bus_object_signal_listen(&c->base,
522 OFONO_PREFIX "VoiceCall",
524 _call_disconnect_reason, c);
525 _bus_object_signal_listen(&c->base,
526 OFONO_PREFIX "VoiceCall",
528 _call_property_changed, c);
531 call_added_cb((void *)call_added_cb_data, c);
536 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
537 dbus_message_iter_next(prop)) {
538 DBusMessageIter entry, value;
541 dbus_message_iter_recurse(prop, &entry);
542 dbus_message_iter_get_basic(&entry, &key);
544 dbus_message_iter_next(&entry);
545 dbus_message_iter_recurse(&entry, &value);
547 _call_property_update(c, key, &value);
551 call_changed_cb((void *)call_changed_cb_data, c);
554 static void _call_remove(OFono_Modem *m, const char *path)
556 DBG("path=%s", path);
557 eina_hash_del_by_key(m->calls, path);
560 static void _call_added(void *data, DBusMessage *msg)
562 OFono_Modem *m = data;
563 DBusMessageIter iter, properties;
566 if (!msg || !dbus_message_iter_init(msg, &iter)) {
567 ERR("Could not handle message %p", msg);
571 dbus_message_iter_get_basic(&iter, &path);
573 dbus_message_iter_next(&iter);
574 dbus_message_iter_recurse(&iter, &properties);
576 _call_add(m, path, &properties);
579 static void _call_removed(void *data, DBusMessage *msg)
581 OFono_Modem *m = data;
586 ERR("Could not handle message %p", msg);
590 dbus_error_init(&err);
591 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
593 ERR("Could not get CallRemoved arguments: %s: %s",
594 err.name, err.message);
595 dbus_error_free(&err);
599 _call_remove(m, path);
602 static OFono_Modem *_modem_selected_get(void)
604 OFono_Modem *found_path = NULL, *found_api = NULL, *m;
605 unsigned int online = 0, powered = 0;
609 return modem_selected;
611 itr = eina_hash_iterator_data_new(modems);
612 EINA_ITERATOR_FOREACH(itr, m) {
621 if ((modem_path_wanted) && (!found_path)) {
622 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
623 if (m->base.path == modem_path_wanted) {
630 DBG("m=%#x, mask=%#x", m->interfaces, modem_api_mask);
631 if ((m->interfaces & modem_api_mask) == modem_api_mask)
635 eina_iterator_free(itr);
637 INF("found_path=%s, found_api=%s, wanted_path=%s, api_mask=%#x",
638 found_path ? found_path->base.path : "",
639 found_api ? found_api->base.path: "",
640 modem_path_wanted ? modem_path_wanted : "",
644 ERR("No modems powered! Run connman or test/enable-modem");
646 WRN("No modems online! Run connman or test/online-modem");
648 modem_selected = found_path ? found_path : found_api;
649 return modem_selected;
652 static OFono_Pending *_ofono_multiparty(const char *method,
653 E_DBus_Method_Return_Cb dbus_cb,
654 OFono_Simple_Cb cb, const void *data)
659 OFono_Simple_Cb_Context *ctx = NULL;
660 OFono_Modem *m = _modem_selected_get();
662 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
665 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
666 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
671 msg = dbus_message_new_method_call(
672 bus_id, m->base.path,
673 OFONO_PREFIX OFONO_VOICE_IFACE,
677 goto error_no_message;
679 if (!dbus_message_append_args(msg, DBUS_TYPE_INVALID))
680 goto error_message_append;
682 INF("Calling - %s - multiparty method.", method);
683 p = _bus_object_message_send(&m->base, msg, dbus_cb, ctx);
687 error_message_append:
688 dbus_message_unref(msg);
691 cb((void *)data, OFONO_ERROR_FAILED);
696 static OFono_Pending *_ofono_multiparty_hangup(OFono_Simple_Cb cb,
699 return _ofono_multiparty("HangupMultiparty",_ofono_simple_reply, cb,
703 OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb,
706 OFono_Simple_Cb_Context *ctx = NULL;
710 /* It looks like we are in a conference */
712 return _ofono_multiparty_hangup(cb, data);
714 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
717 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
718 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
723 msg = dbus_message_new_method_call(
724 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Hangup");
728 INF("Hangup(%s)", c->base.path);
729 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
734 cb((void *)data, OFONO_ERROR_FAILED);
739 OFono_Pending *ofono_call_answer(OFono_Call *c, OFono_Simple_Cb cb,
742 OFono_Simple_Cb_Context *ctx = NULL;
746 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
749 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
750 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
755 msg = dbus_message_new_method_call(
756 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Answer");
760 INF("Answer(%s)", c->base.path);
761 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
766 cb((void *)data, OFONO_ERROR_FAILED);
771 OFono_Call_State ofono_call_state_get(const OFono_Call *c)
773 EINA_SAFETY_ON_NULL_RETURN_VAL(c, OFONO_CALL_STATE_DISCONNECTED);
777 const char *ofono_call_name_get(const OFono_Call *c)
779 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
783 const char *ofono_call_line_id_get(const OFono_Call *c)
785 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
789 static void _ofono_calls_get_reply(void *data, DBusMessage *msg,
792 OFono_Modem *m = data;
793 DBusMessageIter array, dict;
797 ERR("%s: %s", err->name, err->message);
803 eina_hash_free_buckets(m->calls);
805 if (!dbus_message_iter_init(msg, &array)) {
806 ERR("Could not get calls");
810 dbus_message_iter_recurse(&array, &dict);
811 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
812 dbus_message_iter_next(&dict)) {
813 DBusMessageIter value, properties;
816 dbus_message_iter_recurse(&dict, &value);
817 dbus_message_iter_get_basic(&value, &path);
819 dbus_message_iter_next(&value);
820 dbus_message_iter_recurse(&value, &properties);
822 _call_add(m, path, &properties);
826 static void _modem_calls_load(OFono_Modem *m)
828 DBusMessage *msg = dbus_message_new_method_call(
829 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE,
832 DBG("Get calls of %s", m->base.path);
833 _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m);
836 static OFono_Modem *_modem_new(const char *path)
838 OFono_Modem *m = calloc(1, sizeof(OFono_Modem));
839 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
841 m->base.path = eina_stringshare_add(path);
842 EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
844 m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free));
845 EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls);
850 eina_stringshare_del(m->base.path);
856 static void _modem_free(OFono_Modem *m)
858 DBG("m=%p %s", m, m->base.path);
860 if (modem_selected == m)
861 modem_selected = NULL;
863 eina_stringshare_del(m->name);
864 eina_stringshare_del(m->serial);
866 eina_hash_free(m->calls);
868 _bus_object_free(&m->base);
872 static void _call_volume_property_update(OFono_Modem *m, const char *prop_name,
873 DBusMessageIter *iter)
876 if (strcmp(prop_name, "Muted") == 0) {
877 m->muted = _dbus_bool_get(iter);
878 DBG("%s Muted %d", m->base.path, m->muted);
879 } else if (strcmp(prop_name, "SpeakerVolume") == 0) {
880 dbus_message_iter_get_basic(iter, &m->speaker_volume);
881 DBG("%s Speaker Volume %hhu", m->base.path, m->speaker_volume);
882 } else if (strcmp(prop_name, "MicrophoneVolume") == 0) {
883 dbus_message_iter_get_basic(iter, &m->microphone_volume);
884 DBG("%s Microphone Volume %hhu", m->base.path, m->speaker_volume);
888 static void _call_volume_property_changed(void *data, DBusMessage *msg)
890 OFono_Modem *m = data;
891 DBusMessageIter iter, variant_iter;
892 const char *prop_name;
894 if (!msg || !dbus_message_iter_init(msg, &iter)) {
895 ERR("Could not handle message %p", msg);
899 dbus_message_iter_get_basic(&iter, &prop_name);
900 dbus_message_iter_next(&iter);
901 dbus_message_iter_recurse(&iter, &variant_iter);
902 _call_volume_property_update(m, prop_name, &variant_iter);
905 changed_cb((void *)changed_cb_data);
908 static unsigned int _modem_interfaces_extract(DBusMessageIter *array)
910 DBusMessageIter entry;
911 unsigned int interfaces = 0;
913 dbus_message_iter_recurse(array, &entry);
914 for (; dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING;
915 dbus_message_iter_next(&entry)) {
916 const struct API_Interface_Map *itr;
920 dbus_message_iter_get_basic(&entry, &name);
922 if (strncmp(name, OFONO_PREFIX, strlen(OFONO_PREFIX)) != 0)
925 name += strlen(OFONO_PREFIX);
926 namelen = strlen(name);
928 DBG("interface: %s", name);
929 for (itr = api_iface_map; itr->name != NULL; itr++) {
930 if ((itr->namelen == namelen) &&
931 (memcmp(itr->name, name, namelen) == 0)) {
932 interfaces |= itr->bit;
936 if (itr->name == NULL)
937 WRN("ignored %s", name);
943 static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces)
946 if (((m->interfaces & OFONO_API_CALL_VOL) == 0) &&
947 (ifaces & OFONO_API_CALL_VOL) == OFONO_API_CALL_VOL)
948 _ofono_call_volume_properties_get(m);
951 static void _modem_property_update(OFono_Modem *m, const char *key,
952 DBusMessageIter *value)
954 if (strcmp(key, "Powered") == 0) {
955 m->powered = _dbus_bool_get(value);
956 DBG("%s Powered %d", m->base.path, m->powered);
957 } else if (strcmp(key, "Online") == 0) {
958 m->online = _dbus_bool_get(value);
959 DBG("%s Online %d", m->base.path, m->online);
960 } else if (strcmp(key, "Interfaces") == 0) {
961 unsigned int ifaces = _modem_interfaces_extract(value);
962 DBG("%s Interfaces 0x%02x", m->base.path, ifaces);
963 if (m->interfaces != ifaces) {
964 _modem_update_interfaces(m, ifaces);
965 m->interfaces = ifaces;
967 if (modem_selected && modem_path_wanted &&
968 modem_selected->base.path != modem_path_wanted)
969 modem_selected = NULL;
971 } else if (strcmp(key, "Serial") == 0) {
973 dbus_message_iter_get_basic(value, &serial);
974 DBG("%s Serial %s", m->base.path, serial);
975 eina_stringshare_replace(&m->serial, serial);
976 } else if (strcmp(key, "Type") == 0) {
978 dbus_message_iter_get_basic(value, &type);
979 DBG("%s Type %s", m->base.path, type);
980 m->ignored = strcmp(type, "hardware") != 0;
982 DBG("%s %s (unused property)", m->base.path, key);
985 changed_cb((void *)changed_cb_data);
988 static void _ofono_call_volume_properties_get_reply(void *data,
992 OFono_Modem *m = data;
993 DBusMessageIter iter, prop;
995 if (dbus_error_is_set(err)) {
996 DBG("%s: %s", err->name, err->message);
1000 dbus_message_iter_init(msg, &iter);
1001 dbus_message_iter_recurse(&iter, &prop);
1003 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1004 dbus_message_iter_next(&prop)) {
1005 DBusMessageIter entry, value;
1008 dbus_message_iter_recurse(&prop, &entry);
1009 dbus_message_iter_get_basic(&entry, &key);
1011 dbus_message_iter_next(&entry);
1012 dbus_message_iter_recurse(&entry, &value);
1013 _call_volume_property_update(m, key, &value);
1017 static void _ofono_call_volume_properties_get(OFono_Modem *m)
1020 msg = dbus_message_new_method_call(bus_id, m->base.path,
1022 OFONO_CALL_VOL_IFACE,
1027 _bus_object_message_send(&m->base, msg,
1028 _ofono_call_volume_properties_get_reply, m);
1031 static void _modem_add(const char *path, DBusMessageIter *prop)
1035 DBG("path=%s", path);
1037 m = eina_hash_find(modems, path);
1039 DBG("Modem already exists %p (%s)", m, path);
1040 goto update_properties;
1043 m = _modem_new(path);
1044 EINA_SAFETY_ON_NULL_RETURN(m);
1045 eina_hash_add(modems, m->base.path, m);
1047 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1048 "CallAdded", _call_added, m);
1049 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1050 "CallRemoved", _call_removed, m);
1051 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1053 _call_volume_property_changed, m);
1055 /* TODO: do we need to listen to BarringActive or Forwarded? */
1057 if (modem_selected && modem_path_wanted &&
1058 modem_selected->base.path != modem_path_wanted)
1059 modem_selected = NULL;
1064 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
1065 dbus_message_iter_next(prop)) {
1066 DBusMessageIter entry, value;
1069 dbus_message_iter_recurse(prop, &entry);
1070 dbus_message_iter_get_basic(&entry, &key);
1072 dbus_message_iter_next(&entry);
1073 dbus_message_iter_recurse(&entry, &value);
1075 _modem_property_update(m, key, &value);
1078 if (m->interfaces & OFONO_API_VOICE)
1079 _modem_calls_load(m);
1082 static void _modem_remove(const char *path)
1084 DBG("path=%s", path);
1085 eina_hash_del_by_key(modems, path);
1088 static void _ofono_modems_get_reply(void *data __UNUSED__, DBusMessage *msg,
1091 DBusMessageIter array, dict;
1093 pc_get_modems = NULL;
1097 ERR("%s: %s", err->name, err->message);
1103 EINA_SAFETY_ON_NULL_RETURN(modems);
1104 eina_hash_free_buckets(modems);
1106 if (!dbus_message_iter_init(msg, &array)) {
1107 ERR("Could not get modems");
1111 dbus_message_iter_recurse(&array, &dict);
1112 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
1113 dbus_message_iter_next(&dict)) {
1114 DBusMessageIter value, properties;
1117 dbus_message_iter_recurse(&dict, &value);
1118 dbus_message_iter_get_basic(&value, &path);
1120 dbus_message_iter_next(&value);
1121 dbus_message_iter_recurse(&value, &properties);
1123 _modem_add(path, &properties);
1127 static void _modem_added(void *data __UNUSED__, DBusMessage *msg)
1129 DBusMessageIter iter, properties;
1132 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1133 ERR("Could not handle message %p", msg);
1137 dbus_message_iter_get_basic(&iter, &path);
1139 dbus_message_iter_next(&iter);
1140 dbus_message_iter_recurse(&iter, &properties);
1142 _modem_add(path, &properties);
1145 static void _modem_removed(void *data __UNUSED__, DBusMessage *msg)
1151 ERR("Could not handle message %p", msg);
1155 dbus_error_init(&err);
1156 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
1158 ERR("Could not get ModemRemoved arguments: %s: %s",
1159 err.name, err.message);
1160 dbus_error_free(&err);
1164 _modem_remove(path);
1167 static void _modem_property_changed(void *data __UNUSED__, DBusMessage *msg)
1171 DBusMessageIter iter, value;
1174 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1175 ERR("Could not handle message %p", msg);
1179 path = dbus_message_get_path(msg);
1180 DBG("path=%s", path);
1182 m = eina_hash_find(modems, path);
1184 DBG("Modem is unknown (%s)", path);
1188 dbus_message_iter_get_basic(&iter, &key);
1189 dbus_message_iter_next(&iter);
1190 dbus_message_iter_recurse(&iter, &value);
1191 _modem_property_update(m, key, &value);
1194 static void _modems_load(void)
1196 DBusMessage *msg = dbus_message_new_method_call(
1197 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
1200 dbus_pending_call_cancel(pc_get_modems);
1203 pc_get_modems = e_dbus_message_send(
1204 bus_conn, msg, _ofono_modems_get_reply, -1, NULL);
1205 dbus_message_unref(msg);
1208 static void _ofono_connected(const char *id)
1211 bus_id = strdup(id);
1213 sig_modem_added = e_dbus_signal_handler_add(
1214 bus_conn, bus_id, "/",
1215 OFONO_PREFIX OFONO_MANAGER_IFACE,
1217 _modem_added, NULL);
1219 sig_modem_removed = e_dbus_signal_handler_add(
1220 bus_conn, bus_id, "/",
1221 OFONO_PREFIX OFONO_MANAGER_IFACE,
1223 _modem_removed, NULL);
1225 sig_modem_prop_changed = e_dbus_signal_handler_add(
1226 bus_conn, bus_id, NULL,
1227 OFONO_PREFIX OFONO_MODEM_IFACE,
1229 _modem_property_changed, NULL);
1234 connected_cb((void *)connected_cb_data);
1237 static void _ofono_disconnected(void)
1239 eina_hash_free_buckets(modems);
1241 if (sig_modem_added) {
1242 e_dbus_signal_handler_del(bus_conn, sig_modem_added);
1243 sig_modem_added = NULL;
1246 if (sig_modem_removed) {
1247 e_dbus_signal_handler_del(bus_conn, sig_modem_removed);
1248 sig_modem_removed = NULL;
1251 if (sig_modem_prop_changed) {
1252 e_dbus_signal_handler_del(bus_conn, sig_modem_prop_changed);
1253 sig_modem_prop_changed = NULL;
1257 if (disconnected_cb)
1258 disconnected_cb((void *)disconnected_cb_data);
1265 static void _name_owner_changed(void *data __UNUSED__, DBusMessage *msg)
1268 const char *name, *from, *to;
1270 dbus_error_init(&err);
1271 if (!dbus_message_get_args(msg, &err,
1272 DBUS_TYPE_STRING, &name,
1273 DBUS_TYPE_STRING, &from,
1274 DBUS_TYPE_STRING, &to,
1275 DBUS_TYPE_INVALID)) {
1276 ERR("Could not get NameOwnerChanged arguments: %s: %s",
1277 err.name, err.message);
1278 dbus_error_free(&err);
1282 if (strcmp(name, bus_name) != 0)
1285 DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
1287 if (from[0] == '\0' && to[0] != '\0') {
1288 INF("oFono appeared as %s", to);
1289 _ofono_connected(to);
1290 } else if (from[0] != '\0' && to[0] == '\0') {
1291 INF("oFono disappeared from %s", from);
1292 _ofono_disconnected();
1296 static void _ofono_get_name_owner(void *data __UNUSED__, DBusMessage *msg, DBusError *err)
1298 DBusMessageIter itr;
1303 ERR("%s: %s", err->name, err->message);
1309 dbus_message_iter_init(msg, &itr);
1310 dbus_message_iter_get_basic(&itr, &id);
1311 if (!id || id[0] == '\0') {
1312 ERR("No name owner fo %s!", bus_name);
1316 INF("oFono bus id: %s", id);
1317 _ofono_connected(id);
1320 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
1321 const char *new, OFono_Simple_Cb cb,
1324 OFono_Simple_Cb_Context *ctx = NULL;
1325 OFono_Error err = OFONO_ERROR_OFFLINE;
1328 OFono_Modem *m = _modem_selected_get();
1329 EINA_SAFETY_ON_NULL_GOTO(m, error);
1330 EINA_SAFETY_ON_NULL_GOTO(what, error);
1331 EINA_SAFETY_ON_NULL_GOTO(old, error);
1332 EINA_SAFETY_ON_NULL_GOTO(new, error);
1334 if ((m->interfaces & OFONO_API_SIM) == 0)
1336 err = OFONO_ERROR_FAILED;
1339 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1340 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1345 msg = dbus_message_new_method_call(
1346 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
1351 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1352 DBUS_TYPE_STRING, &old,
1353 DBUS_TYPE_STRING, &new,
1357 INF("ChangePin(%s, %s, %s)", what, old, new);
1358 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1362 dbus_message_unref(msg);
1365 cb((void *)data, err);
1370 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
1371 const char *new, OFono_Simple_Cb cb,
1374 OFono_Simple_Cb_Context *ctx = NULL;
1375 OFono_Error err = OFONO_ERROR_OFFLINE;
1378 OFono_Modem *m = _modem_selected_get();
1379 EINA_SAFETY_ON_NULL_GOTO(m, error);
1380 EINA_SAFETY_ON_NULL_GOTO(what, error);
1381 EINA_SAFETY_ON_NULL_GOTO(puk, error);
1382 EINA_SAFETY_ON_NULL_GOTO(new, error);
1384 if ((m->interfaces & OFONO_API_SIM) == 0)
1386 err = OFONO_ERROR_FAILED;
1389 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1390 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1395 msg = dbus_message_new_method_call(
1396 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
1400 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1401 DBUS_TYPE_STRING, &puk,
1402 DBUS_TYPE_STRING, &new,
1406 INF("ResetPin(%s, %s, %s)", what, puk, new);
1407 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1411 dbus_message_unref(msg);
1414 cb((void *)data, err);
1419 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
1420 DBusMessageIter *itr)
1422 const char *ussd_response;
1424 if (dbus_message_iter_get_arg_type(itr) != DBUS_TYPE_STRING) {
1425 ERR("Invalid type: %c (expected: %c)",
1426 dbus_message_iter_get_arg_type(itr), DBUS_TYPE_STRING);
1429 dbus_message_iter_get_basic(itr, &ussd_response);
1430 EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
1431 return strdup(ussd_response);
1434 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
1435 DBusMessageIter *dict)
1437 for (; dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY;
1438 dbus_message_iter_next(dict)) {
1439 DBusMessageIter e, v;
1440 const char *key, *value;
1442 dbus_message_iter_recurse(dict, &e);
1443 dbus_message_iter_get_basic(&e, &key);
1445 dbus_message_iter_next(&e);
1446 dbus_message_iter_recurse(&e, &v);
1447 dbus_message_iter_get_basic(&v, &value);
1449 eina_strbuf_append_printf(buf, " %s=%s<br>",
1454 static char *_ss_initiate_convert_call1(const char *type, DBusMessageIter *itr)
1456 DBusMessageIter array, dict;
1457 const char *ss_op, *service;
1461 dbus_message_iter_recurse(itr, &array);
1463 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1464 ERR("Invalid type: %c (expected: %c)",
1465 dbus_message_iter_get_arg_type(&array),
1469 dbus_message_iter_get_basic(&array, &ss_op);
1470 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1472 if (!dbus_message_iter_next(&array)) {
1473 ERR("Missing %s service", type);
1477 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1478 ERR("Invalid type: %c (expected: %c)",
1479 dbus_message_iter_get_arg_type(&array),
1483 dbus_message_iter_get_basic(&array, &service);
1484 EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
1486 if (!dbus_message_iter_next(&array)) {
1487 ERR("Missing %s information", type);
1491 buf = eina_strbuf_new();
1492 eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
1493 type, ss_op, service);
1495 dbus_message_iter_recurse(&array, &dict);
1496 _ss_initiate_cb_dict_convert(buf, &dict);
1498 str = eina_strbuf_string_steal(buf);
1499 eina_strbuf_free(buf);
1503 static char *_ss_initiate_convert_call_waiting(const char *type,
1504 DBusMessageIter *itr)
1506 DBusMessageIter array, dict;
1511 dbus_message_iter_recurse(itr, &array);
1513 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1514 ERR("Invalid type: %c (expected: %c)",
1515 dbus_message_iter_get_arg_type(&array),
1519 dbus_message_iter_get_basic(&array, &ss_op);
1520 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1522 if (!dbus_message_iter_next(&array)) {
1523 ERR("Missing %s information", type);
1527 buf = eina_strbuf_new();
1528 eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
1531 dbus_message_iter_recurse(&array, &dict);
1532 _ss_initiate_cb_dict_convert(buf, &dict);
1534 str = eina_strbuf_string_steal(buf);
1535 eina_strbuf_free(buf);
1539 static char *_ss_initiate_convert_call2(const char *type,
1540 DBusMessageIter *itr)
1542 DBusMessageIter array;
1543 const char *ss_op, *status;
1547 dbus_message_iter_recurse(itr, &array);
1549 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1550 ERR("Invalid type: %c (expected: %c)",
1551 dbus_message_iter_get_arg_type(&array),
1555 dbus_message_iter_get_basic(&array, &ss_op);
1556 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1558 if (!dbus_message_iter_next(&array)) {
1559 ERR("Missing %s status", type);
1563 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1564 ERR("Invalid type: %c (expected: %c)",
1565 dbus_message_iter_get_arg_type(&array),
1569 dbus_message_iter_get_basic(&array, &status);
1570 EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
1572 buf = eina_strbuf_new();
1573 eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
1574 type, ss_op, status);
1576 str = eina_strbuf_string_steal(buf);
1577 eina_strbuf_free(buf);
1581 static const struct SS_Initiate_Convert_Map {
1584 char *(*convert)(const char *type, DBusMessageIter *itr);
1585 } ss_initiate_convert_map[] = {
1586 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
1587 MAP("USSD", _ss_initiate_convert_ussd),
1588 MAP("CallBarring", _ss_initiate_convert_call1),
1589 MAP("CallForwarding", _ss_initiate_convert_call1),
1590 MAP("CallWaiting", _ss_initiate_convert_call_waiting),
1591 MAP("CallingLinePresentation", _ss_initiate_convert_call2),
1592 MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
1593 MAP("CallingLineRestriction", _ss_initiate_convert_call2),
1594 MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
1599 static char *_ss_initiate_convert(DBusMessage *msg)
1601 DBusMessageIter array, variant;
1602 const struct SS_Initiate_Convert_Map *citr;
1603 const char *type = NULL;
1606 if (!dbus_message_iter_init(msg, &array))
1609 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1610 ERR("Invalid type for first argument: %c (expected: %c)",
1611 dbus_message_iter_get_arg_type(&array),
1615 dbus_message_iter_get_basic(&array, &type);
1617 ERR("Couldn't get SupplementaryServices.Initiate type");
1620 DBG("type: %s", type);
1622 if (!dbus_message_iter_next(&array)) {
1623 ERR("Couldn't get SupplementaryServices.Initiate payload");
1626 dbus_message_iter_recurse(&array, &variant);
1628 typelen = strlen(type);
1629 for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
1630 if ((citr->typelen == typelen) &&
1631 (memcmp(citr->type, type, typelen) == 0)) {
1632 return citr->convert(type, &variant);
1635 ERR("Could not convert SupplementaryServices.Initiate type %s", type);
1641 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
1643 OFono_String_Cb_Context *ctx = NULL;
1644 OFono_Error err = OFONO_ERROR_OFFLINE;
1647 OFono_Modem *m = _modem_selected_get();
1648 EINA_SAFETY_ON_NULL_GOTO(m, error);
1649 EINA_SAFETY_ON_NULL_GOTO(command, error);
1651 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
1653 err = OFONO_ERROR_FAILED;
1655 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
1656 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1659 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
1660 ctx->convert = _ss_initiate_convert;
1662 msg = dbus_message_new_method_call(
1663 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1668 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &command,
1672 INF("SupplementaryServices.Initiate(%s)", command);
1673 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
1677 dbus_message_unref(msg);
1680 cb((void *)data, err, NULL);
1685 typedef struct _OFono_Call_Cb_Context
1691 } OFono_Call_Cb_Context;
1693 static void _ofono_dial_reply(void *data, DBusMessage *msg, DBusError *err)
1695 OFono_Call_Cb_Context *ctx = data;
1696 OFono_Call *c = NULL;
1697 OFono_Error oe = OFONO_ERROR_NONE;
1700 DBG("%s: %s", err->name, err->message);
1701 oe = _ofono_error_parse(err->name);
1705 dbus_error_init(&e);
1706 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
1707 &path, DBUS_TYPE_INVALID)) {
1708 ERR("Could not get Dial reply: %s: %s",
1710 dbus_error_free(&e);
1711 oe = OFONO_ERROR_FAILED;
1713 c = eina_hash_find(ctx->modem->calls, path);
1715 _call_add(ctx->modem, path, NULL);
1716 c = eina_hash_find(ctx->modem->calls, path);
1719 ERR("Could not find call %s", path);
1720 oe = OFONO_ERROR_FAILED;
1726 ctx->cb((void *)ctx->data, oe, c);
1729 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
1730 OFono_Call_Cb cb, const void *data)
1732 OFono_Call_Cb_Context *ctx = NULL;
1733 OFono_Error err = OFONO_ERROR_OFFLINE;
1736 OFono_Modem *m = _modem_selected_get();
1737 EINA_SAFETY_ON_NULL_GOTO(m, error);
1740 if ((m->interfaces & OFONO_API_VOICE) == 0)
1742 err = OFONO_ERROR_FAILED;
1747 ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
1748 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1751 ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
1754 msg = dbus_message_new_method_call(
1755 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
1759 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
1760 DBUS_TYPE_STRING, &hide_callerid,
1764 INF("Dial(%s, %s)", number, hide_callerid);
1765 p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
1769 dbus_message_unref(msg);
1772 cb((void *)data, err, NULL);
1777 const char *ofono_modem_serial_get(void)
1779 OFono_Modem *m = _modem_selected_get();
1780 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
1784 void ofono_modem_api_require(unsigned int api_mask)
1786 if (modem_api_mask == api_mask)
1788 modem_api_mask = api_mask;
1789 modem_selected = NULL;
1792 void ofono_modem_path_wanted_set(const char *path)
1794 if (eina_stringshare_replace(&modem_path_wanted, path))
1795 modem_selected = NULL;
1798 void ofono_connected_cb_set(void (*cb)(void *data), const void *data)
1801 connected_cb_data = data;
1804 void ofono_disconnected_cb_set(void (*cb)(void *data), const void *data)
1806 disconnected_cb = cb;
1807 disconnected_cb_data = data;
1810 void ofono_changed_cb_set(void (*cb)(void *data), const void *data)
1813 changed_cb_data = data;
1816 void ofono_call_added_cb_set(void (*cb)(void *data, OFono_Call *call),
1820 call_added_cb_data = data;
1823 void ofono_call_removed_cb_set(void (*cb)(void *data, OFono_Call *call),
1826 call_removed_cb = cb;
1827 call_removed_cb_data = data;
1830 void ofono_call_changed_cb_set(void (*cb)(void *data, OFono_Call *call),
1833 call_changed_cb = cb;
1834 call_changed_cb_data = data;
1837 void ofono_call_disconnected_cb_set(void (*cb)(void *data, OFono_Call *call, const char *reason),
1840 call_disconnected_cb = cb;
1841 call_disconnected_cb_data = data;
1844 Eina_Bool ofono_init(void)
1846 if (!elm_need_e_dbus()) {
1847 CRITICAL("Elementary does not support DBus.");
1851 bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
1853 CRITICAL("Could not get DBus System Bus");
1857 modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
1858 EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
1860 e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
1861 E_DBUS_FDO_INTERFACE,
1863 _name_owner_changed, NULL);
1865 e_dbus_get_name_owner(bus_conn, bus_name, _ofono_get_name_owner, NULL);
1870 void ofono_shutdown(void)
1872 if (pc_get_modems) {
1873 dbus_pending_call_cancel(pc_get_modems);
1874 pc_get_modems = NULL;
1877 _ofono_disconnected();
1878 eina_stringshare_replace(&modem_path_wanted, NULL);
1880 eina_hash_free(modems);
1884 static OFono_Pending *_ofono_call_volume_property_set(char *property,
1885 int type, void *value,
1890 OFono_Simple_Cb_Context *ctx = NULL;
1892 DBusMessageIter iter, variant;
1893 OFono_Modem *m = _modem_selected_get();
1894 char type_to_send[2] = { type , DBUS_TYPE_INVALID };
1896 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
1899 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1900 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
1905 msg = dbus_message_new_method_call(bus_id, m->base.path,
1906 OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1909 goto error_no_dbus_message;
1911 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &property,
1913 goto error_message_args;
1915 dbus_message_iter_init_append(msg, &iter);
1917 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1918 type_to_send, &variant))
1919 goto error_message_args;
1921 if (!dbus_message_iter_append_basic(&variant, type, value) ||
1922 !dbus_message_iter_close_container(&iter, &variant)) {
1923 dbus_message_iter_abandon_container(&iter, &variant);
1924 goto error_message_args;
1927 INF("Call-Volume - Property:%s called.", property);
1928 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1932 dbus_message_unref(msg);
1934 error_no_dbus_message:
1936 cb((void *)data, OFONO_ERROR_FAILED);
1941 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
1944 dbus_bool_t dbus_mute = !!mute;
1946 return _ofono_call_volume_property_set("Muted", DBUS_TYPE_BOOLEAN,
1947 &dbus_mute, cb, data);
1950 Eina_Bool ofono_mute_get(void)
1952 OFono_Modem *m = _modem_selected_get();
1953 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
1957 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
1962 return _ofono_call_volume_property_set("SpeakerVolume", DBUS_TYPE_BYTE,
1966 unsigned char ofono_volume_speaker_get(void)
1968 OFono_Modem *m = _modem_selected_get();
1969 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
1970 return m->speaker_volume;
1973 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
1977 return _ofono_call_volume_property_set("MicrophoneVolume",
1978 DBUS_TYPE_BYTE, &volume, cb,
1982 unsigned char ofono_volume_microphone_get(void)
1984 OFono_Modem *m = _modem_selected_get();
1985 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
1986 return m->microphone_volume;
1989 OFono_Pending *ofono_tones_send(const char *tones,
1995 OFono_Simple_Cb_Context *ctx = NULL;
1996 OFono_Modem *m = _modem_selected_get();
1998 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2001 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2002 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2007 msg = dbus_message_new_method_call(
2008 bus_id, m->base.path,
2009 OFONO_PREFIX OFONO_VOICE_IFACE,
2012 goto error_no_dbus_message;
2014 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &tones,
2016 goto error_message_args;
2018 INF("Voice-Call-Manager - SendTones:%s called.", tones);
2019 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2023 dbus_message_unref(msg);
2025 error_no_dbus_message:
2027 cb((void *)data, OFONO_ERROR_FAILED);
2032 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
2035 return _ofono_multiparty("CreateMultiparty",
2036 _ofono_simple_reply, cb, data);