4 #include <Elementary.h>
12 typedef struct _OFono_Modem OFono_Modem;
13 typedef struct _OFono_Bus_Object OFono_Bus_Object;
15 static const char bus_name[] = "org.ofono";
17 static const char *known_modem_types[] = {"hfp", "sap", "hardware", NULL};
19 static Eldbus_Connection *bus_conn = NULL;
20 static char *bus_id = NULL;
21 static Eina_Hash *modems = NULL;
22 static OFono_Modem *modem_selected = NULL;
23 static const char *modem_path_wanted = NULL;
24 static unsigned int modem_api_mask = 0;
25 static Eina_List *modem_types = NULL;
26 static Eldbus_Signal_Handler *sig_modem_added = NULL;
27 static Eldbus_Signal_Handler *sig_modem_removed = NULL;
28 static Eldbus_Signal_Handler *sig_modem_prop_changed = NULL;
29 static Eldbus_Pending *pc_get_modems = NULL;
31 static void _ofono_call_volume_properties_get(OFono_Modem *m);
32 static void _ofono_msg_waiting_properties_get(OFono_Modem *m);
33 static void _ofono_suppl_serv_properties_get(OFono_Modem *m);
34 static void _ofono_msg_properties_get(OFono_Modem *m);
36 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
37 OFono_Simple_Cb cb, const void *data);
39 struct _OFono_Callback_List_Modem_Node
42 void (*cb)(void *data);
46 struct _OFono_Callback_List_Call_Node
49 void (*cb)(void *data, OFono_Call *call);
53 struct _OFono_Callback_List_Call_Disconnected_Node
56 void (*cb)(void *data, OFono_Call *call, const char *reason);
60 struct _OFono_Callback_List_USSD_Notify_Node
63 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg);
67 struct _OFono_Callback_List_Sent_SMS_Node
74 struct _OFono_Callback_List_Incoming_SMS_Node
77 OFono_Incoming_SMS_Cb cb;
81 static Eina_Inlist *cbs_modem_changed = NULL;
82 static Eina_Inlist *cbs_modem_connected = NULL;
83 static Eina_Inlist *cbs_modem_disconnected = NULL;
84 static Eina_Inlist *cbs_ussd_notify = NULL;
86 static Eina_Inlist *cbs_call_changed = NULL;
87 static Eina_Inlist *cbs_call_added = NULL;
88 static Eina_Inlist *cbs_call_disconnected = NULL;
89 static Eina_Inlist *cbs_call_removed = NULL;
91 static Eina_Inlist *cbs_sent_sms_changed = NULL;
92 static Eina_Inlist *cbs_incoming_sms = NULL;
94 #define OFONO_SERVICE "org.ofono"
96 #define OFONO_PREFIX OFONO_SERVICE "."
97 #define OFONO_PREFIX_ERROR OFONO_SERVICE ".Error."
98 #define OFONO_MODEM_IFACE "Modem"
99 #define OFONO_MANAGER_IFACE "Manager"
100 #define OFONO_SIM_IFACE "SimManager"
101 #define OFONO_NETREG_IFACE "NetworkRegistration"
102 #define OFONO_VOICE_IFACE "VoiceCallManager"
103 #define OFONO_MSG_IFACE "MessageManager"
104 #define OFONO_MSG_WAITING_IFACE "MessageWaiting"
105 #define OFONO_SMART_MSG_IFACE "SmartMessaging"
106 #define OFONO_STK_IFACE "SimToolkit"
108 #define OFONO_CALL_FW_IFACE "CallForwarding"
109 #define OFONO_CALL_VOL_IFACE "CallVolume"
110 #define OFONO_CALL_METER_IFACE "CallMeter"
111 #define OFONO_CALL_SET_IFACE "CallSettings"
112 #define OFONO_CALL_BAR_IFACE "CallBarring"
113 #define OFONO_SUPPL_SERV_IFACE "SupplementaryServices"
114 #define OFONO_TXT_TEL_IFACE "TextTelephony"
115 #define OFONO_CELL_BROAD_IFACE "CellBroadcast"
116 #define OFONO_CONNMAN_IFACE "ConnectionManager"
117 #define OFONO_PUSH_NOTIF_IFACE "PushNotification"
118 #define OFONO_PHONEBOOK_IFACE "Phonebook"
119 #define OFONO_ASN_IFACE "AssistedSatelliteNavigation"
121 static const struct API_Interface_Map {
125 } api_iface_map[] = {
126 #define MAP(bit, name) {bit, name, sizeof(name) - 1}
127 MAP(OFONO_API_SIM, OFONO_SIM_IFACE),
128 MAP(OFONO_API_NETREG, OFONO_NETREG_IFACE),
129 MAP(OFONO_API_VOICE, OFONO_VOICE_IFACE),
130 MAP(OFONO_API_MSG, OFONO_MSG_IFACE),
131 MAP(OFONO_API_MSG_WAITING, OFONO_MSG_WAITING_IFACE),
132 MAP(OFONO_API_SMART_MSG, OFONO_SMART_MSG_IFACE),
133 MAP(OFONO_API_STK, OFONO_STK_IFACE),
134 MAP(OFONO_API_CALL_FW, OFONO_CALL_FW_IFACE),
135 MAP(OFONO_API_CALL_VOL, OFONO_CALL_VOL_IFACE),
136 MAP(OFONO_API_CALL_METER, OFONO_CALL_METER_IFACE),
137 MAP(OFONO_API_CALL_SET, OFONO_CALL_SET_IFACE),
138 MAP(OFONO_API_CALL_BAR, OFONO_CALL_BAR_IFACE),
139 MAP(OFONO_API_SUPPL_SERV, OFONO_SUPPL_SERV_IFACE),
140 MAP(OFONO_API_TXT_TEL, OFONO_TXT_TEL_IFACE),
141 MAP(OFONO_API_CELL_BROAD, OFONO_CELL_BROAD_IFACE),
142 MAP(OFONO_API_CONNMAN, OFONO_CONNMAN_IFACE),
143 MAP(OFONO_API_PUSH_NOTIF, OFONO_PUSH_NOTIF_IFACE),
144 MAP(OFONO_API_PHONEBOOK, OFONO_PHONEBOOK_IFACE),
145 MAP(OFONO_API_ASN, OFONO_ASN_IFACE),
150 static const struct Error_Map {
156 #define MAP(id, name, msg) {id, name, msg, sizeof(name) - 1}
157 MAP(OFONO_ERROR_FAILED, "Failed", "Failed"),
158 MAP(OFONO_ERROR_DOES_NOT_EXIST, "DoesNotExist", "Does not exist"),
159 MAP(OFONO_ERROR_IN_PROGRESS, "InProgress", "Operation in progress"),
160 MAP(OFONO_ERROR_IN_USE, "InUse", "Already in use"),
161 MAP(OFONO_ERROR_INVALID_ARGS, "InvalidArguments", "Invalid arguments"),
162 MAP(OFONO_ERROR_INVALID_FORMAT, "InvalidFormat", "Invalid format"),
163 MAP(OFONO_ERROR_ACCESS_DENIED, "AccessDenied", "Access Denied"),
164 MAP(OFONO_ERROR_ATTACH_IN_PROGRESS, "AttachInProgress",
165 "Attach is already in progress"),
166 MAP(OFONO_ERROR_INCORRECT_PASSWORD, "IncorrectPassword",
167 "Incorrect password"),
168 MAP(OFONO_ERROR_NOT_ACTIVE, "NotActive", "Not active"),
169 MAP(OFONO_ERROR_NOT_ALLOWED, "NotAllowed", "Not allowed"),
170 MAP(OFONO_ERROR_NOT_ATTACHED, "NotAttached", "Not attached"),
171 MAP(OFONO_ERROR_NOT_AVAILABLE, "NotAvailable", "Not available"),
172 MAP(OFONO_ERROR_NOT_FOUND, "NotFound", "Not found"),
173 MAP(OFONO_ERROR_NOT_IMPLEMENTED, "NotImplemented", "Not implemented"),
174 MAP(OFONO_ERROR_NOT_RECOGNIZED, "NotRecognized", "Not recognized"),
175 MAP(OFONO_ERROR_NOT_REGISTERED, "NotRegistered", "Not registered"),
176 MAP(OFONO_ERROR_NOT_SUPPORTED, "NotSupported", "Not supported"),
177 MAP(OFONO_ERROR_SIM_NOT_READY, "SimNotReady", "SIM not ready"),
178 MAP(OFONO_ERROR_STK, "SimToolkit", "SIM Toolkit Failed"),
179 MAP(OFONO_ERROR_TIMEDOUT, "Timedout", "Timed out"),
184 const char *ofono_error_message_get(OFono_Error e)
186 const struct Error_Map *itr;
188 if (e == OFONO_ERROR_NONE)
191 for (itr = error_map; itr->name != NULL; itr++)
195 return "Unknown error";
198 static OFono_Error _ofono_error_parse(const char *name)
200 size_t namelen, prefixlen = sizeof(OFONO_PREFIX_ERROR) - 1;
201 const struct Error_Map *itr;
203 /* whenever interfaces are not there due modem being offline */
204 if (strcmp(name, "org.freedesktop.DBus.Error.UnknownMethod") == 0)
205 return OFONO_ERROR_OFFLINE;
207 if (strncmp(name, OFONO_PREFIX_ERROR, prefixlen) != 0)
208 return OFONO_ERROR_FAILED;
211 namelen = strlen(name);
212 for (itr = error_map; itr->name != NULL; itr++)
213 if ((itr->namelen == namelen) &&
214 (memcmp(name, itr->name, namelen) == 0))
217 return OFONO_ERROR_FAILED;
220 typedef struct _OFono_Simple_Cb_Context
224 } OFono_Simple_Cb_Context;
226 static void _ofono_simple_reply(void *data, Eldbus_Message *msg,
227 Eldbus_Pending *pending __UNUSED__)
229 OFono_Simple_Cb_Context *ctx = data;
230 OFono_Error oe = OFONO_ERROR_NONE;
231 const char *err_name, *err_message;
235 oe = OFONO_ERROR_FAILED;
238 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
239 ERR("Ofono reply error %s: %s", err_name, err_message);
240 oe = _ofono_error_parse(err_name);
244 ctx->cb((void *)ctx->data, oe);
249 typedef struct _OFono_String_Cb_Context
254 char *(*convert)(Eldbus_Message *msg);
255 } OFono_String_Cb_Context;
257 static void _ofono_string_reply(void *data, Eldbus_Message *msg,
258 Eldbus_Pending *pending __UNUSED__)
260 OFono_String_Cb_Context *ctx = data;
261 OFono_Error oe = OFONO_ERROR_NONE;
263 const char *err_name, *err_message;
265 EINA_SAFETY_ON_NULL_RETURN(data);
269 oe = OFONO_ERROR_FAILED;
272 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
273 ERR("Ofono reply error %s: %s", err_name, err_message);
274 oe = _ofono_error_parse(err_name);
276 str = ctx->convert(msg);
278 oe = OFONO_ERROR_NOT_SUPPORTED;
282 ctx->cb((void *)ctx->data, oe, str);
284 DBG("%s %s", ctx->name, str);
290 struct _OFono_Pending
293 Eldbus_Pending *pending;
294 Eldbus_Message_Cb cb;
299 struct _OFono_Bus_Object
302 Eina_Inlist *dbus_pending; /* of OFono_Pending */
303 Eina_List *dbus_signals; /* of Eldbus_Signal_Handler */
306 static void _notify_ofono_callbacks_call_list(Eina_Inlist *list,
309 OFono_Callback_List_Call_Node *node;
311 EINA_INLIST_FOREACH(list, node)
312 node->cb((void *) node->cb_data, call);
315 static void _notify_ofono_callbacks_call_disconnected_list(Eina_Inlist *list,
319 OFono_Callback_List_Call_Disconnected_Node *node;
321 DBG("call=%p, reason=%s", call, reason);
323 EINA_INLIST_FOREACH(list, node)
324 node->cb((void *) node->cb_data, call, reason);
327 static void _notify_ofono_callbacks_ussd_notify_list(Eina_Inlist *list,
328 Eina_Bool needs_reply,
331 OFono_Callback_List_USSD_Notify_Node *node;
333 DBG("needs_reply=%hhu, msg=%s", needs_reply, msg);
335 EINA_INLIST_FOREACH(list, node)
336 node->cb((void *) node->cb_data, needs_reply, msg);
339 static void _bus_object_free(OFono_Bus_Object *o)
341 Eldbus_Signal_Handler *sh;
343 eina_stringshare_del(o->path);
345 while (o->dbus_pending) {
346 ofono_pending_cancel(
347 EINA_INLIST_CONTAINER_GET(o->dbus_pending,
351 EINA_LIST_FREE(o->dbus_signals, sh)
352 eldbus_signal_handler_del(sh);
357 static void _bus_object_message_send_reply(void *data, Eldbus_Message *reply,
358 Eldbus_Pending *pending __UNUSED__)
360 OFono_Pending *p = data;
361 OFono_Bus_Object *o = p->owner;
364 p->cb(p->data, reply, NULL);
366 if (!o->dbus_pending)
369 o->dbus_pending = eina_inlist_remove(o->dbus_pending, EINA_INLIST_GET(p));
373 static OFono_Pending *_bus_object_message_send(OFono_Bus_Object *o,
375 Eldbus_Message_Cb cb,
379 EINA_SAFETY_ON_NULL_GOTO(o, error);
380 EINA_SAFETY_ON_NULL_GOTO(msg, error);
382 p = calloc(1, sizeof(OFono_Pending));
383 EINA_SAFETY_ON_NULL_GOTO(p, error);
389 p->pending = eldbus_connection_send(
390 bus_conn, msg, _bus_object_message_send_reply, p, -1);
391 EINA_SAFETY_ON_NULL_GOTO(p->pending, error_send);
393 o->dbus_pending = eina_inlist_append(o->dbus_pending,
402 cb(data, NULL, NULL);
404 eldbus_message_unref(msg);
408 void ofono_pending_cancel(OFono_Pending *p)
412 EINA_SAFETY_ON_NULL_RETURN(p);
415 o->dbus_pending = eina_inlist_remove(o->dbus_pending, EINA_INLIST_GET(p));
418 p->cb(p->data, NULL, NULL);
420 eldbus_pending_cancel(p->pending);
424 static void _bus_object_signal_listen(OFono_Bus_Object *o, const char *iface,
425 const char *name, Eldbus_Signal_Cb cb,
428 Eldbus_Signal_Handler *sh = eldbus_signal_handler_add(
429 bus_conn, bus_id, o->path, iface, name, cb, data);
430 EINA_SAFETY_ON_NULL_RETURN(sh);
432 o->dbus_signals = eina_list_append(o->dbus_signals, sh);
435 typedef struct _OFono_Call_Cb_Context
441 } OFono_Call_Cb_Context;
445 OFono_Bus_Object base;
447 const char *incoming_line;
450 time_t full_start_time;
451 OFono_Call_State state;
452 Eina_Bool multiparty : 1;
453 Eina_Bool emergency : 1;
454 OFono_Call_Cb_Context *pending_dial;
457 typedef struct _OFono_Sent_SMS_Cb_Context
459 OFono_Sent_SMS_Cb cb;
462 const char *destination;
464 } OFono_Sent_SMS_Cb_Context;
466 struct _OFono_Sent_SMS
468 OFono_Bus_Object base;
469 OFono_Sent_SMS_State state;
470 OFono_Sent_SMS_Cb_Context *pending_send;
471 const char *destination;
478 OFono_Bus_Object base;
481 const char *voicemail_number;
482 const char *serv_center_addr;
483 const char *msg_bearer;
484 const char *msg_alphabet;
487 unsigned int interfaces;
488 unsigned char strength;
489 unsigned char data_strength;
490 unsigned char speaker_volume;
491 unsigned char microphone_volume;
492 unsigned char voicemail_count;
493 OFono_USSD_State ussd_state;
494 Eina_Bool ignored : 1;
495 Eina_Bool powered : 1;
496 Eina_Bool online : 1;
497 Eina_Bool roaming : 1;
499 Eina_Bool voicemail_waiting : 1;
500 Eina_Bool use_delivery_reports : 1;
503 static OFono_Call *_call_new(const char *path)
505 OFono_Call *c = calloc(1, sizeof(OFono_Call));
506 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
508 c->base.path = eina_stringshare_add(path);
509 EINA_SAFETY_ON_NULL_GOTO(c->base.path, error_path);
511 c->start_time = -1.0;
520 static void _call_free(OFono_Call *c)
522 DBG("c=%p %s", c, c->base.path);
523 ofono_call_hangup(c, NULL, NULL);
525 _notify_ofono_callbacks_call_list(cbs_call_removed, c);
527 eina_stringshare_del(c->line_id);
528 eina_stringshare_del(c->incoming_line);
529 eina_stringshare_del(c->name);
531 _bus_object_free(&c->base);
534 static OFono_Call_State _call_state_parse(const char *str)
536 if (strcmp(str, "active") == 0)
537 return OFONO_CALL_STATE_ACTIVE;
538 else if (strcmp(str, "held") == 0)
539 return OFONO_CALL_STATE_HELD;
540 else if (strcmp(str, "dialing") == 0)
541 return OFONO_CALL_STATE_DIALING;
542 else if (strcmp(str, "alerting") == 0)
543 return OFONO_CALL_STATE_ALERTING;
544 else if (strcmp(str, "incoming") == 0)
545 return OFONO_CALL_STATE_INCOMING;
546 else if (strcmp(str, "waiting") == 0)
547 return OFONO_CALL_STATE_WAITING;
548 else if (strcmp(str, "disconnected") == 0)
549 return OFONO_CALL_STATE_DISCONNECTED;
551 ERR("unknown call state: %s", str);
552 return OFONO_CALL_STATE_DISCONNECTED;
555 static time_t _ofono_time_parse(const char *str)
560 memset(&tm, 0, sizeof(tm));
562 strptime(str, "%Y-%m-%dT%H:%M:%S%z", &tm);
563 zonediff = tm.tm_gmtoff; /* mktime resets it */
565 return mktime(&tm) - zonediff - timezone;
568 static void _call_property_update(OFono_Call *c, const char *key,
569 Eldbus_Message_Iter *value)
571 if (strcmp(key, "LineIdentification") == 0) {
573 eldbus_message_iter_basic_get(value, &str);
574 DBG("%s LineIdentification %s", c->base.path, str);
575 eina_stringshare_replace(&c->line_id, str);
576 } else if (strcmp(key, "IncomingLine") == 0) {
578 eldbus_message_iter_basic_get(value, &str);
579 DBG("%s IncomingLine %s", c->base.path, str);
580 eina_stringshare_replace(&c->incoming_line, str);
581 } else if (strcmp(key, "State") == 0) {
583 OFono_Call_State state;
584 eldbus_message_iter_basic_get(value, &str);
585 state = _call_state_parse(str);
586 DBG("%s State %s (%d)", c->base.path, str, state);
588 if (state == OFONO_CALL_STATE_ACTIVE) {
589 if (c->start_time < 0.0)
590 c->start_time = ecore_loop_time_get();
591 if (c->full_start_time == 0)
592 c->full_start_time = time(NULL);
594 } else if (strcmp(key, "Name") == 0) {
596 eldbus_message_iter_basic_get(value, &str);
597 DBG("%s Name %s", c->base.path, str);
598 eina_stringshare_replace(&c->name, str);
599 } else if (strcmp(key, "Multiparty") == 0) {
601 eldbus_message_iter_basic_get(value, &v);
602 DBG("%s Multiparty %d", c->base.path, v);
604 } else if (strcmp(key, "Emergency") == 0) {
606 eldbus_message_iter_basic_get(value, &v);
607 DBG("%s Emergency %d", c->base.path, v);
609 } else if (strcmp(key, "StartTime") == 0) {
610 const char *ts = NULL;
613 eldbus_message_iter_basic_get(value, &ts);
615 st = _ofono_time_parse(ts);
617 lt = ecore_loop_time_get();
618 c->start_time = st - ut + lt;
619 c->full_start_time = st;
620 DBG("%s StartTime %f (%s)", c->base.path, c->start_time, ts);
622 DBG("%s %s (unused property)", c->base.path, key);
625 static void _call_property_changed(void *data, Eldbus_Message *msg)
627 OFono_Call *c = data;
628 Eldbus_Message_Iter *value;
632 ERR("Could not handle message %p", msg);
636 DBG("path=%s", c->base.path);
638 if (!eldbus_message_arguments_get(msg, "sv", &key, &value)) {
639 ERR("Could not get call PropertyChanged arguments");
643 _call_property_update(c, key, value);
645 _notify_ofono_callbacks_call_list(cbs_call_changed, c);
648 static void _call_disconnect_reason(void *data, Eldbus_Message *msg)
650 OFono_Call *c = data;
658 DBG("path=%s", c->base.path);
659 c->state = OFONO_CALL_STATE_DISCONNECTED;
661 if (!eldbus_message_arguments_get(msg, "s", &reason)) {
662 ERR("Could not get DisconnectReason arguments");
666 _notify_ofono_callbacks_call_disconnected_list(cbs_call_disconnected,
670 static OFono_Call *_call_common_add(OFono_Modem *m, const char *path)
672 OFono_Call *c = _call_new(path);
673 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
674 eina_hash_add(m->calls, c->base.path, c);
676 _bus_object_signal_listen(&c->base,
677 OFONO_PREFIX "VoiceCall",
679 _call_disconnect_reason, c);
680 _bus_object_signal_listen(&c->base,
681 OFONO_PREFIX "VoiceCall",
683 _call_property_changed, c);
687 static OFono_Call *_call_pending_add(OFono_Modem *m, const char *path,
688 OFono_Call_Cb_Context *ctx)
692 DBG("path=%s, ctx=%p", path, ctx);
694 c = _call_common_add(m, path);
695 c->pending_dial = ctx;
699 static void _call_add(OFono_Modem *m, const char *path, Eldbus_Message_Iter *prop)
702 Eina_Bool needs_cb_added;
703 Eldbus_Message_Iter *dict_entry;
705 DBG("path=%s, prop=%p", path, prop);
707 c = eina_hash_find(m->calls, path);
710 DBG("Call already exists %p (%s)", c, path);
712 c = _call_common_add(m, path);
713 EINA_SAFETY_ON_NULL_RETURN(c);
716 while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
717 Eldbus_Message_Iter *value;
720 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
721 ERR("Could not get arguments");
725 _call_property_update(c, key, value);
728 if (c->pending_dial) {
729 OFono_Call_Cb_Context *ctx = c->pending_dial;
731 ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, c);
733 c->pending_dial = NULL;
734 needs_cb_added = EINA_TRUE;
738 _notify_ofono_callbacks_call_list(cbs_call_added, c);
740 _notify_ofono_callbacks_call_list(cbs_call_changed, c);
743 static void _call_remove(OFono_Modem *m, const char *path)
745 DBG("path=%s", path);
746 eina_hash_del_by_key(m->calls, path);
749 static void _call_added(void *data, Eldbus_Message *msg)
751 OFono_Modem *m = data;
752 Eldbus_Message_Iter *properties;
756 ERR("Could not handle message %p", msg);
760 if (!eldbus_message_arguments_get(msg, "oa{sv}", &path, &properties)) {
761 ERR("Could not get CallAdded arguments");
765 _call_add(m, path, properties);
768 static void _call_removed(void *data, Eldbus_Message *msg)
770 OFono_Modem *m = data;
774 ERR("Could not handle message %p", msg);
778 if (!eldbus_message_arguments_get(msg, "o", &path)) {
779 ERR("Could not get CallRemoved arguments");
783 _call_remove(m, path);
786 static OFono_Modem *_modem_selected_get(void)
788 OFono_Modem *found_path = NULL, *found_api = NULL, *m;
789 unsigned int online = 0, powered = 0;
793 return modem_selected;
795 itr = eina_hash_iterator_data_new(modems);
796 EINA_ITERATOR_FOREACH(itr, m) {
805 if ((modem_path_wanted) && (!found_path)) {
806 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
807 if (m->base.path == modem_path_wanted) {
813 if ((!found_api) || ((!found_api->online) ||
814 (!found_api->powered))) {
815 DBG("m=%#x, mask=%#x, previous=%s "
816 "(online=%d, powered=%d)",
817 m->interfaces, modem_api_mask,
818 found_api ? found_api->base.path : "",
819 found_api ? found_api->online : 0,
820 found_api ? found_api->powered : 0);
821 if ((m->interfaces & modem_api_mask) == modem_api_mask)
825 eina_iterator_free(itr);
827 INF("found_path=%s, found_api=%s, wanted_path=%s, api_mask=%#x",
828 found_path ? found_path->base.path : "",
829 found_api ? found_api->base.path: "",
830 modem_path_wanted ? modem_path_wanted : "",
834 ERR("No modems powered! Run connman or test/enable-modem");
836 WRN("No modems online! Run connman or test/online-modem");
838 modem_selected = found_path ? found_path : found_api;
839 return modem_selected;
842 static OFono_Pending *_ofono_multiparty(const char *method,
843 OFono_Simple_Cb cb, const void *data)
848 OFono_Simple_Cb_Context *ctx = NULL;
849 OFono_Modem *m = _modem_selected_get();
851 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
854 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
855 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
860 msg = eldbus_message_method_call_new(
861 bus_id, m->base.path,
862 OFONO_PREFIX OFONO_VOICE_IFACE,
866 goto error_no_message;
869 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
875 cb((void *)data, OFONO_ERROR_FAILED);
880 OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb,
883 OFono_Simple_Cb_Context *ctx = NULL;
887 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
890 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
891 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
896 msg = eldbus_message_method_call_new(
897 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Hangup");
901 INF("Hangup(%s)", c->base.path);
902 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
907 cb((void *)data, OFONO_ERROR_FAILED);
912 OFono_Pending *ofono_call_answer(OFono_Call *c, OFono_Simple_Cb cb,
915 OFono_Simple_Cb_Context *ctx = NULL;
919 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
922 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
923 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
928 msg = eldbus_message_method_call_new(
929 bus_id, c->base.path, OFONO_PREFIX "VoiceCall", "Answer");
933 INF("Answer(%s)", c->base.path);
934 p = _bus_object_message_send(&c->base, msg, _ofono_simple_reply, ctx);
939 cb((void *)data, OFONO_ERROR_FAILED);
944 OFono_Call_State ofono_call_state_get(const OFono_Call *c)
946 EINA_SAFETY_ON_NULL_RETURN_VAL(c, OFONO_CALL_STATE_DISCONNECTED);
950 const char *ofono_call_name_get(const OFono_Call *c)
952 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
956 const char *ofono_call_line_id_get(const OFono_Call *c)
958 EINA_SAFETY_ON_NULL_RETURN_VAL(c, NULL);
962 Eina_Bool ofono_call_multiparty_get(const OFono_Call *c)
964 EINA_SAFETY_ON_NULL_RETURN_VAL(c, EINA_FALSE);
965 return c->multiparty;
968 double ofono_call_start_time_get(const OFono_Call *c)
970 EINA_SAFETY_ON_NULL_RETURN_VAL(c, -1.0);
971 return c->start_time;
974 time_t ofono_call_full_start_time_get(const OFono_Call *c)
976 EINA_SAFETY_ON_NULL_RETURN_VAL(c, 0);
977 return c->full_start_time;
980 static void _ofono_calls_get_reply(void *data, Eldbus_Message *msg,
981 Eldbus_Pending *pending __UNUSED__)
983 Eldbus_Message_Iter *array, *dict_entry;
984 const char *err_name, *err_message;
986 EINA_SAFETY_ON_NULL_RETURN(data);
987 OFono_Modem *m = data;
994 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
995 ERR("Failed to get reply: %s: %s", err_name, err_message);
999 eina_hash_free_buckets(m->calls);
1001 if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array)) {
1002 ERR("Could not get calls");
1006 while (eldbus_message_iter_get_and_next(array, 'r', &dict_entry)) {
1007 Eldbus_Message_Iter *properties;
1010 if (!eldbus_message_iter_arguments_get(dict_entry, "oa{sv}", &path, &properties)) {
1011 ERR("Could not get CallAdded arguments");
1015 _call_add(m, path, properties);
1019 static void _modem_calls_load(OFono_Modem *m)
1021 Eldbus_Message *msg = eldbus_message_method_call_new(
1022 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE,
1025 DBG("Get calls of %s", m->base.path);
1026 _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m);
1029 static OFono_Sent_SMS *_sent_sms_new(const char *path)
1031 OFono_Sent_SMS *sms = calloc(1, sizeof(OFono_Sent_SMS));
1032 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
1034 sms->base.path = eina_stringshare_add(path);
1035 EINA_SAFETY_ON_NULL_GOTO(sms->base.path, error_path);
1044 static void _sent_sms_free(OFono_Sent_SMS *sms)
1046 DBG("sms=%p %s", sms, sms->base.path);
1047 eina_stringshare_del(sms->destination);
1048 eina_stringshare_del(sms->message);
1049 _bus_object_free(&sms->base);
1052 static OFono_Modem *_modem_new(const char *path)
1054 OFono_Modem *m = calloc(1, sizeof(OFono_Modem));
1055 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
1057 m->base.path = eina_stringshare_add(path);
1058 EINA_SAFETY_ON_NULL_GOTO(m->base.path, error_path);
1060 m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free));
1061 EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls);
1063 m->sent_sms = eina_hash_string_small_new(EINA_FREE_CB(_sent_sms_free));
1064 EINA_SAFETY_ON_NULL_GOTO(m->sent_sms, error_sent_sms);
1069 eina_hash_free(m->calls);
1071 eina_stringshare_del(m->base.path);
1077 static void _modem_free(OFono_Modem *m)
1079 DBG("m=%p %s", m, m->base.path);
1081 if (modem_selected == m)
1082 modem_selected = NULL;
1084 eina_stringshare_del(m->name);
1085 eina_stringshare_del(m->serial);
1086 eina_stringshare_del(m->voicemail_number);
1087 eina_stringshare_del(m->serv_center_addr);
1088 eina_stringshare_del(m->msg_bearer);
1089 eina_stringshare_del(m->msg_alphabet);
1091 eina_hash_free(m->calls);
1092 eina_hash_free(m->sent_sms);
1094 _bus_object_free(&m->base);
1098 static void _call_volume_property_update(OFono_Modem *m, const char *prop_name,
1099 Eldbus_Message_Iter *iter)
1102 if (strcmp(prop_name, "Muted") == 0) {
1104 eldbus_message_iter_basic_get(iter, &b);
1106 DBG("%s Muted %d", m->base.path, m->muted);
1107 } else if (strcmp(prop_name, "SpeakerVolume") == 0) {
1108 eldbus_message_iter_basic_get(iter, &m->speaker_volume);
1109 DBG("%s Speaker Volume %hhu", m->base.path, m->speaker_volume);
1110 } else if (strcmp(prop_name, "MicrophoneVolume") == 0) {
1111 eldbus_message_iter_basic_get(iter, &m->microphone_volume);
1112 DBG("%s Microphone Volume %hhu", m->base.path, m->speaker_volume);
1114 DBG("%s %s (unused property)", m->base.path, prop_name);
1117 static void _msg_waiting_property_update(OFono_Modem *m, const char *prop_name,
1118 Eldbus_Message_Iter *iter)
1121 if (strcmp(prop_name, "VoicemailWaiting") == 0) {
1123 eldbus_message_iter_basic_get(iter, &b);
1124 m->voicemail_waiting = b;
1125 DBG("%s VoicemailWaiting %d",
1126 m->base.path, m->voicemail_waiting);
1127 } else if (strcmp(prop_name, "VoicemailMessageCount") == 0) {
1128 eldbus_message_iter_basic_get(iter, &m->voicemail_count);
1129 DBG("%s VoicemailMessageCount %hhu",
1130 m->base.path, m->voicemail_count);
1131 } else if (strcmp(prop_name, "VoicemailMailboxNumber") == 0) {
1133 eldbus_message_iter_basic_get(iter, &s);
1134 eina_stringshare_replace(&(m->voicemail_number), s);
1135 DBG("%s VoicemailMailboxNumber %s",
1136 m->base.path, m->voicemail_number);
1138 DBG("%s %s (unused property)", m->base.path, prop_name);
1141 static OFono_USSD_State _suppl_serv_state_parse(const char *s)
1143 EINA_SAFETY_ON_NULL_RETURN_VAL(s, OFONO_USSD_STATE_IDLE);
1144 if (strcmp(s, "idle") == 0)
1145 return OFONO_USSD_STATE_IDLE;
1146 else if (strcmp(s, "active") == 0)
1147 return OFONO_USSD_STATE_ACTIVE;
1148 else if (strcmp(s, "user-response") == 0)
1149 return OFONO_USSD_STATE_USER_RESPONSE;
1151 ERR("unknown state: %s", s);
1152 return OFONO_USSD_STATE_IDLE;
1155 static void _suppl_serv_property_update(OFono_Modem *m, const char *prop_name,
1156 Eldbus_Message_Iter *iter)
1159 if (strcmp(prop_name, "State") == 0) {
1161 eldbus_message_iter_basic_get(iter, &s);
1162 m->ussd_state = _suppl_serv_state_parse(s);
1163 DBG("%s USSD.State %d", m->base.path, m->ussd_state);
1165 DBG("%s %s (unused property)", m->base.path, prop_name);
1168 static void _msg_property_update(OFono_Modem *m, const char *prop_name,
1169 Eldbus_Message_Iter *iter)
1172 if (strcmp(prop_name, "ServiceCenterAddress") == 0) {
1174 eldbus_message_iter_arguments_get(iter, "s", &str);
1175 DBG("%s ServiceCenterAddress %s", m->base.path, str);
1176 eina_stringshare_replace(&(m->serv_center_addr), str);
1177 } else if (strcmp(prop_name, "UseDeliveryReports") == 0) {
1179 eldbus_message_iter_arguments_get(iter, "b", &b);
1180 m->use_delivery_reports = b;
1181 DBG("%s UseDeliveryReports %hhu", m->base.path,
1182 m->use_delivery_reports);
1183 } else if (strcmp(prop_name, "Bearer") == 0) {
1185 eldbus_message_iter_arguments_get(iter, "s", &str);
1186 DBG("%s Bearer %s", m->base.path, str);
1187 eina_stringshare_replace(&(m->msg_bearer), str);
1188 } else if (strcmp(prop_name, "Alphabet") == 0) {
1190 eldbus_message_iter_arguments_get(iter, "s", &str);
1191 DBG("%s Alphabet %s", m->base.path, str);
1192 eina_stringshare_replace(&(m->msg_alphabet), str);
1194 DBG("%s %s (unused property)", m->base.path, prop_name);
1197 static void _notify_ofono_callbacks_modem_list(Eina_Inlist *list)
1199 OFono_Callback_List_Modem_Node *node;
1201 EINA_INLIST_FOREACH(list, node)
1202 node->cb((void *) node->cb_data);
1205 static void _call_volume_property_changed(void *data, Eldbus_Message *msg)
1207 OFono_Modem *m = data;
1208 Eldbus_Message_Iter *variant_iter;
1209 const char *prop_name;
1212 ERR("Could not handle message %p", msg);
1216 if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1217 ERR("Could not get volume PropertyChanged arguments");
1221 _call_volume_property_update(m, prop_name, variant_iter);
1223 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1226 static void _msg_waiting_property_changed(void *data, Eldbus_Message *msg)
1228 OFono_Modem *m = data;
1229 Eldbus_Message_Iter *variant_iter;
1230 const char *prop_name;
1233 ERR("Could not handle message %p", msg);
1237 if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1238 ERR("Could not get message waiting PropertyChanged arguments");
1242 _msg_waiting_property_update(m, prop_name, variant_iter);
1244 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1247 static void _suppl_serv_property_changed(void *data, Eldbus_Message *msg)
1249 OFono_Modem *m = data;
1250 Eldbus_Message_Iter *variant_iter;
1251 const char *prop_name;
1254 ERR("Could not handle message %p", msg);
1258 if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1259 ERR("Could not get supplicant service PropertyChanged arguments");
1263 _suppl_serv_property_update(m, prop_name, variant_iter);
1265 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1268 static void _suppl_serv_notification_recv(void *data __UNUSED__,
1269 Eldbus_Message *msg)
1274 ERR("Could not handle message %p", msg);
1278 if (!eldbus_message_arguments_get(msg, "s", &s)) {
1279 ERR("Could not get supplementary respond arguments");
1283 _notify_ofono_callbacks_ussd_notify_list(
1284 cbs_ussd_notify, EINA_FALSE, s);
1287 static void _suppl_serv_request_recv(void *data __UNUSED__, Eldbus_Message *msg)
1292 ERR("Could not handle message %p", msg);
1296 if (!eldbus_message_arguments_get(msg, "s", &s)) {
1297 ERR("Could not get supplementary service request arguments");
1301 _notify_ofono_callbacks_ussd_notify_list(cbs_ussd_notify, EINA_TRUE, s);
1304 static void _msg_property_changed(void *data, Eldbus_Message *msg)
1306 OFono_Modem *m = data;
1307 Eldbus_Message_Iter *variant_iter;
1308 const char *prop_name;
1311 ERR("Could not handle message %p", msg);
1315 if (!eldbus_message_arguments_get(msg, "sv", &prop_name, &variant_iter)) {
1316 ERR("Could not get message PropertyChanged arguments");
1319 _msg_property_update(m, prop_name, variant_iter);
1321 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1324 static OFono_Sent_SMS_State _sent_sms_state_parse(const char *str)
1326 if (strcmp(str, "pending") == 0)
1327 return OFONO_SENT_SMS_STATE_PENDING;
1328 else if (strcmp(str, "failed") == 0)
1329 return OFONO_SENT_SMS_STATE_FAILED;
1330 else if (strcmp(str, "sent") == 0)
1331 return OFONO_SENT_SMS_STATE_SENT;
1333 ERR("unknown message state: %s", str);
1334 return OFONO_SENT_SMS_STATE_FAILED;
1337 static void _sent_sms_property_update(OFono_Sent_SMS *sms, const char *key,
1338 Eldbus_Message_Iter *value)
1340 if (strcmp(key, "State") == 0) {
1342 OFono_Sent_SMS_State state;
1343 eldbus_message_iter_arguments_get(value, "s", &str);;
1344 state = _sent_sms_state_parse(str);
1345 DBG("%s State %d %s", sms->base.path, state, str);
1348 DBG("%s %s (unused property)", sms->base.path, key);
1351 static void _notify_ofono_callbacks_sent_sms(OFono_Error err,
1352 OFono_Sent_SMS *sms)
1354 OFono_Callback_List_Sent_SMS_Node *node;
1356 EINA_INLIST_FOREACH(cbs_sent_sms_changed, node)
1357 node->cb((void *) node->cb_data, err, sms);
1360 static void _sent_sms_property_changed(void *data, Eldbus_Message *msg)
1362 OFono_Sent_SMS *sms = data;
1363 Eldbus_Message_Iter *value;
1367 ERR("Could not handle message %p", msg);
1371 DBG("path=%s", sms->base.path);
1373 if (!eldbus_message_arguments_get(msg, "sv", &key, &value)) {
1374 ERR("Could not get sent sms PropertyChanged arguments");
1378 _sent_sms_property_update(sms, key, value);
1380 _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms);
1383 static void _notify_ofono_callbacks_incoming_sms(unsigned int sms_class,
1386 const char *message)
1388 OFono_Callback_List_Incoming_SMS_Node *node;
1390 EINA_INLIST_FOREACH(cbs_incoming_sms, node) {
1391 node->cb((void *) node->cb_data, sms_class, timestamp, sender,
1396 static void _msg_notify(unsigned int sms_class, Eldbus_Message_Iter *iter)
1398 Eldbus_Message_Iter *info, *dict_entry;
1399 const char *message = NULL;
1400 const char *sender = NULL;
1401 const char *orig_timestamp = NULL;
1402 const char *local_timestamp = NULL;
1405 EINA_SAFETY_ON_NULL_RETURN(iter);
1407 if (!eldbus_message_iter_arguments_get(iter, "sa{sv}", &message, &info)) {
1408 ERR("Could not get message notify arguments");
1412 EINA_SAFETY_ON_NULL_RETURN(message);
1413 DBG("Message '%s'", message);
1415 while (eldbus_message_iter_get_and_next(info, 'e', &dict_entry)) {
1416 Eldbus_Message_Iter *value;
1419 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1420 ERR("Could not get ModemAdded arguments");
1424 if (strcmp(key, "Sender") == 0) {
1425 eldbus_message_iter_basic_get(value, &sender);
1426 DBG("Sender %s", sender);
1427 } else if (strcmp(key, "SentTime") == 0) {
1428 eldbus_message_iter_basic_get(value, &orig_timestamp);
1429 DBG("SentTime %s", orig_timestamp);
1430 } else if (strcmp(key, "LocalSentTime") == 0) {
1431 eldbus_message_iter_basic_get(value, &local_timestamp);
1432 DBG("LocalSentTime %s", local_timestamp);
1434 DBG("%s (unused property)", key);
1437 EINA_SAFETY_ON_NULL_RETURN(sender);
1438 EINA_SAFETY_ON_NULL_RETURN(local_timestamp);
1439 timestamp = _ofono_time_parse(local_timestamp);
1441 _notify_ofono_callbacks_incoming_sms(sms_class, timestamp, sender,
1445 static void _msg_immediate(void *data, Eldbus_Message *msg)
1447 OFono_Modem *m = data;
1448 Eldbus_Message_Iter *iter;
1451 ERR("Could not handle message %p", msg);
1455 iter = eldbus_message_iter_get(msg);
1457 DBG("path=%s", m->base.path);
1458 _msg_notify(0, iter);
1461 static void _msg_incoming(void *data, Eldbus_Message *msg)
1463 OFono_Modem *m = data;
1464 Eldbus_Message_Iter *iter;
1466 iter = eldbus_message_iter_get(msg);
1469 ERR("Could not handle message %p", msg);
1473 DBG("path=%s", m->base.path);
1474 _msg_notify(1, iter);
1477 static OFono_Sent_SMS *_sent_sms_common_add(OFono_Modem *m, const char *path)
1479 OFono_Sent_SMS *sms = _sent_sms_new(path);
1480 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
1481 eina_hash_add(m->sent_sms, sms->base.path, sms);
1483 _bus_object_signal_listen(&sms->base,
1484 OFONO_PREFIX "Message",
1486 _sent_sms_property_changed, sms);
1490 static OFono_Sent_SMS *_sent_sms_pending_add(OFono_Modem *m, const char *path,
1491 OFono_Sent_SMS_Cb_Context *ctx)
1493 OFono_Sent_SMS *sms;
1495 DBG("path=%s, ctx=%p", path, ctx);
1497 sms = _sent_sms_common_add(m, path);
1498 sms->pending_send = ctx;
1502 static void _msg_add(OFono_Modem *m, const char *path, Eldbus_Message_Iter *prop)
1504 Eldbus_Message_Iter *dict_entry;
1505 OFono_Sent_SMS *sms;
1507 DBG("path=%s, prop=%p", path, prop);
1509 sms = eina_hash_find(m->sent_sms, path);
1511 DBG("SMS already exists %p (%s)", sms, path);
1513 sms = _sent_sms_common_add(m, path);
1514 EINA_SAFETY_ON_NULL_RETURN(sms);
1517 while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1518 Eldbus_Message_Iter *value;
1521 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1522 ERR("Could not get arguments");
1526 _sent_sms_property_update(sms, key, value);
1529 if (sms->pending_send) {
1530 OFono_Sent_SMS_Cb_Context *ctx = sms->pending_send;
1531 sms->destination = ctx->destination;
1532 sms->message = ctx->message;
1533 sms->timestamp = time(NULL);
1535 ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, sms);
1537 sms->pending_send = NULL;
1540 _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms);
1543 static void _msg_added(void *data, Eldbus_Message *msg)
1545 OFono_Modem *m = data;
1546 Eldbus_Message_Iter *properties;
1550 ERR("Could not handle message %p", msg);
1554 if (!eldbus_message_arguments_get(msg, "oa{sv}", &path, &properties)) {
1555 ERR("Could not get MessageAdded arguments");
1559 _msg_add(m, path, properties);
1562 static void _msg_remove(OFono_Modem *m, const char *path)
1564 DBG("path=%s", path);
1565 eina_hash_del_by_key(m->sent_sms, path);
1568 static void _msg_removed(void *data, Eldbus_Message *msg)
1570 OFono_Modem *m = data;
1574 ERR("Could not handle message %p", msg);
1578 if (!eldbus_message_arguments_get(msg, "o", &path)) {
1579 ERR("Could not get MessageRemoved arguments");
1583 _msg_remove(m, path);
1586 static unsigned int _modem_interfaces_extract(Eldbus_Message_Iter *iter)
1588 Eldbus_Message_Iter *array;
1590 unsigned int interfaces = 0;
1592 if (!eldbus_message_iter_arguments_get(iter, "as", &array)) {
1593 ERR("Could not get modem interfaces arguments");
1597 while (eldbus_message_iter_get_and_next(array, 's', &name)) {
1598 const struct API_Interface_Map *itr;
1601 if (strncmp(name, OFONO_PREFIX, strlen(OFONO_PREFIX)) != 0)
1604 name += strlen(OFONO_PREFIX);
1605 namelen = strlen(name);
1607 DBG("interface: %s", name);
1608 for (itr = api_iface_map; itr->name != NULL; itr++) {
1609 if ((itr->namelen == namelen) &&
1610 (memcmp(itr->name, name, namelen) == 0)) {
1611 interfaces |= itr->bit;
1615 if (itr->name == NULL)
1616 WRN("ignored %s", name);
1622 static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces)
1625 if (((m->interfaces & OFONO_API_CALL_VOL) == 0) &&
1626 (ifaces & OFONO_API_CALL_VOL) == OFONO_API_CALL_VOL)
1627 _ofono_call_volume_properties_get(m);
1629 if (((m->interfaces & OFONO_API_MSG_WAITING) == 0) &&
1630 (ifaces & OFONO_API_MSG_WAITING) == OFONO_API_MSG_WAITING)
1631 _ofono_msg_waiting_properties_get(m);
1633 if (((m->interfaces & OFONO_API_SUPPL_SERV) == 0) &&
1634 (ifaces & OFONO_API_SUPPL_SERV) == OFONO_API_SUPPL_SERV)
1635 _ofono_suppl_serv_properties_get(m);
1637 if (((m->interfaces & OFONO_API_MSG) == 0) &&
1638 (ifaces & OFONO_API_MSG) == OFONO_API_MSG)
1639 _ofono_msg_properties_get(m);
1642 static void _modem_property_update(OFono_Modem *m, const char *key,
1643 Eldbus_Message_Iter *value)
1645 if (strcmp(key, "Powered") == 0) {
1647 eldbus_message_iter_basic_get(value, &b);
1649 DBG("%s Powered %d", m->base.path, m->powered);
1650 } else if (strcmp(key, "Online") == 0) {
1652 eldbus_message_iter_basic_get(value, &b);
1654 DBG("%s Online %d", m->base.path, m->online);
1655 } else if (strcmp(key, "Interfaces") == 0) {
1656 unsigned int ifaces = _modem_interfaces_extract(value);
1657 DBG("%s Interfaces 0x%02x", m->base.path, ifaces);
1658 if (m->interfaces != ifaces) {
1659 _modem_update_interfaces(m, ifaces);
1660 m->interfaces = ifaces;
1662 if (modem_selected && modem_path_wanted &&
1663 modem_selected->base.path != modem_path_wanted)
1664 modem_selected = NULL;
1666 } else if (strcmp(key, "Serial") == 0) {
1668 eldbus_message_iter_basic_get(value, &serial);
1669 DBG("%s Serial %s", m->base.path, serial);
1670 eina_stringshare_replace(&m->serial, serial);
1671 } else if (strcmp(key, "Type") == 0) {
1673 eldbus_message_iter_basic_get(value, &type);
1674 DBG("%s Type %s", m->base.path, type);
1677 m->ignored = EINA_FALSE;
1681 m->ignored = EINA_TRUE;
1682 EINA_LIST_FOREACH(modem_types, n, t) {
1683 if (strcmp(t, type) == 0) {
1684 m->ignored = EINA_FALSE;
1689 INF("Modem %s type %s is ignored",
1690 m->base.path, type);
1693 DBG("%s %s (unused property)", m->base.path, key);
1696 static void _ofono_call_volume_properties_get_reply(void *data,
1697 Eldbus_Message *msg,
1698 Eldbus_Pending *pending __UNUSED__)
1700 OFono_Modem *m = data;
1701 Eldbus_Message_Iter *prop, *dict_entry;
1702 const char *err_name, *err_message;
1709 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1710 ERR("Call volume reply error %s: %s", err_name, err_message);
1714 if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1715 ERR("Could not get call volume arguments");
1719 DBG("m=%s", m->base.path);
1720 while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1721 Eldbus_Message_Iter *value;
1724 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1725 ERR("Could not get arguments");
1728 _call_volume_property_update(m, key, value);
1731 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1734 static void _ofono_call_volume_properties_get(OFono_Modem *m)
1736 Eldbus_Message *msg;
1737 msg = eldbus_message_method_call_new(bus_id, m->base.path,
1739 OFONO_CALL_VOL_IFACE,
1741 DBG("m=%s", m->base.path);
1742 EINA_SAFETY_ON_NULL_RETURN(msg);
1744 _bus_object_message_send(&m->base, msg,
1745 _ofono_call_volume_properties_get_reply, m);
1748 static void _ofono_msg_waiting_properties_get_reply(void *data,
1749 Eldbus_Message *msg,
1750 Eldbus_Pending *pending __UNUSED__)
1752 OFono_Modem *m = data;
1753 Eldbus_Message_Iter *prop, *dict_entry;
1754 const char *err_name, *err_message;
1761 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1762 ERR("Ofono reply error %s: %s", err_name, err_message);
1766 if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1767 ERR("Could not get message waiting properties arguments");
1771 DBG("m=%s", m->base.path);
1772 while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1773 Eldbus_Message_Iter *value;
1776 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1777 ERR("Could not get arguments");
1780 _msg_waiting_property_update(m, key, value);
1783 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1786 static void _ofono_msg_waiting_properties_get(OFono_Modem *m)
1788 Eldbus_Message *msg;
1789 msg = eldbus_message_method_call_new(bus_id, m->base.path,
1791 OFONO_MSG_WAITING_IFACE,
1793 DBG("m=%s", m->base.path);
1794 EINA_SAFETY_ON_NULL_RETURN(msg);
1796 _bus_object_message_send(&m->base, msg,
1797 _ofono_msg_waiting_properties_get_reply, m);
1800 static void _ofono_suppl_serv_properties_get_reply(void *data,
1801 Eldbus_Message *msg,
1802 Eldbus_Pending *pending __UNUSED__)
1804 OFono_Modem *m = data;
1805 Eldbus_Message_Iter *prop, *dict_entry;
1806 const char *err_name, *err_message;
1813 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1814 ERR("SS service properties reply error %s: %s", err_name, err_message);
1818 if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1819 ERR("Could not get supplementary service properties arguments");
1823 DBG("m=%s", m->base.path);
1824 while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1825 Eldbus_Message_Iter *value;
1828 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1829 ERR("Could not get arguments");
1832 _suppl_serv_property_update(m, key, value);
1835 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1838 static void _ofono_suppl_serv_properties_get(OFono_Modem *m)
1840 Eldbus_Message *msg;
1841 msg = eldbus_message_method_call_new(bus_id, m->base.path,
1843 OFONO_SUPPL_SERV_IFACE,
1845 DBG("m=%s", m->base.path);
1846 EINA_SAFETY_ON_NULL_RETURN(msg);
1848 _bus_object_message_send(&m->base, msg,
1849 _ofono_suppl_serv_properties_get_reply, m);
1853 static void _ofono_msg_properties_get_reply(void *data, Eldbus_Message *msg,
1854 Eldbus_Pending *pending __UNUSED__)
1856 OFono_Modem *m = data;
1857 Eldbus_Message_Iter *prop, *dict_entry;
1858 const char *err_name, *err_message;
1865 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
1866 ERR("Message properties reply error %s: %s", err_name, err_message);
1870 if (!eldbus_message_arguments_get(msg, "a{sv}", &prop)) {
1871 ERR("Could not get message properties arguments");
1875 DBG("m=%s", m->base.path);
1876 while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1877 Eldbus_Message_Iter *value;
1880 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1881 ERR("Could not get arguments");
1884 _msg_property_update(m, key, value);
1887 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1890 static void _ofono_msg_properties_get(OFono_Modem *m)
1892 Eldbus_Message *msg;
1893 msg = eldbus_message_method_call_new(bus_id, m->base.path,
1897 DBG("m=%s", m->base.path);
1898 EINA_SAFETY_ON_NULL_RETURN(msg);
1900 _bus_object_message_send(&m->base, msg,
1901 _ofono_msg_properties_get_reply, m);
1904 static void _modem_add(const char *path, Eldbus_Message_Iter *prop)
1907 Eldbus_Message_Iter *dict_entry;
1909 DBG("path=%s", path);
1911 m = eina_hash_find(modems, path);
1913 DBG("Modem already exists %p (%s)", m, path);
1914 goto update_properties;
1917 m = _modem_new(path);
1918 EINA_SAFETY_ON_NULL_RETURN(m);
1919 eina_hash_add(modems, m->base.path, m);
1921 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1922 "CallAdded", _call_added, m);
1923 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_VOICE_IFACE,
1924 "CallRemoved", _call_removed, m);
1925 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_CALL_VOL_IFACE,
1927 _call_volume_property_changed, m);
1928 _bus_object_signal_listen(&m->base,
1929 OFONO_PREFIX OFONO_MSG_WAITING_IFACE,
1931 _msg_waiting_property_changed, m);
1932 _bus_object_signal_listen(&m->base,
1933 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1935 _suppl_serv_property_changed, m);
1936 _bus_object_signal_listen(&m->base,
1937 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1938 "NotificationReceived",
1939 _suppl_serv_notification_recv, m);
1940 _bus_object_signal_listen(&m->base,
1941 OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
1943 _suppl_serv_request_recv, m);
1945 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1947 _msg_property_changed, m);
1948 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1949 "ImmediateMessage", _msg_immediate, m);
1950 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1951 "IncomingMessage", _msg_incoming, m);
1952 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1953 "MessageAdded", _msg_added, m);
1954 _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE,
1955 "MessageRemoved", _msg_removed, m);
1957 /* TODO: do we need to listen to BarringActive or Forwarded? */
1959 if (modem_selected && modem_path_wanted &&
1960 modem_selected->base.path != modem_path_wanted)
1961 modem_selected = NULL;
1966 while (eldbus_message_iter_get_and_next(prop, 'e', &dict_entry)) {
1967 Eldbus_Message_Iter *value;
1970 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
1971 ERR("Could not get ModemAdded arguments");
1975 _modem_property_update(m, key, value);
1978 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
1980 if (m->interfaces & OFONO_API_VOICE)
1981 _modem_calls_load(m);
1984 static void _modem_remove(const char *path)
1986 DBG("path=%s", path);
1987 eina_hash_del_by_key(modems, path);
1990 static void _ofono_modems_get_reply(void *data __UNUSED__, Eldbus_Message *msg,
1991 Eldbus_Pending *pending __UNUSED__)
1993 Eldbus_Message_Iter *array, *dict_entry;
1994 const char *err_name, *err_message;
1996 pc_get_modems = NULL;
2003 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
2004 ERR("Failed to get modems: %s: %s", err_name, err_message);
2008 EINA_SAFETY_ON_NULL_RETURN(modems);
2009 eina_hash_free_buckets(modems);
2011 if (!eldbus_message_arguments_get(msg, "a(oa{sv})", &array)) {
2012 ERR("Could not get modems");
2016 while (eldbus_message_iter_get_and_next(array, 'r', &dict_entry)) {
2017 Eldbus_Message_Iter *properties;
2020 if (!eldbus_message_iter_arguments_get(dict_entry, "oa{sv}", &path, &properties)) {
2021 ERR("Could not get ModemAdded arguments");
2025 _modem_add(path, properties);
2028 if (!ofono_voice_is_online()) {
2029 ofono_powered_set(EINA_TRUE, NULL, NULL);
2034 static void _modem_added(void *data __UNUSED__, Eldbus_Message *msg)
2036 Eldbus_Message_Iter *properties;
2040 ERR("Could not handle message %p", msg);
2044 if (!eldbus_message_arguments_get(msg, "sa{sv}", &path, &properties)) {
2045 ERR("Could not get ModemAdded arguments");
2049 _modem_add(path, properties);
2052 static void _modem_removed(void *data __UNUSED__, Eldbus_Message *msg)
2057 ERR("Could not handle message %p", msg);
2061 if (!eldbus_message_arguments_get(msg, "o", &path)) {
2062 ERR("Could not get ModemRemoved arguments");
2066 _modem_remove(path);
2069 static void _modem_property_changed(void *data __UNUSED__, Eldbus_Message *msg)
2073 Eldbus_Message_Iter *value;
2077 ERR("Could not handle message %p", msg);
2081 path = eldbus_message_path_get(msg);
2082 DBG("path=%s", path);
2084 m = eina_hash_find(modems, path);
2086 DBG("Modem is unknown (%s)", path);
2090 if (!eldbus_message_arguments_get(msg, "sv", &key, &value)) {
2091 ERR("Could not get modem PropertyChanged arguments");
2095 _modem_property_update(m, key, value);
2097 _notify_ofono_callbacks_modem_list(cbs_modem_changed);
2100 static void _modems_load(void)
2102 Eldbus_Message *msg = eldbus_message_method_call_new(
2103 bus_id, "/", OFONO_PREFIX OFONO_MANAGER_IFACE, "GetModems");
2106 eldbus_pending_cancel(pc_get_modems);
2109 pc_get_modems = eldbus_connection_send(
2110 bus_conn, msg, _ofono_modems_get_reply, NULL, -1);
2113 static void _ofono_connected(const char *id)
2116 bus_id = strdup(id);
2118 sig_modem_added = eldbus_signal_handler_add(
2119 bus_conn, bus_id, "/",
2120 OFONO_PREFIX OFONO_MANAGER_IFACE,
2122 _modem_added, NULL);
2124 sig_modem_removed = eldbus_signal_handler_add(
2125 bus_conn, bus_id, "/",
2126 OFONO_PREFIX OFONO_MANAGER_IFACE,
2128 _modem_removed, NULL);
2130 sig_modem_prop_changed = eldbus_signal_handler_add(
2131 bus_conn, bus_id, NULL,
2132 OFONO_PREFIX OFONO_MODEM_IFACE,
2134 _modem_property_changed, NULL);
2138 _notify_ofono_callbacks_modem_list(cbs_modem_connected);
2141 static void _ofono_disconnected(void)
2143 eina_hash_free_buckets(modems);
2145 if (sig_modem_added) {
2146 eldbus_signal_handler_del(sig_modem_added);
2147 sig_modem_added = NULL;
2150 if (sig_modem_removed) {
2151 eldbus_signal_handler_del(sig_modem_removed);
2152 sig_modem_removed = NULL;
2155 if (sig_modem_prop_changed) {
2156 eldbus_signal_handler_del(sig_modem_prop_changed);
2157 sig_modem_prop_changed = NULL;
2161 _notify_ofono_callbacks_modem_list(cbs_modem_disconnected);
2167 static void _name_owner_changed(void *data __UNUSED__, Eldbus_Message *msg)
2169 const char *name, *from, *to;
2171 if (!eldbus_message_arguments_get(msg, "sss", &name, &from, &to)) {
2172 ERR("Could not get NameOwnerChanged arguments");
2176 if (strcmp(name, bus_name) != 0)
2179 DBG("NameOwnerChanged %s from=%s to=%s", name, from, to);
2181 if (from[0] == '\0' && to[0] != '\0') {
2182 INF("oFono appeared as %s", to);
2183 _ofono_connected(to);
2184 } else if (from[0] != '\0' && to[0] == '\0') {
2185 INF("oFono disappeared from %s", from);
2186 _ofono_disconnected();
2190 static void _ofono_get_name_owner(void *data __UNUSED__, Eldbus_Message *msg,
2191 Eldbus_Pending *pending __UNUSED__)
2193 const char *id, *err_name, *err_message;
2200 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
2201 ERR("Failed to get name owner: %s: %s", err_name, err_message);
2205 if (!eldbus_message_arguments_get(msg, "s", &id)) {
2206 ERR("Could not get arguments");
2210 if (!id || id[0] == '\0') {
2211 ERR("No name owner fo %s!", bus_name);
2215 INF("oFono bus id: %s", id);
2216 _ofono_connected(id);
2219 OFono_Pending *ofono_modem_change_pin(const char *what, const char *old,
2220 const char *new, OFono_Simple_Cb cb,
2223 OFono_Simple_Cb_Context *ctx = NULL;
2224 OFono_Error err = OFONO_ERROR_OFFLINE;
2226 Eldbus_Message *msg;
2227 OFono_Modem *m = _modem_selected_get();
2228 EINA_SAFETY_ON_NULL_GOTO(m, error);
2229 EINA_SAFETY_ON_NULL_GOTO(what, error);
2230 EINA_SAFETY_ON_NULL_GOTO(old, error);
2231 EINA_SAFETY_ON_NULL_GOTO(new, error);
2233 if ((m->interfaces & OFONO_API_SIM) == 0)
2235 err = OFONO_ERROR_FAILED;
2238 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2239 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2244 msg = eldbus_message_method_call_new(
2245 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE,
2250 if (!eldbus_message_arguments_append(msg, "sss", what, old, new))
2253 INF("ChangePin(%s, %s, %s)", what, old, new);
2254 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2258 eldbus_message_unref(msg);
2261 cb((void *)data, err);
2266 OFono_Pending *ofono_modem_reset_pin(const char *what, const char *puk,
2267 const char *new, OFono_Simple_Cb cb,
2270 OFono_Simple_Cb_Context *ctx = NULL;
2271 OFono_Error err = OFONO_ERROR_OFFLINE;
2273 Eldbus_Message *msg;
2274 OFono_Modem *m = _modem_selected_get();
2275 EINA_SAFETY_ON_NULL_GOTO(m, error);
2276 EINA_SAFETY_ON_NULL_GOTO(what, error);
2277 EINA_SAFETY_ON_NULL_GOTO(puk, error);
2278 EINA_SAFETY_ON_NULL_GOTO(new, error);
2280 if ((m->interfaces & OFONO_API_SIM) == 0)
2282 err = OFONO_ERROR_FAILED;
2285 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2286 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2291 msg = eldbus_message_method_call_new(
2292 bus_id, m->base.path, OFONO_PREFIX OFONO_SIM_IFACE, "ResetPin");
2296 if (!eldbus_message_arguments_append(msg, "sss", what, puk, new))
2299 INF("ResetPin(%s, %s, %s)", what, puk, new);
2300 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2304 eldbus_message_unref(msg);
2307 cb((void *)data, err);
2312 static OFono_Pending *_ofono_modem_property_set(const char *property,
2319 OFono_Simple_Cb_Context *ctx = NULL;
2320 Eldbus_Message *msg;
2321 Eldbus_Message_Iter *iter, *variant;
2322 OFono_Modem *found_path = NULL, *found_hfp = NULL, *m;
2328 itr = eina_hash_iterator_data_new(modems);
2329 EINA_ITERATOR_FOREACH(itr, m) {
2333 if ((modem_path_wanted) && (!found_path)) {
2334 DBG("m=%s, wanted=%s", m->base.path, modem_path_wanted);
2335 if (m->base.path == modem_path_wanted) {
2342 DBG("m=%#x, mask=%#x, previous=%s "
2343 "(online=%d, powered=%d)",
2344 m->interfaces, modem_api_mask,
2345 found_hfp ? found_hfp->base.path : "",
2346 found_hfp ? found_hfp->online : 0,
2347 found_hfp ? found_hfp->powered : 0);
2348 if (strncmp(m->base.path, "/hfp", 4) == 0)
2352 eina_iterator_free(itr);
2353 m = found_path ? found_path : found_hfp;
2359 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
2362 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2363 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
2368 msg = eldbus_message_method_call_new(bus_id, m->base.path,
2369 OFONO_PREFIX OFONO_MODEM_IFACE,
2372 goto error_no_dbus_message;
2374 if (!eldbus_message_arguments_append(msg, "s", property))
2375 goto error_message_args;
2377 iter = eldbus_message_iter_get(msg);
2379 variant = eldbus_message_iter_container_new(iter, 'v', (const char*) &type);
2382 goto error_message_args;
2384 if (strcmp(property, "Powered") == 0) {
2385 if (!eldbus_message_iter_basic_append(variant, type, *(Eina_Bool *) value) ||
2386 !eldbus_message_iter_container_close(iter, variant)) {
2387 goto error_message_args;
2390 ERR("Unsupported property: %s", property);
2393 INF("%s.SetProperty(%s)", OFONO_MODEM_IFACE, property);
2394 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2398 eldbus_message_unref(msg);
2400 error_no_dbus_message:
2402 cb((void *)data, OFONO_ERROR_FAILED);
2407 OFono_Pending *ofono_powered_set(Eina_Bool powered, OFono_Simple_Cb cb,
2410 Eina_Bool dbus_powered = !!powered;
2412 return _ofono_modem_property_set("Powered", 'b',
2413 &dbus_powered, cb, data);
2416 Eina_Bool ofono_powered_get(void)
2418 OFono_Modem *m = _modem_selected_get();
2419 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
2423 static char *_ss_initiate_convert_ussd(const char *type __UNUSED__,
2424 Eldbus_Message_Iter *itr)
2426 const char *ussd_response;
2428 eldbus_message_iter_basic_get(itr, &ussd_response);
2429 EINA_SAFETY_ON_NULL_RETURN_VAL(ussd_response, NULL);
2430 return strdup(ussd_response);
2433 static void _ss_initiate_cb_dict_convert(Eina_Strbuf *buf,
2434 Eldbus_Message_Iter *dict)
2436 Eldbus_Message_Iter *dict_entry;
2438 while (eldbus_message_iter_get_and_next(dict, 'e', &dict_entry)) {
2439 Eldbus_Message_Iter *value;
2442 if (!eldbus_message_iter_arguments_get(dict_entry, "sv", &key, &value)) {
2443 ERR("Could not get ss init dictionary arguments");
2447 eina_strbuf_append_printf(buf, " %s=%s<br>",
2452 static char *_ss_initiate_convert_call1(const char *type, Eldbus_Message_Iter *itr)
2454 Eldbus_Message_Iter *array, *dict, *entry;
2455 const char *ss_op, *service;
2459 if (!eldbus_message_iter_arguments_get(itr, "(ssa{sv})", &array)) {
2460 ERR("Could not get call1 array");
2464 if (!eldbus_message_iter_arguments_get(array, "ssa{sv}", &ss_op, &service, &dict)) {
2465 ERR("Could not get call1 arguments");
2469 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2470 EINA_SAFETY_ON_NULL_RETURN_VAL(service, NULL);
2472 if (!eldbus_message_iter_get_and_next(array, 'e', &entry)){
2473 ERR("Missing %s information", type);
2477 buf = eina_strbuf_new();
2478 eina_strbuf_append_printf(buf, "<b>%s %s=%s</b><br><br>",
2479 type, ss_op, service);
2481 _ss_initiate_cb_dict_convert(buf, &dict);
2483 str = eina_strbuf_string_steal(buf);
2484 eina_strbuf_free(buf);
2488 static char *_ss_initiate_convert_call_waiting(const char *type,
2489 Eldbus_Message_Iter *itr)
2491 Eldbus_Message_Iter *array, *dict;
2496 if (!eldbus_message_iter_arguments_get(itr, "(sa{sv})", &array)) {
2497 ERR("Could not get call waiting array");
2501 if (!eldbus_message_iter_arguments_get(array, "sa{sv}", &ss_op, &dict)) {
2502 ERR("Could not get CallWaiting arguments");
2506 EINA_SAFETY_ON_NULL_RETURN_VAL(ss_op, NULL);
2508 buf = eina_strbuf_new();
2509 eina_strbuf_append_printf(buf, "<b>%s %s</b><br><br>",
2512 _ss_initiate_cb_dict_convert(buf, &dict);
2514 str = eina_strbuf_string_steal(buf);
2515 eina_strbuf_free(buf);
2519 static char *_ss_initiate_convert_call2(const char *type,
2520 Eldbus_Message_Iter *itr)
2522 Eldbus_Message_Iter *array;
2523 const char *ss_op, *status;
2527 if (!eldbus_message_iter_arguments_get(itr, "(ss)", &array)) {
2528 ERR("Could not get call2 array");
2532 if (!eldbus_message_iter_arguments_get(array, "ss", &ss_op, &status)) {
2533 ERR("Could not get call2 arguments");
2537 EINA_SAFETY_ON_NULL_RETURN_VAL(status, NULL);
2539 buf = eina_strbuf_new();
2540 eina_strbuf_append_printf(buf, "<b>%s:</b><br><br>%s=%s",
2541 type, ss_op, status);
2543 str = eina_strbuf_string_steal(buf);
2544 eina_strbuf_free(buf);
2548 static const struct SS_Initiate_Convert_Map {
2551 char *(*convert)(const char *type, Eldbus_Message_Iter *itr);
2552 } ss_initiate_convert_map[] = {
2553 #define MAP(type, conv) {type, sizeof(type) - 1, conv}
2554 MAP("USSD", _ss_initiate_convert_ussd),
2555 MAP("CallBarring", _ss_initiate_convert_call1),
2556 MAP("CallForwarding", _ss_initiate_convert_call1),
2557 MAP("CallWaiting", _ss_initiate_convert_call_waiting),
2558 MAP("CallingLinePresentation", _ss_initiate_convert_call2),
2559 MAP("ConnectedLinePresentation", _ss_initiate_convert_call2),
2560 MAP("CallingLineRestriction", _ss_initiate_convert_call2),
2561 MAP("ConnectedLineRestriction", _ss_initiate_convert_call2),
2566 static char *_ss_initiate_convert(Eldbus_Message *msg)
2568 Eldbus_Message_Iter *variant;
2569 const struct SS_Initiate_Convert_Map *citr;
2570 const char *type = NULL;
2573 if (!eldbus_message_arguments_get(msg, "sv", &type, &variant)) {
2574 ERR("Couldn't get supplementary service nitiate arguments");
2577 DBG("SupplementaryServices.Initiate type: %s", type);
2579 typelen = strlen(type);
2580 for (citr = ss_initiate_convert_map; citr->type != NULL; citr++) {
2581 if ((citr->typelen == typelen) &&
2582 (memcmp(citr->type, type, typelen) == 0)) {
2583 return citr->convert(type, &variant);
2586 ERR("Could not convert SupplementaryServices.Initiate type %s", type);
2592 OFono_Pending *ofono_ss_initiate(const char *command, OFono_String_Cb cb, const void *data)
2594 OFono_String_Cb_Context *ctx = NULL;
2595 OFono_Error err = OFONO_ERROR_OFFLINE;
2597 Eldbus_Message *msg;
2598 OFono_Modem *m = _modem_selected_get();
2599 EINA_SAFETY_ON_NULL_GOTO(m, error);
2600 EINA_SAFETY_ON_NULL_GOTO(command, error);
2602 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2604 err = OFONO_ERROR_FAILED;
2606 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2607 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2610 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2611 ctx->convert = _ss_initiate_convert;
2613 msg = eldbus_message_method_call_new(
2614 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2619 if (!eldbus_message_arguments_append(msg, "s", command))
2622 INF("SupplementaryServices.Initiate(%s)", command);
2623 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2627 eldbus_message_unref(msg);
2630 cb((void *)data, err, NULL);
2635 static char *_ussd_respond_convert(Eldbus_Message *msg)
2640 ERR("Could not handle message %p", msg);
2644 if (!eldbus_message_arguments_get(msg, "s", &s)) {
2645 ERR("Could not get ussd respond arguments");
2649 EINA_SAFETY_ON_NULL_RETURN_VAL(s, NULL);
2653 OFono_Pending *ofono_ussd_respond(const char *string,
2654 OFono_String_Cb cb, const void *data)
2656 OFono_String_Cb_Context *ctx = NULL;
2657 OFono_Error err = OFONO_ERROR_OFFLINE;
2659 Eldbus_Message *msg;
2660 OFono_Modem *m = _modem_selected_get();
2661 EINA_SAFETY_ON_NULL_GOTO(m, error);
2662 EINA_SAFETY_ON_NULL_GOTO(string, error);
2664 if ((m->interfaces & OFONO_API_SUPPL_SERV) == 0)
2666 err = OFONO_ERROR_FAILED;
2668 ctx = calloc(1, sizeof(OFono_String_Cb_Context));
2669 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2672 ctx->name = OFONO_PREFIX OFONO_SUPPL_SERV_IFACE ".Initiate";
2673 ctx->convert = _ussd_respond_convert;
2675 msg = eldbus_message_method_call_new(
2676 bus_id, m->base.path, OFONO_PREFIX OFONO_SUPPL_SERV_IFACE,
2681 if (!eldbus_message_arguments_append(msg, "s", string))
2684 INF("SupplementaryServices.Respond(%s)", string);
2685 p = _bus_object_message_send(&m->base, msg, _ofono_string_reply, ctx);
2689 eldbus_message_unref(msg);
2692 cb((void *)data, err, NULL);
2697 OFono_Pending *ofono_ussd_cancel(OFono_Simple_Cb cb, const void *data)
2699 return _ofono_simple_do(OFONO_API_SUPPL_SERV, "Cancel", cb, data);
2702 static void _ofono_dial_reply(void *data, Eldbus_Message *msg,
2703 Eldbus_Pending *pending __UNUSED__)
2705 OFono_Call_Cb_Context *ctx = data;
2706 OFono_Call *c = NULL;
2707 OFono_Error oe = OFONO_ERROR_NONE;
2708 const char *err_name, *err_message;
2710 EINA_SAFETY_ON_NULL_RETURN(data);
2714 oe = OFONO_ERROR_FAILED;
2717 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
2718 ERR("Ofono reply error %s: %s", err_name, err_message);
2719 oe = _ofono_error_parse(err_name);
2722 if (!eldbus_message_arguments_get(msg, "o", &path)) {
2723 ERR("Could not get Dial reply");
2724 oe = OFONO_ERROR_FAILED;
2726 c = eina_hash_find(ctx->modem->calls, path);
2727 DBG("path=%s, existing call=%p", path, c);
2729 c = _call_pending_add(ctx->modem, path, ctx);
2731 /* ctx->cb will be dispatched on
2732 * CallAdded signal handler.
2738 ERR("Could not find call %s", path);
2739 oe = OFONO_ERROR_FAILED;
2744 ctx->cb((void *)ctx->data, oe, c);
2749 OFono_Pending *ofono_dial(const char *number, const char *hide_callerid,
2750 OFono_Call_Cb cb, const void *data)
2752 OFono_Call_Cb_Context *ctx = NULL;
2753 OFono_Error err = OFONO_ERROR_OFFLINE;
2755 Eldbus_Message *msg;
2756 OFono_Modem *m = _modem_selected_get();
2757 EINA_SAFETY_ON_NULL_GOTO(m, error);
2760 if ((m->interfaces & OFONO_API_VOICE) == 0)
2762 err = OFONO_ERROR_FAILED;
2767 ctx = calloc(1, sizeof(OFono_Call_Cb_Context));
2768 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2771 ctx->name = OFONO_PREFIX OFONO_VOICE_IFACE ".Dial";
2774 msg = eldbus_message_method_call_new(
2775 bus_id, m->base.path, OFONO_PREFIX OFONO_VOICE_IFACE, "Dial");
2779 if (!eldbus_message_arguments_append(msg, "ss", number, hide_callerid))
2782 INF("Dial(%s, %s)", number, hide_callerid);
2783 p = _bus_object_message_send(&m->base, msg, _ofono_dial_reply, ctx);
2787 eldbus_message_unref(msg);
2790 cb((void *)data, err, NULL);
2795 static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method,
2796 OFono_Simple_Cb cb, const void *data)
2798 OFono_Simple_Cb_Context *ctx = NULL;
2799 OFono_Error err = OFONO_ERROR_OFFLINE;
2801 Eldbus_Message *msg;
2802 char iface[128] = "";
2803 const struct API_Interface_Map *itr;
2804 OFono_Modem *m = _modem_selected_get();
2805 EINA_SAFETY_ON_NULL_GOTO(m, error);
2806 EINA_SAFETY_ON_NULL_GOTO(method, error);
2808 if ((m->interfaces & api) == 0)
2810 err = OFONO_ERROR_FAILED;
2812 for (itr = api_iface_map; itr->name != NULL; itr++) {
2813 if (itr->bit == api) {
2814 snprintf(iface, sizeof(iface), "%s%s",
2815 OFONO_PREFIX, itr->name);
2819 if (iface[0] == '\0') {
2820 ERR("Could not map api %d to interface name!", api);
2825 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
2826 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
2831 msg = eldbus_message_method_call_new(bus_id, m->base.path, iface, method);
2835 INF("%s.%s()", iface, method);
2836 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
2841 cb((void *)data, err);
2846 OFono_Pending *ofono_transfer(OFono_Simple_Cb cb, const void *data)
2848 return _ofono_simple_do(OFONO_API_VOICE, "Transfer", cb, data);
2851 OFono_Pending *ofono_swap_calls(OFono_Simple_Cb cb, const void *data)
2853 return _ofono_simple_do(OFONO_API_VOICE, "SwapCalls", cb, data);
2856 OFono_Pending *ofono_release_and_answer(OFono_Simple_Cb cb, const void *data)
2858 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndAnswer", cb, data);
2861 OFono_Pending *ofono_release_and_swap(OFono_Simple_Cb cb, const void *data)
2863 return _ofono_simple_do(OFONO_API_VOICE, "ReleaseAndSwap", cb, data);
2866 OFono_Pending *ofono_hold_and_answer(OFono_Simple_Cb cb, const void *data)
2868 return _ofono_simple_do(OFONO_API_VOICE, "HoldAndAnswer", cb, data);
2871 OFono_Pending *ofono_hangup_all(OFono_Simple_Cb cb, const void *data)
2873 return _ofono_simple_do(OFONO_API_VOICE, "HangupAll", cb, data);
2876 const char *ofono_modem_serial_get(void)
2878 OFono_Modem *m = _modem_selected_get();
2879 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
2883 void ofono_modem_api_require(const char *spec)
2885 unsigned int api_mask = 0;
2886 const char *name = spec;
2888 EINA_SAFETY_ON_NULL_RETURN(spec);
2891 const struct API_Interface_Map *itr;
2893 unsigned int namelen;
2895 p = strchr(name, ',');
2899 namelen = strlen(name);
2901 for (itr = api_iface_map; itr->name != NULL; itr++) {
2902 if ((itr->namelen == namelen) &&
2903 (memcmp(itr->name, name, namelen) == 0)) {
2904 api_mask |= itr->bit;
2908 if (itr->name == NULL)
2909 WRN("Unknown oFono API: %.*s", namelen, name);
2918 DBG("API parsed: '%s' = %#x", spec, api_mask);
2920 ERR("Could not parse API: %s", spec);
2924 if (modem_api_mask == api_mask)
2926 modem_api_mask = api_mask;
2927 modem_selected = NULL;
2930 void ofono_modem_api_list(FILE *fp, const char *prefix, const char *suffix)
2932 const struct API_Interface_Map *itr;
2933 for (itr = api_iface_map; itr->name != NULL; itr++)
2934 fprintf(fp, "%s%s%s", prefix, itr->name, suffix);
2937 void ofono_modem_type_require(const char *spec)
2939 Eina_List *lst = NULL;
2940 const char *name = spec;
2942 EINA_SAFETY_ON_NULL_RETURN(spec);
2947 unsigned int namelen;
2949 p = strchr(name, ',');
2953 namelen = strlen(name);
2955 for (itr = known_modem_types; *itr != NULL; itr++) {
2956 unsigned int itrlen = strlen(*itr);
2957 if ((itrlen == namelen) &&
2958 (memcmp(*itr, name, namelen) == 0)) {
2959 lst = eina_list_append(lst, *itr);
2964 WRN("Unknown oFono type: %.*s", namelen, name);
2973 DBG("Type parsed: '%s'", spec);
2975 ERR("Could not parse type: %s", spec);
2979 eina_list_free(modem_types);
2981 modem_selected = NULL;
2984 void ofono_modem_type_list(FILE *fp, const char *prefix, const char *suffix)
2987 for (itr = known_modem_types; *itr != NULL; itr++)
2988 fprintf(fp, "%s%s%s", prefix, *itr, suffix);
2991 void ofono_modem_path_wanted_set(const char *path)
2993 if (eina_stringshare_replace(&modem_path_wanted, path))
2994 modem_selected = NULL;
2997 unsigned int ofono_modem_api_get(void)
2999 OFono_Modem *m = _modem_selected_get();
3000 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3001 return m->interfaces;
3004 Eina_Bool ofono_init(void)
3008 if (!elm_need_eldbus()) {
3009 CRITICAL("Elementary does not support DBus.");
3013 bus_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
3015 CRITICAL("Could not get DBus System Bus");
3019 modems = eina_hash_string_small_new(EINA_FREE_CB(_modem_free));
3020 EINA_SAFETY_ON_NULL_RETURN_VAL(modems, EINA_FALSE);
3022 eldbus_signal_handler_add(bus_conn, ELDBUS_FDO_BUS, ELDBUS_FDO_PATH,
3023 ELDBUS_FDO_INTERFACE,
3025 _name_owner_changed, NULL);
3027 eldbus_name_owner_get(bus_conn, bus_name, _ofono_get_name_owner, NULL);
3032 void ofono_shutdown(void)
3034 if (pc_get_modems) {
3035 eldbus_pending_cancel(pc_get_modems);
3036 pc_get_modems = NULL;
3039 _ofono_disconnected();
3040 eina_stringshare_replace(&modem_path_wanted, NULL);
3042 eina_hash_free(modems);
3045 eina_list_free(modem_types);
3048 static OFono_Pending *_ofono_call_volume_property_set(const char *property,
3055 OFono_Simple_Cb_Context *ctx = NULL;
3056 Eldbus_Message *msg;
3057 Eldbus_Message_Iter *iter, *variant;
3058 OFono_Modem *m = _modem_selected_get();
3060 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
3063 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3064 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
3069 msg = eldbus_message_method_call_new(bus_id, m->base.path,
3070 OFONO_PREFIX OFONO_CALL_VOL_IFACE,
3073 goto error_no_dbus_message;
3075 if (!eldbus_message_arguments_append(msg, "s", property))
3076 goto error_message_args;
3078 iter = eldbus_message_iter_get(msg);
3080 variant = eldbus_message_iter_container_new(iter, 'v', (const char*) &type);
3083 goto error_message_args;
3085 if (strcmp(property, "Muted") == 0) {
3086 if (!eldbus_message_iter_basic_append(variant, type, *(Eina_Bool *) value) ||
3087 !eldbus_message_iter_container_close(iter, variant)) {
3088 goto error_message_args;
3090 } else if (strcmp(property, "SpeakerVolume") == 0 || strcmp(property, "MicrophoneVolume") == 0) {
3091 if (!eldbus_message_iter_basic_append(variant, type, *(char *) value) ||
3092 !eldbus_message_iter_container_close(iter, variant)) {
3093 goto error_message_args;
3096 ERR("Unsupported property: %s", property);
3099 INF("%s.SetProperty(%s)", OFONO_CALL_VOL_IFACE, property);
3100 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3104 eldbus_message_unref(msg);
3106 error_no_dbus_message:
3108 cb((void *)data, OFONO_ERROR_FAILED);
3113 OFono_Pending *ofono_mute_set(Eina_Bool mute, OFono_Simple_Cb cb,
3116 Eina_Bool dbus_mute = !!mute;
3118 return _ofono_call_volume_property_set("Muted", 'b',
3119 &dbus_mute, cb, data);
3122 Eina_Bool ofono_mute_get(void)
3124 OFono_Modem *m = _modem_selected_get();
3125 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3129 OFono_Pending *ofono_volume_speaker_set(unsigned char volume,
3134 return _ofono_call_volume_property_set("SpeakerVolume", 'y',
3138 unsigned char ofono_volume_speaker_get(void)
3140 OFono_Modem *m = _modem_selected_get();
3141 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3142 return m->speaker_volume;
3145 OFono_Pending *ofono_volume_microphone_set(unsigned char volume,
3149 return _ofono_call_volume_property_set("MicrophoneVolume",
3154 unsigned char ofono_volume_microphone_get(void)
3156 OFono_Modem *m = _modem_selected_get();
3157 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3158 return m->microphone_volume;
3161 Eina_Bool ofono_voicemail_waiting_get(void)
3163 OFono_Modem *m = _modem_selected_get();
3164 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3165 return m->voicemail_waiting;
3168 unsigned char ofono_voicemail_count_get(void)
3170 OFono_Modem *m = _modem_selected_get();
3171 EINA_SAFETY_ON_NULL_RETURN_VAL(m, 0);
3172 return m->voicemail_count;
3175 const char *ofono_voicemail_number_get(void)
3177 OFono_Modem *m = _modem_selected_get();
3178 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3179 return m->voicemail_number;
3182 OFono_USSD_State ofono_ussd_state_get(void)
3184 OFono_Modem *m = _modem_selected_get();
3185 EINA_SAFETY_ON_NULL_RETURN_VAL(m, OFONO_USSD_STATE_IDLE);
3186 return m->ussd_state;
3189 const char *ofono_service_center_address_get(void)
3191 OFono_Modem *m = _modem_selected_get();
3192 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3193 return m->serv_center_addr;
3196 Eina_Bool ofono_use_delivery_reports_get(void)
3198 OFono_Modem *m = _modem_selected_get();
3199 EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE);
3200 return m->use_delivery_reports;
3203 const char *ofono_message_bearer_get(void)
3205 OFono_Modem *m = _modem_selected_get();
3206 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3207 return m->msg_bearer;
3210 const char *ofono_message_alphabet_get(void)
3212 OFono_Modem *m = _modem_selected_get();
3213 EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL);
3214 return m->msg_alphabet;
3217 OFono_Sent_SMS_State ofono_sent_sms_state_get(const OFono_Sent_SMS *sms)
3219 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, OFONO_SENT_SMS_STATE_FAILED);
3223 const char *ofono_sent_sms_destination_get(const OFono_Sent_SMS *sms)
3225 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3226 return sms->destination;
3229 const char *ofono_sent_sms_message_get(const OFono_Sent_SMS *sms)
3231 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL);
3232 return sms->message;
3235 time_t ofono_sent_sms_timestamp_get(const OFono_Sent_SMS *sms)
3237 EINA_SAFETY_ON_NULL_RETURN_VAL(sms, 0);
3238 return sms->timestamp;
3241 OFono_Pending *ofono_sent_sms_cancel(OFono_Sent_SMS *sms, OFono_Simple_Cb cb,
3244 OFono_Simple_Cb_Context *ctx = NULL;
3245 OFono_Error err = OFONO_ERROR_OFFLINE;
3247 Eldbus_Message *msg;
3250 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3251 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3256 msg = eldbus_message_method_call_new(bus_id, sms->base.path,
3257 OFONO_PREFIX "Message",
3262 INF("Cancel(%s)", sms->base.path);
3263 p = _bus_object_message_send(&sms->base, msg, _ofono_simple_reply, ctx);
3268 cb((void *)data, err);
3273 static void _ofono_sms_send_reply(void *data, Eldbus_Message *msg,
3274 Eldbus_Pending *pending __UNUSED__)
3276 OFono_Sent_SMS_Cb_Context *ctx = data;
3277 OFono_Sent_SMS *sms = NULL;
3278 OFono_Error oe = OFONO_ERROR_NONE;
3279 const char *err_name, *err_message;
3281 EINA_SAFETY_ON_NULL_RETURN(data);
3285 oe = OFONO_ERROR_FAILED;
3288 if (eldbus_message_error_get(msg, &err_name, &err_message)) {
3289 ERR("Ofono reply error %s: %s", err_name, err_message);
3290 oe = _ofono_error_parse(err_name);
3293 if (!eldbus_message_arguments_get(msg, "o", &path)) {
3294 ERR("Could not get SendMessage reply");
3295 oe = OFONO_ERROR_FAILED;
3297 sms = eina_hash_find(ctx->modem->sent_sms, path);
3298 DBG("path=%s, existing sms=%p", path, sms);
3300 sms = _sent_sms_pending_add(ctx->modem, path,
3303 /* ctx->cb will be dispatched on
3304 * MessageAdded signal handler.
3310 ERR("Could not find sms %s", path);
3311 oe = OFONO_ERROR_FAILED;
3316 ctx->cb((void *)ctx->data, oe, sms);
3318 eina_stringshare_del(ctx->destination);
3319 eina_stringshare_del(ctx->message);
3323 OFono_Pending *ofono_sms_send(const char *number, const char *message,
3324 OFono_Sent_SMS_Cb cb, const void *data)
3326 OFono_Sent_SMS_Cb_Context *ctx = NULL;
3327 OFono_Error err = OFONO_ERROR_OFFLINE;
3329 Eldbus_Message *msg;
3330 OFono_Modem *m = _modem_selected_get();
3331 EINA_SAFETY_ON_NULL_GOTO(m, error);
3332 EINA_SAFETY_ON_NULL_GOTO(number, error);
3333 EINA_SAFETY_ON_NULL_GOTO(message, error);
3335 if ((m->interfaces & OFONO_API_MSG) == 0)
3337 err = OFONO_ERROR_FAILED;
3339 ctx = calloc(1, sizeof(OFono_Sent_SMS_Cb_Context));
3340 EINA_SAFETY_ON_NULL_GOTO(ctx, error);
3344 ctx->destination = eina_stringshare_add(number);
3345 ctx->message = eina_stringshare_add(message);
3347 msg = eldbus_message_method_call_new(
3348 bus_id, m->base.path, OFONO_PREFIX OFONO_MSG_IFACE,
3353 if (!eldbus_message_arguments_append(msg, "ss", number, message))
3356 INF("SendMessage(%s, %s)", number, message);
3357 p = _bus_object_message_send(&m->base, msg, _ofono_sms_send_reply, ctx);
3361 eldbus_message_unref(msg);
3363 eina_stringshare_del(ctx->destination);
3364 eina_stringshare_del(ctx->message);
3367 cb((void *)data, err, NULL);
3372 OFono_Pending *ofono_tones_send(const char *tones,
3377 Eldbus_Message *msg;
3378 OFono_Simple_Cb_Context *ctx = NULL;
3379 OFono_Modem *m = _modem_selected_get();
3381 EINA_SAFETY_ON_NULL_GOTO(m, error_no_dbus_message);
3384 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3385 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_dbus_message);
3390 msg = eldbus_message_method_call_new(
3391 bus_id, m->base.path,
3392 OFONO_PREFIX OFONO_VOICE_IFACE,
3395 goto error_no_dbus_message;
3397 if (!eldbus_message_arguments_append(msg, "s", tones))
3398 goto error_message_args;
3400 INF("SendTones(%s)", tones);
3401 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3405 eldbus_message_unref(msg);
3407 error_no_dbus_message:
3409 cb((void *)data, OFONO_ERROR_FAILED);
3414 OFono_Pending *ofono_multiparty_create(OFono_Simple_Cb cb,
3417 return _ofono_multiparty("CreateMultiparty", cb, data);
3420 OFono_Pending *ofono_multiparty_hangup(OFono_Simple_Cb cb, const void *data)
3422 return _ofono_multiparty("HangupMultiparty", cb, data);
3425 OFono_Pending *ofono_private_chat(OFono_Call *c, OFono_Simple_Cb cb,
3429 Eldbus_Message *msg;
3430 OFono_Simple_Cb_Context *ctx = NULL;
3431 OFono_Modem *m = _modem_selected_get();
3433 EINA_SAFETY_ON_NULL_GOTO(m, error_no_message);
3434 EINA_SAFETY_ON_NULL_GOTO(c, error_no_message);
3437 ctx = calloc(1, sizeof(OFono_Simple_Cb_Context));
3438 EINA_SAFETY_ON_NULL_GOTO(ctx, error_no_message);
3443 msg = eldbus_message_method_call_new(
3444 bus_id, m->base.path,
3445 OFONO_PREFIX OFONO_VOICE_IFACE,
3449 goto error_no_message;
3451 if (!eldbus_message_arguments_append(msg, "o", c->base.path))
3452 goto error_message_append;
3454 INF("PrivateChat(%s)", c->base.path);
3455 p = _bus_object_message_send(&m->base, msg, _ofono_simple_reply, ctx);
3458 error_message_append:
3459 eldbus_message_unref(msg);
3462 cb((void *)data, OFONO_ERROR_FAILED);
3467 static OFono_Callback_List_Modem_Node * _ofono_callback_modem_node_create(
3468 void (*cb)(void *data),const void *data)
3470 OFono_Callback_List_Modem_Node *node_new;
3472 node_new = calloc(1, sizeof(OFono_Callback_List_Modem_Node));
3473 EINA_SAFETY_ON_NULL_RETURN_VAL(node_new, NULL);
3475 node_new->cb_data = data;
3481 OFono_Callback_List_Modem_Node *
3482 ofono_modem_conected_cb_add(void (*cb)(void *data), const void *data)
3484 OFono_Callback_List_Modem_Node *node;
3486 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3487 node = _ofono_callback_modem_node_create(cb, data);
3488 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3490 cbs_modem_connected = eina_inlist_append(cbs_modem_connected,
3491 EINA_INLIST_GET(node));
3496 OFono_Callback_List_Modem_Node *
3497 ofono_modem_disconnected_cb_add(void (*cb)(void *data), const void *data)
3499 OFono_Callback_List_Modem_Node *node;
3501 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3502 node = _ofono_callback_modem_node_create(cb, data);
3503 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3505 cbs_modem_disconnected = eina_inlist_append(cbs_modem_disconnected,
3506 EINA_INLIST_GET(node));
3511 OFono_Callback_List_Modem_Node *
3512 ofono_modem_changed_cb_add(void (*cb)(void *data), const void *data)
3514 OFono_Callback_List_Modem_Node *node;
3516 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3517 node = _ofono_callback_modem_node_create(cb, data);
3518 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3520 cbs_modem_changed = eina_inlist_append(cbs_modem_changed,
3521 EINA_INLIST_GET(node));
3526 static void _ofono_callback_modem_list_delete(Eina_Inlist **list,
3527 OFono_Callback_List_Modem_Node *node)
3529 EINA_SAFETY_ON_NULL_RETURN(*list);
3530 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3534 void ofono_modem_changed_cb_del(OFono_Callback_List_Modem_Node *node)
3536 EINA_SAFETY_ON_NULL_RETURN(node);
3537 _ofono_callback_modem_list_delete(&cbs_modem_changed, node);
3540 void ofono_modem_disconnected_cb_del(OFono_Callback_List_Modem_Node *node)
3542 EINA_SAFETY_ON_NULL_RETURN(node);
3543 _ofono_callback_modem_list_delete(&cbs_modem_disconnected, node);
3546 void ofono_modem_connected_cb_del(OFono_Callback_List_Modem_Node *node)
3548 EINA_SAFETY_ON_NULL_RETURN(node);
3549 _ofono_callback_modem_list_delete(&cbs_modem_connected, node);
3552 static OFono_Callback_List_Call_Node *_ofono_callback_call_node_create(
3553 void (*cb)(void *data, OFono_Call *call),const void *data)
3555 OFono_Callback_List_Call_Node *node;
3557 node = calloc(1, sizeof(OFono_Callback_List_Call_Node));
3558 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3560 node->cb_data = data;
3566 static OFono_Callback_List_Call_Disconnected_Node *
3567 _ofono_callback_call_disconnected_node_create(
3568 void (*cb)(void *data, OFono_Call *call, const char *reason),
3571 OFono_Callback_List_Call_Disconnected_Node *node;
3573 node = calloc(1, sizeof(OFono_Callback_List_Call_Disconnected_Node));
3574 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3576 node->cb_data = data;
3582 static OFono_Callback_List_USSD_Notify_Node *
3583 _ofono_callback_ussd_notify_node_create(
3584 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3587 OFono_Callback_List_USSD_Notify_Node *node;
3589 node = calloc(1, sizeof(OFono_Callback_List_USSD_Notify_Node));
3590 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3592 node->cb_data = data;
3598 OFono_Callback_List_Call_Node *ofono_call_added_cb_add(
3599 void (*cb)(void *data,OFono_Call *call), const void *data)
3601 OFono_Callback_List_Call_Node *node;
3603 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3604 node = _ofono_callback_call_node_create(cb, data);
3605 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3607 cbs_call_added = eina_inlist_append(cbs_call_added,
3608 EINA_INLIST_GET(node));
3613 OFono_Callback_List_Call_Node *ofono_call_removed_cb_add(
3614 void (*cb)(void *data, OFono_Call *call), const void *data)
3616 OFono_Callback_List_Call_Node *node;
3618 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3619 node = _ofono_callback_call_node_create(cb, data);
3620 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3622 cbs_call_removed = eina_inlist_append(cbs_call_removed,
3623 EINA_INLIST_GET(node));
3628 OFono_Callback_List_Call_Node *ofono_call_changed_cb_add(
3629 void (*cb)(void *data, OFono_Call *call), const void *data)
3631 OFono_Callback_List_Call_Node *node;
3633 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3634 node = _ofono_callback_call_node_create(cb, data);
3635 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3637 cbs_call_changed = eina_inlist_append(cbs_call_changed,
3638 EINA_INLIST_GET(node));
3643 OFono_Callback_List_Call_Disconnected_Node *ofono_call_disconnected_cb_add(
3644 void (*cb)(void *data, OFono_Call *call, const char *reason),
3647 OFono_Callback_List_Call_Disconnected_Node *node;
3649 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3650 node = _ofono_callback_call_disconnected_node_create(cb, data);
3651 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3653 cbs_call_disconnected = eina_inlist_append(cbs_call_disconnected,
3654 EINA_INLIST_GET(node));
3659 OFono_Callback_List_USSD_Notify_Node *ofono_ussd_notify_cb_add(
3660 void (*cb)(void *data, Eina_Bool needs_reply, const char *msg),
3663 OFono_Callback_List_USSD_Notify_Node *node;
3665 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3666 node = _ofono_callback_ussd_notify_node_create(cb, data);
3667 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3669 cbs_ussd_notify = eina_inlist_append(cbs_ussd_notify,
3670 EINA_INLIST_GET(node));
3675 static void _ofono_callback_call_list_delete(Eina_Inlist **list,
3676 OFono_Callback_List_Call_Node *node)
3678 EINA_SAFETY_ON_NULL_RETURN(*list);
3679 *list = eina_inlist_remove(*list, EINA_INLIST_GET(node));
3683 void ofono_call_changed_cb_del(OFono_Callback_List_Call_Node *node)
3685 EINA_SAFETY_ON_NULL_RETURN(node);
3686 _ofono_callback_call_list_delete(&cbs_call_changed, node);
3689 void ofono_call_disconnected_cb_del(
3690 OFono_Callback_List_Call_Disconnected_Node *node)
3692 EINA_SAFETY_ON_NULL_RETURN(node);
3693 EINA_SAFETY_ON_NULL_RETURN(cbs_call_disconnected);
3694 cbs_call_disconnected = eina_inlist_remove(cbs_call_disconnected,
3695 EINA_INLIST_GET(node));
3699 void ofono_ussd_notify_cb_del(OFono_Callback_List_USSD_Notify_Node *node)
3701 EINA_SAFETY_ON_NULL_RETURN(node);
3702 EINA_SAFETY_ON_NULL_RETURN(cbs_ussd_notify);
3703 cbs_ussd_notify = eina_inlist_remove(cbs_ussd_notify,
3704 EINA_INLIST_GET(node));
3708 void ofono_call_added_cb_del(OFono_Callback_List_Call_Node *node)
3710 EINA_SAFETY_ON_NULL_RETURN(node);
3711 _ofono_callback_call_list_delete(&cbs_call_added, node);
3714 void ofono_call_removed_cb_del(OFono_Callback_List_Call_Node *node)
3716 EINA_SAFETY_ON_NULL_RETURN(node);
3717 _ofono_callback_call_list_delete(&cbs_call_removed, node);
3720 OFono_Callback_List_Sent_SMS_Node *
3721 ofono_sent_sms_changed_cb_add(OFono_Sent_SMS_Cb cb, const void *data)
3723 OFono_Callback_List_Sent_SMS_Node *node;
3725 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3726 node = calloc(1, sizeof(OFono_Callback_List_Sent_SMS_Node));
3727 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3729 node->cb_data = data;
3731 cbs_sent_sms_changed = eina_inlist_append(cbs_sent_sms_changed,
3732 EINA_INLIST_GET(node));
3737 void ofono_sent_sms_changed_cb_del(OFono_Callback_List_Sent_SMS_Node *node)
3739 EINA_SAFETY_ON_NULL_RETURN(node);
3740 cbs_sent_sms_changed = eina_inlist_remove(cbs_sent_sms_changed,
3741 EINA_INLIST_GET(node));
3745 OFono_Callback_List_Incoming_SMS_Node *
3746 ofono_incoming_sms_cb_add(OFono_Incoming_SMS_Cb cb, const void *data)
3748 OFono_Callback_List_Incoming_SMS_Node *node;
3750 EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
3751 node = calloc(1, sizeof(OFono_Callback_List_Incoming_SMS_Node));
3752 EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL);
3754 node->cb_data = data;
3756 cbs_incoming_sms = eina_inlist_append(cbs_incoming_sms,
3757 EINA_INLIST_GET(node));
3762 void ofono_incoming_sms_cb_del(OFono_Callback_List_Incoming_SMS_Node *node)
3764 EINA_SAFETY_ON_NULL_RETURN(node);
3765 cbs_incoming_sms = eina_inlist_remove(cbs_incoming_sms,
3766 EINA_INLIST_GET(node));
3770 Eina_Bool ofono_voice_is_online(void)
3772 OFono_Modem *m = _modem_selected_get();
3774 /* The modem is expected to be NULL here, because maybe
3775 * OFono isn't up yet.
3780 if (m->interfaces & OFONO_API_VOICE)