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 E_DBus_Connection *bus_conn = NULL;
17 static char *bus_id = NULL;
18 static Eina_Hash *modems = NULL;
19 static OFono_Modem *modem_selected = NULL;
20 static const char *modem_path_wanted = NULL;
21 static unsigned int modem_api_mask = (OFONO_API_SIM |
26 static E_DBus_Signal_Handler *sig_modem_added = NULL;
27 static E_DBus_Signal_Handler *sig_modem_removed = NULL;
28 static E_DBus_Signal_Handler *sig_modem_prop_changed = NULL;
29 static DBusPendingCall *pc_get_modems = NULL;
31 static void (*connected_cb)(void *) = NULL;
32 static const void *connected_cb_data = NULL;
34 static void (*disconnected_cb)(void *) = NULL;
35 static const void *disconnected_cb_data = NULL;
37 static void (*changed_cb)(void *) = NULL;
38 static const void *changed_cb_data = NULL;
40 static void (*call_added_cb)(void *, OFono_Call *) = NULL;
41 static const void *call_added_cb_data = NULL;
43 static void (*call_removed_cb)(void *, OFono_Call *) = NULL;
44 static const void *call_removed_cb_data = NULL;
46 static void (*call_changed_cb)(void *, OFono_Call *) = NULL;
47 static const void *call_changed_cb_data = NULL;
49 static void (*call_disconnected_cb)(void *, OFono_Call *, const char *) = NULL;
50 static const void *call_disconnected_cb_data = NULL;
52 static void _ofono_call_volume_properties_get(OFono_Modem *m);
54 #define OFONO_SERVICE "org.ofono"
56 #define OFONO_PREFIX OFONO_SERVICE "."
57 #define OFONO_MODEM_IFACE "Modem"
58 #define OFONO_MANAGER_IFACE "Manager"
59 #define OFONO_SIM_IFACE "SimManager"
60 #define OFONO_NETREG_IFACE "NetworkRegistration"
61 #define OFONO_VOICE_IFACE "VoiceCallManager"
62 #define OFONO_MSG_IFACE "MessageManager"
63 #define OFONO_MSG_WAITING_IFACE "MessageWaiting"
64 #define OFONO_SMART_MSG_IFACE "SmartMessaging"
65 #define OFONO_STK_IFACE "SimToolkit"
67 #define OFONO_CALL_FW_IFACE "CallForwarding"
68 #define OFONO_CALL_VOL_IFACE "CallVolume"
69 #define OFONO_CALL_METER_IFACE "CallMeter"
70 #define OFONO_CALL_SET_IFACE "CallSettings"
71 #define OFONO_CALL_BAR_IFACE "CallBarring"
72 #define OFONO_SUPPL_SERV_IFACE "SupplementaryServices"
73 #define OFONO_TXT_TEL_IFACE "TextTelephony"
74 #define OFONO_CELL_BROAD_IFACE "CellBroadcast"
75 #define OFONO_CONNMAN_IFACE "ConnectionManager"
76 #define OFONO_PUSH_NOTIF_IFACE "PushNotification"
77 #define OFONO_PHONEBOOK_IFACE "Phonebook"
78 #define OFONO_ASN_IFACE "AssistedSatelliteNavigation"
80 static const struct API_Interface_Map {
85 #define MAP(bit, name) {bit, name, sizeof(name) - 1}
86 MAP(OFONO_API_SIM, OFONO_SIM_IFACE),
87 MAP(OFONO_API_NETREG, OFONO_NETREG_IFACE),
88 MAP(OFONO_API_VOICE, OFONO_VOICE_IFACE),
89 MAP(OFONO_API_MSG, OFONO_MSG_IFACE),
90 MAP(OFONO_API_MSG_WAITING, OFONO_MSG_WAITING_IFACE),
91 MAP(OFONO_API_SMART_MSG, OFONO_SMART_MSG_IFACE),
92 MAP(OFONO_API_STK, OFONO_STK_IFACE),
93 MAP(OFONO_API_CALL_FW, OFONO_CALL_FW_IFACE),
94 MAP(OFONO_API_CALL_VOL, OFONO_CALL_VOL_IFACE),
95 MAP(OFONO_API_CALL_METER, OFONO_CALL_METER_IFACE),
96 MAP(OFONO_API_CALL_SET, OFONO_CALL_SET_IFACE),
97 MAP(OFONO_API_CALL_BAR, OFONO_CALL_BAR_IFACE),
98 MAP(OFONO_API_SUPPL_SERV, OFONO_SUPPL_SERV_IFACE),
99 MAP(OFONO_API_TXT_TEL, OFONO_TXT_TEL_IFACE),
100 MAP(OFONO_API_CELL_BROAD, OFONO_CELL_BROAD_IFACE),
101 MAP(OFONO_API_CONNMAN, OFONO_CONNMAN_IFACE),
102 MAP(OFONO_API_PUSH_NOTIF, OFONO_PUSH_NOTIF_IFACE),
103 MAP(OFONO_API_PHONEBOOK, OFONO_PHONEBOOK_IFACE),
104 MAP(OFONO_API_ASN, OFONO_ASN_IFACE),
109 static Eina_Bool _dbus_bool_get(DBusMessageIter *itr)
112 dbus_message_iter_get_basic(itr, &val);
116 static const struct Error_Map {
121 #define MAP(id, name) {id, name, sizeof(name) - 1}
122 MAP(OFONO_ERROR_FAILED, "Failed"),
123 MAP(OFONO_ERROR_DOES_NOT_EXIST, "DoesNotExist"),
124 MAP(OFONO_ERROR_IN_PROGRESS, "InProgress"),
125 MAP(OFONO_ERROR_IN_USE, "InUse"),
126 MAP(OFONO_ERROR_INVALID_ARGS, "InvalidArguments"),
127 MAP(OFONO_ERROR_INVALID_FORMAT, "InvalidFormat"),
128 MAP(OFONO_ERROR_ACCESS_DENIED, "AccessDenied"),
129 MAP(OFONO_ERROR_ATTACH_IN_PROGRESS, "AttachInProgress"),
130 MAP(OFONO_ERROR_INCORRECT_PASSWORD, "IncorrectPassword"),
131 MAP(OFONO_ERROR_NOT_ACTIVE, "NotActive"),
132 MAP(OFONO_ERROR_NOT_ALLOWED, "NotAllowed"),
133 MAP(OFONO_ERROR_NOT_ATTACHED, "NotAttached"),
134 MAP(OFONO_ERROR_NOT_AVAILABLE, "NotAvailable"),
135 MAP(OFONO_ERROR_NOT_FOUND, "NotFound"),
136 MAP(OFONO_ERROR_NOT_IMPLEMENTED, "NotImplemented"),
137 MAP(OFONO_ERROR_NOT_RECOGNIZED, "NotRecognized"),
138 MAP(OFONO_ERROR_NOT_REGISTERED, "NotRegistered"),
139 MAP(OFONO_ERROR_NOT_SUPPORTED, "NotSupported"),
140 MAP(OFONO_ERROR_SIM_NOT_READY, "SimNotReady"),
141 MAP(OFONO_ERROR_STK, "SimToolkit"),
142 MAP(OFONO_ERROR_TIMEDOUT, "Timedout"),
147 static OFono_Error _ofono_error_parse(const char *name)
149 size_t namelen, prefixlen = sizeof(OFONO_PREFIX) - 1;
150 const struct Error_Map *itr;
152 /* whenever interfaces are not there due modem being offline */
153 if (strcmp(name, "org.freedesktop.DBus.Error.UnknownMethod") == 0)
154 return OFONO_ERROR_OFFLINE;
156 if (strncmp(name, OFONO_PREFIX, prefixlen) != 0)
157 return OFONO_ERROR_FAILED;
160 namelen = strlen(name);
161 for (itr = error_map; itr->name != NULL; itr++)
162 if ((itr->namelen == namelen) &&
163 (memcmp(name, itr->name, namelen) == 0))
166 return OFONO_ERROR_FAILED;
169 typedef struct _OFono_Simple_Cb_Context
173 } OFono_Simple_Cb_Context;
175 static void _ofono_simple_reply(void *data, DBusMessage *msg __UNUSED__,
178 OFono_Simple_Cb_Context *ctx = data;
179 OFono_Error e = OFONO_ERROR_NONE;
181 if (dbus_error_is_set(err)) {
182 DBG("%s: %s", err->name, err->message);
183 e = _ofono_error_parse(err->name);
187 ctx->cb((void *)ctx->data, e);
190 typedef struct _OFono_String_Cb_Context
195 char *(*convert)(DBusMessage *msg);
196 } OFono_String_Cb_Context;
198 static void _ofono_string_reply(void *data, DBusMessage *msg, DBusError *err)
200 OFono_String_Cb_Context *ctx = data;
201 OFono_Error e = OFONO_ERROR_NONE;
204 if (dbus_error_is_set(err)) {
205 DBG("%s: %s", err->name, err->message);
206 e = _ofono_error_parse(err->name);
208 str = ctx->convert(msg);
210 e = OFONO_ERROR_NOT_SUPPORTED;
214 ctx->cb((void *)ctx->data, e, str);
216 DBG("%s %s", ctx->name, str);
221 struct _OFono_Pending
224 DBusPendingCall *pending;
225 E_DBus_Method_Return_Cb cb;
230 struct _OFono_Bus_Object
233 Eina_Inlist *dbus_pending; /* of OFono_Pending */
234 Eina_List *dbus_signals; /* of E_DBus_Signal_Handler */
237 static void _bus_object_free(OFono_Bus_Object *o)
239 E_DBus_Signal_Handler *sh;
241 eina_stringshare_del(o->path);
243 while (o->dbus_pending) {
244 ofono_pending_cancel(
245 EINA_INLIST_CONTAINER_GET(o->dbus_pending,
249 EINA_LIST_FREE(o->dbus_signals, sh)
250 e_dbus_signal_handler_del(bus_conn, sh);
255 static void _bus_object_message_send_reply(void *data, DBusMessage *reply,
258 OFono_Pending *p = data;
259 OFono_Bus_Object *o = p->owner;
262 p->cb(p->data, reply, err);
264 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
269 static OFono_Pending *_bus_object_message_send(OFono_Bus_Object *o,
271 E_DBus_Method_Return_Cb cb,
275 EINA_SAFETY_ON_NULL_GOTO(o, error);
276 EINA_SAFETY_ON_NULL_GOTO(msg, error);
278 p = calloc(1, sizeof(OFono_Pending));
279 EINA_SAFETY_ON_NULL_GOTO(p, error);
285 p->pending = e_dbus_message_send(
286 bus_conn, msg, _bus_object_message_send_reply, -1, p);
287 EINA_SAFETY_ON_NULL_GOTO(p->pending, error_send);
289 o->dbus_pending = eina_inlist_append(o->dbus_pending,
291 dbus_message_unref(msg);
299 dbus_error_init(&err);
300 dbus_set_error(&err, "Failed", "call setup failed.");
301 cb(data, NULL, &err);
303 dbus_message_unref(msg);
307 void ofono_pending_cancel(OFono_Pending *p)
311 EINA_SAFETY_ON_NULL_RETURN(p);
314 o->dbus_pending = eina_inlist_remove(o->dbus_pending,
320 dbus_error_init(&err);
321 dbus_set_error(&err, "Canceled",
322 "Pending method call was canceled.");
323 p->cb(p->data, NULL, &err);
325 dbus_pending_call_cancel(p->pending);
329 static void _bus_object_signal_listen(OFono_Bus_Object *o, const char *iface,
330 const char *name, E_DBus_Signal_Cb cb,
333 E_DBus_Signal_Handler *sh = e_dbus_signal_handler_add(
334 bus_conn, bus_id, o->path, iface, name, cb, data);
335 EINA_SAFETY_ON_NULL_RETURN(sh);
337 o->dbus_signals = eina_list_append(o->dbus_signals, sh);
342 OFono_Bus_Object base;
344 const char *incoming_line;
347 OFono_Call_State state;
348 Eina_Bool multiparty : 1;
349 Eina_Bool emergency : 1;
354 OFono_Bus_Object base;
358 unsigned int interfaces;
359 unsigned char strength;
360 unsigned char data_strength;
361 unsigned char speaker_volume;
362 unsigned char microphone_volume;
363 Eina_Bool ignored : 1;
364 Eina_Bool powered : 1;
365 Eina_Bool online : 1;
366 Eina_Bool roaming : 1;
370 static OFono_Call *_call_new(const char *path)
372 OFono_Call *c = calloc(1, sizeof(OFono_Call));
373 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
375 c->base.path = eina_stringshare_add(path);
376 EINA_SAFETY_ON_NULL_GOTO(c->base.path, error_path);
378 c->start_time = -1.0;
387 static void _call_free(OFono_Call *c)
389 DBG("c=%p %s", c, c->base.path);
392 call_removed_cb((void *)call_removed_cb_data, c);
394 eina_stringshare_del(c->line_id);
395 eina_stringshare_del(c->incoming_line);
396 eina_stringshare_del(c->name);
398 _bus_object_free(&c->base);
401 static OFono_Call_State _call_state_parse(const char *str)
403 if (strcmp(str, "active") == 0)
404 return OFONO_CALL_STATE_ACTIVE;
405 else if (strcmp(str, "held") == 0)
406 return OFONO_CALL_STATE_HELD;
407 else if (strcmp(str, "dialing") == 0)
408 return OFONO_CALL_STATE_DIALING;
409 else if (strcmp(str, "alerting") == 0)
410 return OFONO_CALL_STATE_ALERTING;
411 else if (strcmp(str, "incoming") == 0)
412 return OFONO_CALL_STATE_INCOMING;
413 else if (strcmp(str, "waiting") == 0)
414 return OFONO_CALL_STATE_WAITING;
415 else if (strcmp(str, "disconnected") == 0)
416 return OFONO_CALL_STATE_DISCONNECTED;
418 ERR("unknown call state: %s", str);
419 return OFONO_CALL_STATE_DISCONNECTED;
422 static void _call_property_update(OFono_Call *c, const char *key,
423 DBusMessageIter *value)
425 if (strcmp(key, "LineIdentification") == 0) {
427 dbus_message_iter_get_basic(value, &str);
428 DBG("%s LineIdentification %s", c->base.path, str);
429 eina_stringshare_replace(&c->line_id, str);
430 } else if (strcmp(key, "IncomingLine") == 0) {
432 dbus_message_iter_get_basic(value, &str);
433 DBG("%s IncomingLine %s", c->base.path, str);
434 eina_stringshare_replace(&c->incoming_line, str);
435 } else if (strcmp(key, "State") == 0) {
437 OFono_Call_State state;
438 dbus_message_iter_get_basic(value, &str);
439 state = _call_state_parse(str);
440 DBG("%s State %s (%d)", c->base.path, str, state);
442 if ((state == OFONO_CALL_STATE_ACTIVE) && (c->start_time < 0.0))
443 c->start_time = ecore_loop_time_get();
444 } else if (strcmp(key, "Name") == 0) {
446 dbus_message_iter_get_basic(value, &str);
447 DBG("%s Name %s", c->base.path, str);
448 eina_stringshare_replace(&c->name, str);
449 } else if (strcmp(key, "Multiparty") == 0) {
451 dbus_message_iter_get_basic(value, &v);
452 DBG("%s Multiparty %d", c->base.path, v);
454 } else if (strcmp(key, "Emergency") == 0) {
456 dbus_message_iter_get_basic(value, &v);
457 DBG("%s Emergency %d", c->base.path, v);
459 } else if (strcmp(key, "StartTime") == 0) {
460 const char *end, *ts = NULL;
462 dbus_message_iter_get_basic(value, &ts);
463 memset(&tm, 0, sizeof(tm));
464 end = strptime(ts, "%Y-%m-%dT%H:%M:%S%z", &tm);
465 if ((end) && (*end != '\0'))
466 ERR("Failed to parse StartTime=%s", ts);
468 time_t st = mktime(&tm);
469 time_t ut = time(NULL);
470 double lt = ecore_loop_time_get();
471 c->start_time = st - ut + lt;
472 DBG("%s StartTime %f (%s)", c->base.path, c->start_time,
476 DBG("%s %s (unused property)", c->base.path, key);
479 static void _call_property_changed(void *data, DBusMessage *msg)
481 OFono_Call *c = data;
482 DBusMessageIter iter, value;
485 if (!msg || !dbus_message_iter_init(msg, &iter)) {
486 ERR("Could not handle message %p", msg);
490 DBG("path=%s", c->base.path);
492 dbus_message_iter_get_basic(&iter, &key);
493 dbus_message_iter_next(&iter);
494 dbus_message_iter_recurse(&iter, &value);
495 _call_property_update(c, key, &value);
498 call_changed_cb((void *)call_changed_cb_data, c);
501 static void _call_disconnect_reason(void *data, DBusMessage *msg)
503 OFono_Call *c = data;
512 DBG("path=%s", c->base.path);
514 dbus_error_init(&err);
515 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &reason,
516 DBUS_TYPE_INVALID)) {
517 ERR("Could not get DisconnectReason arguments: %s: %s",
518 err.name, err.message);
519 dbus_error_free(&err);
523 if (call_disconnected_cb)
524 call_disconnected_cb((void *)call_disconnected_cb_data, c,
528 static void _call_add(OFono_Modem *m, const char *path, DBusMessageIter *prop)
532 DBG("path=%s", path);
534 c = eina_hash_find(m->calls, path);
536 DBG("Call already exists %p (%s)", c, path);
537 goto update_properties;
541 EINA_SAFETY_ON_NULL_RETURN(c);
542 eina_hash_add(m->calls, c->base.path, c);
544 _bus_object_signal_listen(&c->base,
545 OFONO_PREFIX "VoiceCall",
547 _call_disconnect_reason, c);
548 _bus_object_signal_listen(&c->base,
549 OFONO_PREFIX "VoiceCall",
551 _call_property_changed, c);
554 call_added_cb((void *)call_added_cb_data, c);
559 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
560 dbus_message_iter_next(prop)) {
561 DBusMessageIter entry, value;
564 dbus_message_iter_recurse(prop, &entry);
565 dbus_message_iter_get_basic(&entry, &key);
567 dbus_message_iter_next(&entry);
568 dbus_message_iter_recurse(&entry, &value);
570 _call_property_update(c, key, &value);
574 call_changed_cb((void *)call_changed_cb_data, c);
577 static void _call_remove(OFono_Modem *m, const char *path)
579 DBG("path=%s", path);
580 eina_hash_del_by_key(m->calls, path);
583 static void _call_added(void *data, DBusMessage *msg)
585 OFono_Modem *m = data;
586 DBusMessageIter iter, properties;
589 if (!msg || !dbus_message_iter_init(msg, &iter)) {
590 ERR("Could not handle message %p", msg);
594 dbus_message_iter_get_basic(&iter, &path);
596 dbus_message_iter_next(&iter);
597 dbus_message_iter_recurse(&iter, &properties);
599 _call_add(m, path, &properties);
602 static void _call_removed(void *data, DBusMessage *msg)
604 OFono_Modem *m = data;
609 ERR("Could not handle message %p", msg);
613 dbus_error_init(&err);
614 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
616 ERR("Could not get CallRemoved arguments: %s: %s",
617 err.name, err.message);
618 dbus_error_free(&err);
622 _call_remove(m, path);
625 static OFono_Modem *_modem_selected_get(void)
627 OFono_Modem *found_path = NULL, *found_api = NULL, *m;
628 unsigned int online = 0, powered = 0;
632 return modem_selected;
634 itr = eina_hash_iterator_data_new(modems);
635 EINA_ITERATOR_FOREACH(itr, m) {
644 if ((modem_path_wanted) && (!found_path)) {
645 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
646 if (m->base.path == modem_path_wanted) {
653 DBG("m=%#x, mask=%#x", m->interfaces, modem_api_mask);
654 if ((m->interfaces & modem_api_mask) == modem_api_mask)
658 eina_iterator_free(itr);
660 INF("found_path=%s, found_api=%s, wanted_path=%s, api_mask=%#x",
661 found_path ? found_path->base.path : "",
662 found_api ? found_api->base.path: "",
663 modem_path_wanted ? modem_path_wanted : "",
667 ERR("No modems powered! Run connman or test/enable-modem");
669 WRN("No modems online! Run connman or test/online-modem");
671 modem_selected = found_path ? found_path : found_api;
672 return modem_selected;
675 static OFono_Pending *_ofono_multiparty(const char *method,
676 E_DBus_Method_Return_Cb dbus_cb,
677 OFono_Simple_Cb cb, const void *data)
682 OFono_Simple_Cb_Context *ctx = NULL;
683 OFono_Modem *m = _modem_selected_get();
685 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
688 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
689 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
694 msg = dbus_message_new_method_call(
695 bus_id, m->base.path,
696 OFONO_PREFIX OFONO_VOICE_IFACE,
700 goto error_no_message;
702 if (!dbus_message_append_args(msg, DBUS_TYPE_INVALID))
703 goto error_message_append;
705 INF("Calling - %s - multiparty method.", method);
706 p = _bus_object_message_send(&m->base, msg, dbus_cb, ctx);
710 error_message_append:
711 dbus_message_unref(msg);
714 cb((void *)data, OFONO_ERROR_FAILED);
719 static OFono_Pending *_ofono_multiparty_hangup(OFono_Simple_Cb cb,
722 return _ofono_multiparty("HangupMultiparty",_ofono_simple_reply, cb,
726 OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb,
729 OFono_Simple_Cb_Context *ctx = NULL;
733 /* It looks like we are in a conference */
735 return _ofono_multiparty_hangup(cb, data);
737 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
740 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
741 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
746 msg = dbus_message_new_method_call(
747 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Hangup");
751 INF("Hangup(%s)", c->base.path);
752 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
757 cb((void *)data, OFONO_ERROR_FAILED);
762 OFono_Pending *ofono_call_answer(OFono_Call *c, OFono_Simple_Cb cb,
765 OFono_Simple_Cb_Context *ctx = NULL;
769 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
772 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
773 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
778 msg = dbus_message_new_method_call(
779 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Answer");
783 INF("Answer(%s)", c->base.path);
784 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
789 cb((void *)data, OFONO_ERROR_FAILED);
794 OFono_Call_State ofono_call_state_get(const OFono_Call *c)
796 EINA_SAFETY_ON_NULL_RETURN_VAL(c, OFONO_CALL_STATE_DISCONNECTED);
800 const char *ofono_call_name_get(const OFono_Call *c)
802 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
806 const char *ofono_call_line_id_get(const OFono_Call *c)
808 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
812 double ofono_call_start_time_get(const OFono_Call *c)
814 EINA_SAFETY_ON_NULL_RETURN_VAL(c, -1.0);
815 return c->start_time;
818 static void _ofono_calls_get_reply(void *data, DBusMessage *msg,
821 OFono_Modem *m = data;
822 DBusMessageIter array, dict;
826 ERR("%s: %s", err->name, err->message);
832 eina_hash_free_buckets(m->calls);
834 if (!dbus_message_iter_init(msg, &array)) {
835 ERR("Could not get calls");
839 dbus_message_iter_recurse(&array, &dict);
840 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
841 dbus_message_iter_next(&dict)) {
842 DBusMessageIter value, properties;
845 dbus_message_iter_recurse(&dict, &value);
846 dbus_message_iter_get_basic(&value, &path);
848 dbus_message_iter_next(&value);
849 dbus_message_iter_recurse(&value, &properties);
851 _call_add(m, path, &properties);
855 static void _modem_calls_load(OFono_Modem *m)
857 DBusMessage *msg = dbus_message_new_method_call(
858 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE,
861 DBG("Get calls of %s", m->base.path);
862 _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m);
865 static OFono_Modem *_modem_new(const char *path)
867 OFono_Modem *m = calloc(1, sizeof(OFono_Modem));
868 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
870 m->base.path = eina_stringshare_add(path);
871 EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
873 m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free));
874 EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls);
879 eina_stringshare_del(m->base.path);
885 static void _modem_free(OFono_Modem *m)
887 DBG("m=%p %s", m, m->base.path);
889 if (modem_selected == m)
890 modem_selected = NULL;
892 eina_stringshare_del(m->name);
893 eina_stringshare_del(m->serial);
895 eina_hash_free(m->calls);
897 _bus_object_free(&m->base);
901 static void _call_volume_property_update(OFono_Modem *m, const char *prop_name,
902 DBusMessageIter *iter)
905 if (strcmp(prop_name, "Muted") == 0) {
906 m->muted = _dbus_bool_get(iter);
907 DBG("%s Muted %d", m->base.path, m->muted);
908 } else if (strcmp(prop_name, "SpeakerVolume") == 0) {
909 dbus_message_iter_get_basic(iter, &m->speaker_volume);
910 DBG("%s Speaker Volume %hhu", m->base.path, m->speaker_volume);
911 } else if (strcmp(prop_name, "MicrophoneVolume") == 0) {
912 dbus_message_iter_get_basic(iter, &m->microphone_volume);
913 DBG("%s Microphone Volume %hhu", m->base.path, m->speaker_volume);
917 static void _call_volume_property_changed(void *data, DBusMessage *msg)
919 OFono_Modem *m = data;
920 DBusMessageIter iter, variant_iter;
921 const char *prop_name;
923 if (!msg || !dbus_message_iter_init(msg, &iter)) {
924 ERR("Could not handle message %p", msg);
928 dbus_message_iter_get_basic(&iter, &prop_name);
929 dbus_message_iter_next(&iter);
930 dbus_message_iter_recurse(&iter, &variant_iter);
931 _call_volume_property_update(m, prop_name, &variant_iter);
934 changed_cb((void *)changed_cb_data);
937 static unsigned int _modem_interfaces_extract(DBusMessageIter *array)
939 DBusMessageIter entry;
940 unsigned int interfaces = 0;
942 dbus_message_iter_recurse(array, &entry);
943 for (; dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING;
944 dbus_message_iter_next(&entry)) {
945 const struct API_Interface_Map *itr;
949 dbus_message_iter_get_basic(&entry, &name);
951 if (strncmp(name, OFONO_PREFIX, strlen(OFONO_PREFIX)) != 0)
954 name += strlen(OFONO_PREFIX);
955 namelen = strlen(name);
957 DBG("interface: %s", name);
958 for (itr = api_iface_map; itr->name != NULL; itr++) {
959 if ((itr->namelen == namelen) &&
960 (memcmp(itr->name, name, namelen) == 0)) {
961 interfaces |= itr->bit;
965 if (itr->name == NULL)
966 WRN("ignored %s", name);
972 static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces)
975 if (((m->interfaces & OFONO_API_CALL_VOL) == 0) &&
976 (ifaces & OFONO_API_CALL_VOL) == OFONO_API_CALL_VOL)
977 _ofono_call_volume_properties_get(m);
980 static void _modem_property_update(OFono_Modem *m, const char *key,
981 DBusMessageIter *value)
983 if (strcmp(key, "Powered") == 0) {
984 m->powered = _dbus_bool_get(value);
985 DBG("%s Powered %d", m->base.path, m->powered);
986 } else if (strcmp(key, "Online") == 0) {
987 m->online = _dbus_bool_get(value);
988 DBG("%s Online %d", m->base.path, m->online);
989 } else if (strcmp(key, "Interfaces") == 0) {
990 unsigned int ifaces = _modem_interfaces_extract(value);
991 DBG("%s Interfaces 0x%02x", m->base.path, ifaces);
992 if (m->interfaces != ifaces) {
993 _modem_update_interfaces(m, ifaces);
994 m->interfaces = ifaces;
996 if (modem_selected && modem_path_wanted &&
997 modem_selected->base.path != modem_path_wanted)
998 modem_selected = NULL;
1000 } else if (strcmp(key, "Serial") == 0) {
1002 dbus_message_iter_get_basic(value, &serial);
1003 DBG("%s Serial %s", m->base.path, serial);
1004 eina_stringshare_replace(&m->serial, serial);
1005 } else if (strcmp(key, "Type") == 0) {
1007 dbus_message_iter_get_basic(value, &type);
1008 DBG("%s Type %s", m->base.path, type);
1009 m->ignored = strcmp(type, "hardware") != 0;
1011 DBG("%s %s (unused property)", m->base.path, key);
1014 changed_cb((void *)changed_cb_data);
1017 static void _ofono_call_volume_properties_get_reply(void *data,
1021 OFono_Modem *m = data;
1022 DBusMessageIter iter, prop;
1024 if (dbus_error_is_set(err)) {
1025 DBG("%s: %s", err->name, err->message);
1029 dbus_message_iter_init(msg, &iter);
1030 dbus_message_iter_recurse(&iter, &prop);
1032 for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY;
1033 dbus_message_iter_next(&prop)) {
1034 DBusMessageIter entry, value;
1037 dbus_message_iter_recurse(&prop, &entry);
1038 dbus_message_iter_get_basic(&entry, &key);
1040 dbus_message_iter_next(&entry);
1041 dbus_message_iter_recurse(&entry, &value);
1042 _call_volume_property_update(m, key, &value);
1046 static void _ofono_call_volume_properties_get(OFono_Modem *m)
1049 msg = dbus_message_new_method_call(bus_id, m->base.path,
1051 OFONO_CALL_VOL_IFACE,
1056 _bus_object_message_send(&m->base, msg,
1057 _ofono_call_volume_properties_get_reply, m);
1060 static void _modem_add(const char *path, DBusMessageIter *prop)
1064 DBG("path=%s", path);
1066 m = eina_hash_find(modems, path);
1068 DBG("Modem already exists %p (%s)", m, path);
1069 goto update_properties;
1072 m = _modem_new(path);
1073 EINA_SAFETY_ON_NULL_RETURN(m);
1074 eina_hash_add(modems, m->base.path, m);
1076 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1077 "CallAdded", _call_added, m);
1078 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1079 "CallRemoved", _call_removed, m);
1080 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1082 _call_volume_property_changed, m);
1084 /* TODO: do we need to listen to BarringActive or Forwarded? */
1086 if (modem_selected && modem_path_wanted &&
1087 modem_selected->base.path != modem_path_wanted)
1088 modem_selected = NULL;
1093 for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY;
1094 dbus_message_iter_next(prop)) {
1095 DBusMessageIter entry, value;
1098 dbus_message_iter_recurse(prop, &entry);
1099 dbus_message_iter_get_basic(&entry, &key);
1101 dbus_message_iter_next(&entry);
1102 dbus_message_iter_recurse(&entry, &value);
1104 _modem_property_update(m, key, &value);
1107 if (m->interfaces & OFONO_API_VOICE)
1108 _modem_calls_load(m);
1111 static void _modem_remove(const char *path)
1113 DBG("path=%s", path);
1114 eina_hash_del_by_key(modems, path);
1117 static void _ofono_modems_get_reply(void *data __UNUSED__, DBusMessage *msg,
1120 DBusMessageIter array, dict;
1122 pc_get_modems = NULL;
1126 ERR("%s: %s", err->name, err->message);
1132 EINA_SAFETY_ON_NULL_RETURN(modems);
1133 eina_hash_free_buckets(modems);
1135 if (!dbus_message_iter_init(msg, &array)) {
1136 ERR("Could not get modems");
1140 dbus_message_iter_recurse(&array, &dict);
1141 for (; dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT;
1142 dbus_message_iter_next(&dict)) {
1143 DBusMessageIter value, properties;
1146 dbus_message_iter_recurse(&dict, &value);
1147 dbus_message_iter_get_basic(&value, &path);
1149 dbus_message_iter_next(&value);
1150 dbus_message_iter_recurse(&value, &properties);
1152 _modem_add(path, &properties);
1156 static void _modem_added(void *data __UNUSED__, DBusMessage *msg)
1158 DBusMessageIter iter, properties;
1161 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1162 ERR("Could not handle message %p", msg);
1166 dbus_message_iter_get_basic(&iter, &path);
1168 dbus_message_iter_next(&iter);
1169 dbus_message_iter_recurse(&iter, &properties);
1171 _modem_add(path, &properties);
1174 static void _modem_removed(void *data __UNUSED__, DBusMessage *msg)
1180 ERR("Could not handle message %p", msg);
1184 dbus_error_init(&err);
1185 if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH,
1187 ERR("Could not get ModemRemoved arguments: %s: %s",
1188 err.name, err.message);
1189 dbus_error_free(&err);
1193 _modem_remove(path);
1196 static void _modem_property_changed(void *data __UNUSED__, DBusMessage *msg)
1200 DBusMessageIter iter, value;
1203 if (!msg || !dbus_message_iter_init(msg, &iter)) {
1204 ERR("Could not handle message %p", msg);
1208 path = dbus_message_get_path(msg);
1209 DBG("path=%s", path);
1211 m = eina_hash_find(modems, path);
1213 DBG("Modem is unknown (%s)", path);
1217 dbus_message_iter_get_basic(&iter, &key);
1218 dbus_message_iter_next(&iter);
1219 dbus_message_iter_recurse(&iter, &value);
1220 _modem_property_update(m, key, &value);
1223 static void _modems_load(void)
1225 DBusMessage *msg = dbus_message_new_method_call(
1226 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
1229 dbus_pending_call_cancel(pc_get_modems);
1232 pc_get_modems = e_dbus_message_send(
1233 bus_conn, msg, _ofono_modems_get_reply, -1, NULL);
1234 dbus_message_unref(msg);
1237 static void _ofono_connected(const char *id)
1240 bus_id = strdup(id);
1242 sig_modem_added = e_dbus_signal_handler_add(
1243 bus_conn, bus_id, "/",
1244 OFONO_PREFIX OFONO_MANAGER_IFACE,
1246 _modem_added, NULL);
1248 sig_modem_removed = e_dbus_signal_handler_add(
1249 bus_conn, bus_id, "/",
1250 OFONO_PREFIX OFONO_MANAGER_IFACE,
1252 _modem_removed, NULL);
1254 sig_modem_prop_changed = e_dbus_signal_handler_add(
1255 bus_conn, bus_id, NULL,
1256 OFONO_PREFIX OFONO_MODEM_IFACE,
1258 _modem_property_changed, NULL);
1263 connected_cb((void *)connected_cb_data);
1266 static void _ofono_disconnected(void)
1268 eina_hash_free_buckets(modems);
1270 if (sig_modem_added) {
1271 e_dbus_signal_handler_del(bus_conn, sig_modem_added);
1272 sig_modem_added = NULL;
1275 if (sig_modem_removed) {
1276 e_dbus_signal_handler_del(bus_conn, sig_modem_removed);
1277 sig_modem_removed = NULL;
1280 if (sig_modem_prop_changed) {
1281 e_dbus_signal_handler_del(bus_conn, sig_modem_prop_changed);
1282 sig_modem_prop_changed = NULL;
1286 if (disconnected_cb)
1287 disconnected_cb((void *)disconnected_cb_data);
1294 static void _name_owner_changed(void *data __UNUSED__, DBusMessage *msg)
1297 const char *name, *from, *to;
1299 dbus_error_init(&err);
1300 if (!dbus_message_get_args(msg, &err,
1301 DBUS_TYPE_STRING, &name,
1302 DBUS_TYPE_STRING, &from,
1303 DBUS_TYPE_STRING, &to,
1304 DBUS_TYPE_INVALID)) {
1305 ERR("Could not get NameOwnerChanged arguments: %s: %s",
1306 err.name, err.message);
1307 dbus_error_free(&err);
1311 if (strcmp(name, bus_name) != 0)
1314 DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
1316 if (from[0] == '\0' && to[0] != '\0') {
1317 INF("oFono appeared as %s", to);
1318 _ofono_connected(to);
1319 } else if (from[0] != '\0' && to[0] == '\0') {
1320 INF("oFono disappeared from %s", from);
1321 _ofono_disconnected();
1325 static void _ofono_get_name_owner(void *data __UNUSED__, DBusMessage *msg, DBusError *err)
1327 DBusMessageIter itr;
1332 ERR("%s: %s", err->name, err->message);
1338 dbus_message_iter_init(msg, &itr);
1339 dbus_message_iter_get_basic(&itr, &id);
1340 if (!id || id[0] == '\0') {
1341 ERR("No name owner fo %s!", bus_name);
1345 INF("oFono bus id: %s", id);
1346 _ofono_connected(id);
1349 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
1350 const char *new, OFono_Simple_Cb cb,
1353 OFono_Simple_Cb_Context *ctx = NULL;
1354 OFono_Error err = OFONO_ERROR_OFFLINE;
1357 OFono_Modem *m = _modem_selected_get();
1358 EINA_SAFETY_ON_NULL_GOTO(m, error);
1359 EINA_SAFETY_ON_NULL_GOTO(what, error);
1360 EINA_SAFETY_ON_NULL_GOTO(old, error);
1361 EINA_SAFETY_ON_NULL_GOTO(new, error);
1363 if ((m->interfaces & OFONO_API_SIM) == 0)
1365 err = OFONO_ERROR_FAILED;
1368 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1369 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1374 msg = dbus_message_new_method_call(
1375 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
1380 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1381 DBUS_TYPE_STRING, &old,
1382 DBUS_TYPE_STRING, &new,
1386 INF("ChangePin(%s, %s, %s)", what, old, new);
1387 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1391 dbus_message_unref(msg);
1394 cb((void *)data, err);
1399 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
1400 const char *new, OFono_Simple_Cb cb,
1403 OFono_Simple_Cb_Context *ctx = NULL;
1404 OFono_Error err = OFONO_ERROR_OFFLINE;
1407 OFono_Modem *m = _modem_selected_get();
1408 EINA_SAFETY_ON_NULL_GOTO(m, error);
1409 EINA_SAFETY_ON_NULL_GOTO(what, error);
1410 EINA_SAFETY_ON_NULL_GOTO(puk, error);
1411 EINA_SAFETY_ON_NULL_GOTO(new, error);
1413 if ((m->interfaces & OFONO_API_SIM) == 0)
1415 err = OFONO_ERROR_FAILED;
1418 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1419 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1424 msg = dbus_message_new_method_call(
1425 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
1429 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &what,
1430 DBUS_TYPE_STRING, &puk,
1431 DBUS_TYPE_STRING, &new,
1435 INF("ResetPin(%s, %s, %s)", what, puk, new);
1436 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1440 dbus_message_unref(msg);
1443 cb((void *)data, err);
1448 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
1449 DBusMessageIter *itr)
1451 const char *ussd_response;
1453 if (dbus_message_iter_get_arg_type(itr) != DBUS_TYPE_STRING) {
1454 ERR("Invalid type: %c (expected: %c)",
1455 dbus_message_iter_get_arg_type(itr), DBUS_TYPE_STRING);
1458 dbus_message_iter_get_basic(itr, &ussd_response);
1459 EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
1460 return strdup(ussd_response);
1463 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
1464 DBusMessageIter *dict)
1466 for (; dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY;
1467 dbus_message_iter_next(dict)) {
1468 DBusMessageIter e, v;
1469 const char *key, *value;
1471 dbus_message_iter_recurse(dict, &e);
1472 dbus_message_iter_get_basic(&e, &key);
1474 dbus_message_iter_next(&e);
1475 dbus_message_iter_recurse(&e, &v);
1476 dbus_message_iter_get_basic(&v, &value);
1478 eina_strbuf_append_printf(buf, " %s=%s<br>",
1483 static char *_ss_initiate_convert_call1(const char *type, DBusMessageIter *itr)
1485 DBusMessageIter array, dict;
1486 const char *ss_op, *service;
1490 dbus_message_iter_recurse(itr, &array);
1492 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1493 ERR("Invalid type: %c (expected: %c)",
1494 dbus_message_iter_get_arg_type(&array),
1498 dbus_message_iter_get_basic(&array, &ss_op);
1499 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1501 if (!dbus_message_iter_next(&array)) {
1502 ERR("Missing %s service", type);
1506 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1507 ERR("Invalid type: %c (expected: %c)",
1508 dbus_message_iter_get_arg_type(&array),
1512 dbus_message_iter_get_basic(&array, &service);
1513 EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
1515 if (!dbus_message_iter_next(&array)) {
1516 ERR("Missing %s information", type);
1520 buf = eina_strbuf_new();
1521 eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
1522 type, ss_op, service);
1524 dbus_message_iter_recurse(&array, &dict);
1525 _ss_initiate_cb_dict_convert(buf, &dict);
1527 str = eina_strbuf_string_steal(buf);
1528 eina_strbuf_free(buf);
1532 static char *_ss_initiate_convert_call_waiting(const char *type,
1533 DBusMessageIter *itr)
1535 DBusMessageIter array, dict;
1540 dbus_message_iter_recurse(itr, &array);
1542 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1543 ERR("Invalid type: %c (expected: %c)",
1544 dbus_message_iter_get_arg_type(&array),
1548 dbus_message_iter_get_basic(&array, &ss_op);
1549 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1551 if (!dbus_message_iter_next(&array)) {
1552 ERR("Missing %s information", type);
1556 buf = eina_strbuf_new();
1557 eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
1560 dbus_message_iter_recurse(&array, &dict);
1561 _ss_initiate_cb_dict_convert(buf, &dict);
1563 str = eina_strbuf_string_steal(buf);
1564 eina_strbuf_free(buf);
1568 static char *_ss_initiate_convert_call2(const char *type,
1569 DBusMessageIter *itr)
1571 DBusMessageIter array;
1572 const char *ss_op, *status;
1576 dbus_message_iter_recurse(itr, &array);
1578 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1579 ERR("Invalid type: %c (expected: %c)",
1580 dbus_message_iter_get_arg_type(&array),
1584 dbus_message_iter_get_basic(&array, &ss_op);
1585 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
1587 if (!dbus_message_iter_next(&array)) {
1588 ERR("Missing %s status", type);
1592 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1593 ERR("Invalid type: %c (expected: %c)",
1594 dbus_message_iter_get_arg_type(&array),
1598 dbus_message_iter_get_basic(&array, &status);
1599 EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
1601 buf = eina_strbuf_new();
1602 eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
1603 type, ss_op, status);
1605 str = eina_strbuf_string_steal(buf);
1606 eina_strbuf_free(buf);
1610 static const struct SS_Initiate_Convert_Map {
1613 char *(*convert)(const char *type, DBusMessageIter *itr);
1614 } ss_initiate_convert_map[] = {
1615 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
1616 MAP("USSD", _ss_initiate_convert_ussd),
1617 MAP("CallBarring", _ss_initiate_convert_call1),
1618 MAP("CallForwarding", _ss_initiate_convert_call1),
1619 MAP("CallWaiting", _ss_initiate_convert_call_waiting),
1620 MAP("CallingLinePresentation", _ss_initiate_convert_call2),
1621 MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
1622 MAP("CallingLineRestriction", _ss_initiate_convert_call2),
1623 MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
1628 static char *_ss_initiate_convert(DBusMessage *msg)
1630 DBusMessageIter array, variant;
1631 const struct SS_Initiate_Convert_Map *citr;
1632 const char *type = NULL;
1635 if (!dbus_message_iter_init(msg, &array))
1638 if (dbus_message_iter_get_arg_type(&array) != DBUS_TYPE_STRING) {
1639 ERR("Invalid type for first argument: %c (expected: %c)",
1640 dbus_message_iter_get_arg_type(&array),
1644 dbus_message_iter_get_basic(&array, &type);
1646 ERR("Couldn't get SupplementaryServices.Initiate type");
1649 DBG("type: %s", type);
1651 if (!dbus_message_iter_next(&array)) {
1652 ERR("Couldn't get SupplementaryServices.Initiate payload");
1655 dbus_message_iter_recurse(&array, &variant);
1657 typelen = strlen(type);
1658 for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
1659 if ((citr->typelen == typelen) &&
1660 (memcmp(citr->type, type, typelen) == 0)) {
1661 return citr->convert(type, &variant);
1664 ERR("Could not convert SupplementaryServices.Initiate type %s", type);
1670 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
1672 OFono_String_Cb_Context *ctx = NULL;
1673 OFono_Error err = OFONO_ERROR_OFFLINE;
1676 OFono_Modem *m = _modem_selected_get();
1677 EINA_SAFETY_ON_NULL_GOTO(m, error);
1678 EINA_SAFETY_ON_NULL_GOTO(command, error);
1680 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
1682 err = OFONO_ERROR_FAILED;
1684 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
1685 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1688 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
1689 ctx->convert = _ss_initiate_convert;
1691 msg = dbus_message_new_method_call(
1692 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1697 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &command,
1701 INF("SupplementaryServices.Initiate(%s)", command);
1702 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
1706 dbus_message_unref(msg);
1709 cb((void *)data, err, NULL);
1714 typedef struct _OFono_Call_Cb_Context
1720 } OFono_Call_Cb_Context;
1722 static void _ofono_dial_reply(void *data, DBusMessage *msg, DBusError *err)
1724 OFono_Call_Cb_Context *ctx = data;
1725 OFono_Call *c = NULL;
1726 OFono_Error oe = OFONO_ERROR_NONE;
1729 DBG("%s: %s", err->name, err->message);
1730 oe = _ofono_error_parse(err->name);
1734 dbus_error_init(&e);
1735 if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH,
1736 &path, DBUS_TYPE_INVALID)) {
1737 ERR("Could not get Dial reply: %s: %s",
1739 dbus_error_free(&e);
1740 oe = OFONO_ERROR_FAILED;
1742 c = eina_hash_find(ctx->modem->calls, path);
1744 _call_add(ctx->modem, path, NULL);
1745 c = eina_hash_find(ctx->modem->calls, path);
1748 ERR("Could not find call %s", path);
1749 oe = OFONO_ERROR_FAILED;
1755 ctx->cb((void *)ctx->data, oe, c);
1758 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
1759 OFono_Call_Cb cb, const void *data)
1761 OFono_Call_Cb_Context *ctx = NULL;
1762 OFono_Error err = OFONO_ERROR_OFFLINE;
1765 OFono_Modem *m = _modem_selected_get();
1766 EINA_SAFETY_ON_NULL_GOTO(m, error);
1769 if ((m->interfaces & OFONO_API_VOICE) == 0)
1771 err = OFONO_ERROR_FAILED;
1776 ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
1777 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
1780 ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
1783 msg = dbus_message_new_method_call(
1784 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
1788 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number,
1789 DBUS_TYPE_STRING, &hide_callerid,
1793 INF("Dial(%s, %s)", number, hide_callerid);
1794 p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
1798 dbus_message_unref(msg);
1801 cb((void *)data, err, NULL);
1806 const char *ofono_modem_serial_get(void)
1808 OFono_Modem *m = _modem_selected_get();
1809 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
1813 void ofono_modem_api_require(unsigned int api_mask)
1815 if (modem_api_mask == api_mask)
1817 modem_api_mask = api_mask;
1818 modem_selected = NULL;
1821 void ofono_modem_path_wanted_set(const char *path)
1823 if (eina_stringshare_replace(&modem_path_wanted, path))
1824 modem_selected = NULL;
1827 void ofono_connected_cb_set(void (*cb)(void *data), const void *data)
1830 connected_cb_data = data;
1833 void ofono_disconnected_cb_set(void (*cb)(void *data), const void *data)
1835 disconnected_cb = cb;
1836 disconnected_cb_data = data;
1839 void ofono_changed_cb_set(void (*cb)(void *data), const void *data)
1842 changed_cb_data = data;
1845 void ofono_call_added_cb_set(void (*cb)(void *data, OFono_Call *call),
1849 call_added_cb_data = data;
1852 void ofono_call_removed_cb_set(void (*cb)(void *data, OFono_Call *call),
1855 call_removed_cb = cb;
1856 call_removed_cb_data = data;
1859 void ofono_call_changed_cb_set(void (*cb)(void *data, OFono_Call *call),
1862 call_changed_cb = cb;
1863 call_changed_cb_data = data;
1866 void ofono_call_disconnected_cb_set(void (*cb)(void *data, OFono_Call *call, const char *reason),
1869 call_disconnected_cb = cb;
1870 call_disconnected_cb_data = data;
1873 Eina_Bool ofono_init(void)
1875 if (!elm_need_e_dbus()) {
1876 CRITICAL("Elementary does not support DBus.");
1880 bus_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM);
1882 CRITICAL("Could not get DBus System Bus");
1886 modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
1887 EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
1889 e_dbus_signal_handler_add(bus_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH,
1890 E_DBUS_FDO_INTERFACE,
1892 _name_owner_changed, NULL);
1894 e_dbus_get_name_owner(bus_conn, bus_name, _ofono_get_name_owner, NULL);
1899 void ofono_shutdown(void)
1901 if (pc_get_modems) {
1902 dbus_pending_call_cancel(pc_get_modems);
1903 pc_get_modems = NULL;
1906 _ofono_disconnected();
1907 eina_stringshare_replace(&modem_path_wanted, NULL);
1909 eina_hash_free(modems);
1913 static OFono_Pending *_ofono_call_volume_property_set(char *property,
1914 int type, void *value,
1919 OFono_Simple_Cb_Context *ctx = NULL;
1921 DBusMessageIter iter, variant;
1922 OFono_Modem *m = _modem_selected_get();
1923 char type_to_send[2] = { type , DBUS_TYPE_INVALID };
1925 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
1928 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
1929 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
1934 msg = dbus_message_new_method_call(bus_id, m->base.path,
1935 OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1938 goto error_no_dbus_message;
1940 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &property,
1942 goto error_message_args;
1944 dbus_message_iter_init_append(msg, &iter);
1946 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
1947 type_to_send, &variant))
1948 goto error_message_args;
1950 if (!dbus_message_iter_append_basic(&variant, type, value) ||
1951 !dbus_message_iter_close_container(&iter, &variant)) {
1952 dbus_message_iter_abandon_container(&iter, &variant);
1953 goto error_message_args;
1956 INF("Call-Volume - Property:%s called.", property);
1957 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
1961 dbus_message_unref(msg);
1963 error_no_dbus_message:
1965 cb((void *)data, OFONO_ERROR_FAILED);
1970 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
1973 dbus_bool_t dbus_mute = !!mute;
1975 return _ofono_call_volume_property_set("Muted", DBUS_TYPE_BOOLEAN,
1976 &dbus_mute, cb, data);
1979 Eina_Bool ofono_mute_get(void)
1981 OFono_Modem *m = _modem_selected_get();
1982 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
1986 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
1991 return _ofono_call_volume_property_set("SpeakerVolume", DBUS_TYPE_BYTE,
1995 unsigned char ofono_volume_speaker_get(void)
1997 OFono_Modem *m = _modem_selected_get();
1998 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
1999 return m->speaker_volume;
2002 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
2006 return _ofono_call_volume_property_set("MicrophoneVolume",
2007 DBUS_TYPE_BYTE, &volume, cb,
2011 unsigned char ofono_volume_microphone_get(void)
2013 OFono_Modem *m = _modem_selected_get();
2014 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
2015 return m->microphone_volume;
2018 OFono_Pending *ofono_tones_send(const char *tones,
2024 OFono_Simple_Cb_Context *ctx = NULL;
2025 OFono_Modem *m = _modem_selected_get();
2027 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2030 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2031 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2036 msg = dbus_message_new_method_call(
2037 bus_id, m->base.path,
2038 OFONO_PREFIX OFONO_VOICE_IFACE,
2041 goto error_no_dbus_message;
2043 if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &tones,
2045 goto error_message_args;
2047 INF("Voice-Call-Manager - SendTones:%s called.", tones);
2048 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2052 dbus_message_unref(msg);
2054 error_no_dbus_message:
2056 cb((void *)data, OFONO_ERROR_FAILED);
2061 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
2064 return _ofono_multiparty("CreateMultiparty",
2065 _ofono_simple_reply, cb, data);