From d4e94fd62866a5247ce1e71dbe6454ec95406857 Mon Sep 17 00:00:00 2001 From: Gustavo Sverzut Barbieri Date: Mon, 10 Sep 2012 19:46:25 -0300 Subject: [PATCH] ofono: add MessageManager and Message API. This covers the usage we expect for our message application: - MessageManager: - SendMessage(): ofono_sms_send() - ServiceCenterAddress: ofono_service_center_address_get() - UseDeliveryReports: ofono_use_delivery_reports_get() - Bearer: ofono_message_bearer_get() - Alphabet: ofono_message_alphabet_get() - MessageAdded, MessageRemoved: ofono_sent_sms_changed_cb_add() - IncomingMessage, ImmediateMessage: ofono_incoming_sms_cb_add() - Message: - Cancel(): ofono_sent_sms_cancel() - State: ofono_sent_sms_state_get() sms_class = 0 means immediate messages (just popup, not going to application and history), while 1 means regular messages (goes to all of popup, application and history). --- utils/ofono.c | 643 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils/ofono.h | 33 +++ 2 files changed, 676 insertions(+) diff --git a/utils/ofono.c b/utils/ofono.c index 6975828..5521d37 100644 --- a/utils/ofono.c +++ b/utils/ofono.c @@ -30,6 +30,7 @@ static DBusPendingCall *pc_get_modems = NULL; static void _ofono_call_volume_properties_get(OFono_Modem *m); static void _ofono_msg_waiting_properties_get(OFono_Modem *m); static void _ofono_suppl_serv_properties_get(OFono_Modem *m); +static void _ofono_msg_properties_get(OFono_Modem *m); static OFono_Pending *_ofono_simple_do(OFono_API api, const char *method, OFono_Simple_Cb cb, const void *data); @@ -62,6 +63,20 @@ struct _OFono_Callback_List_USSD_Notify_Node const void *cb_data; }; +struct _OFono_Callback_List_Sent_SMS_Node +{ + EINA_INLIST; + OFono_Sent_SMS_Cb cb; + const void *cb_data; +}; + +struct _OFono_Callback_List_Incoming_SMS_Node +{ + EINA_INLIST; + OFono_Incoming_SMS_Cb cb; + const void *cb_data; +}; + static Eina_Inlist *cbs_modem_changed = NULL; static Eina_Inlist *cbs_modem_connected = NULL; static Eina_Inlist *cbs_modem_disconnected = NULL; @@ -72,6 +87,9 @@ static Eina_Inlist *cbs_call_added = NULL; static Eina_Inlist *cbs_call_disconnected = NULL; static Eina_Inlist *cbs_call_removed = NULL; +static Eina_Inlist *cbs_sent_sms_changed = NULL; +static Eina_Inlist *cbs_incoming_sms = NULL; + #define OFONO_SERVICE "org.ofono" #define OFONO_PREFIX OFONO_SERVICE "." @@ -434,13 +452,31 @@ struct _OFono_Call OFono_Call_Cb_Context *pending_dial; }; +typedef struct _OFono_Sent_SMS_Cb_Context +{ + OFono_Sent_SMS_Cb cb; + OFono_Modem *modem; + const void *data; +} OFono_Sent_SMS_Cb_Context; + +struct _OFono_Sent_SMS +{ + OFono_Bus_Object base; + OFono_Sent_SMS_State state; + OFono_Sent_SMS_Cb_Context *pending_send; +}; + struct _OFono_Modem { OFono_Bus_Object base; const char *name; const char *serial; const char *voicemail_number; + const char *serv_center_addr; + const char *msg_bearer; + const char *msg_alphabet; Eina_Hash *calls; + Eina_Hash *sent_sms; unsigned int interfaces; unsigned char strength; unsigned char data_strength; @@ -454,6 +490,7 @@ struct _OFono_Modem Eina_Bool roaming : 1; Eina_Bool muted : 1; Eina_Bool voicemail_waiting : 1; + Eina_Bool use_delivery_reports : 1; }; static OFono_Call *_call_new(const char *path) @@ -987,6 +1024,27 @@ static void _modem_calls_load(OFono_Modem *m) _bus_object_message_send(&m->base, msg, _ofono_calls_get_reply, m); } +static OFono_Sent_SMS *_sent_sms_new(const char *path) +{ + OFono_Sent_SMS *sms = calloc(1, sizeof(OFono_Sent_SMS)); + EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL); + + sms->base.path = eina_stringshare_add(path); + EINA_SAFETY_ON_NULL_GOTO(sms->base.path, error_path); + + return sms; + +error_path: + free(sms); + return NULL; +} + +static void _sent_sms_free(OFono_Sent_SMS *sms) +{ + DBG("sms=%p %s", sms, sms->base.path); + _bus_object_free(&sms->base); +} + static OFono_Modem *_modem_new(const char *path) { OFono_Modem *m = calloc(1, sizeof(OFono_Modem)); @@ -998,8 +1056,13 @@ static OFono_Modem *_modem_new(const char *path) m->calls = eina_hash_string_small_new(EINA_FREE_CB(_call_free)); EINA_SAFETY_ON_NULL_GOTO(m->calls, error_calls); + m->sent_sms = eina_hash_string_small_new(EINA_FREE_CB(_sent_sms_free)); + EINA_SAFETY_ON_NULL_GOTO(m->sent_sms, error_sent_sms); + return m; +error_sent_sms: + eina_hash_free(m->calls); error_calls: eina_stringshare_del(m->base.path); error_path: @@ -1017,8 +1080,12 @@ static void _modem_free(OFono_Modem *m) eina_stringshare_del(m->name); eina_stringshare_del(m->serial); eina_stringshare_del(m->voicemail_number); + eina_stringshare_del(m->serv_center_addr); + eina_stringshare_del(m->msg_bearer); + eina_stringshare_del(m->msg_alphabet); eina_hash_free(m->calls); + eina_hash_free(m->sent_sms); _bus_object_free(&m->base); } @@ -1090,6 +1157,33 @@ static void _suppl_serv_property_update(OFono_Modem *m, const char *prop_name, DBG("%s %s (unused property)", m->base.path, prop_name); } +static void _msg_property_update(OFono_Modem *m, const char *prop_name, + DBusMessageIter *iter) +{ + + if (strcmp(prop_name, "ServiceCenterAddress") == 0) { + const char *str; + dbus_message_iter_get_basic(iter, &str); + DBG("%s ServiceCenterAddress %s", m->base.path, str); + eina_stringshare_replace(&(m->serv_center_addr), str); + } else if (strcmp(prop_name, "UseDeliveryReports") == 0) { + m->use_delivery_reports = _dbus_bool_get(iter); + DBG("%s UseDeliveryReports %hhu", m->base.path, + m->use_delivery_reports); + } else if (strcmp(prop_name, "Bearer") == 0) { + const char *str; + dbus_message_iter_get_basic(iter, &str); + DBG("%s Bearer %s", m->base.path, str); + eina_stringshare_replace(&(m->msg_bearer), str); + } else if (strcmp(prop_name, "Alphabet") == 0) { + const char *str; + dbus_message_iter_get_basic(iter, &str); + DBG("%s Alphabet %s", m->base.path, str); + eina_stringshare_replace(&(m->msg_alphabet), str); + } else + DBG("%s %s (unused property)", m->base.path, prop_name); +} + static void _notify_ofono_callbacks_modem_list(Eina_Inlist *list) { OFono_Callback_List_Modem_Node *node; @@ -1187,6 +1281,287 @@ static void _suppl_serv_request_recv(void *data __UNUSED__, DBusMessage *msg) _notify_ofono_callbacks_ussd_notify_list(cbs_ussd_notify, EINA_TRUE, s); } +static void _msg_property_changed(void *data, DBusMessage *msg) +{ + OFono_Modem *m = data; + DBusMessageIter iter, variant_iter; + const char *prop_name; + + if (!msg || !dbus_message_iter_init(msg, &iter)) { + ERR("Could not handle message %p", msg); + return; + } + + dbus_message_iter_get_basic(&iter, &prop_name); + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &variant_iter); + _msg_property_update(m, prop_name, &variant_iter); + + _notify_ofono_callbacks_modem_list(cbs_modem_changed); +} + +static OFono_Sent_SMS_State _sent_sms_state_parse(const char *str) +{ + if (strcmp(str, "pending") == 0) + return OFONO_SENT_SMS_STATE_PENDING; + else if (strcmp(str, "failed") == 0) + return OFONO_SENT_SMS_STATE_FAILED; + else if (strcmp(str, "sent") == 0) + return OFONO_SENT_SMS_STATE_SENT; + + ERR("unknown message state: %s", str); + return OFONO_SENT_SMS_STATE_FAILED; +} + +static void _sent_sms_property_update(OFono_Sent_SMS *sms, const char *key, + DBusMessageIter *value) +{ + if (strcmp(key, "State") == 0) { + const char *str; + OFono_Sent_SMS_State state; + dbus_message_iter_get_basic(value, &str); + state = _sent_sms_state_parse(str); + DBG("%s State %d %s", sms->base.path, state, str); + sms->state = state; + } else + DBG("%s %s (unused property)", sms->base.path, key); +} + +static void _notify_ofono_callbacks_sent_sms(OFono_Error err, + OFono_Sent_SMS *sms) +{ + OFono_Callback_List_Sent_SMS_Node *node; + + EINA_INLIST_FOREACH(cbs_sent_sms_changed, node) + node->cb((void *) node->cb_data, err, sms); +} + +static void _sent_sms_property_changed(void *data, DBusMessage *msg) +{ + OFono_Sent_SMS *sms = data; + DBusMessageIter iter, value; + const char *key; + + if (!msg || !dbus_message_iter_init(msg, &iter)) { + ERR("Could not handle message %p", msg); + return; + } + + DBG("path=%s", sms->base.path); + + dbus_message_iter_get_basic(&iter, &key); + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &value); + _sent_sms_property_update(sms, key, &value); + + _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms); +} + +static void _notify_ofono_callbacks_incoming_sms(unsigned int sms_class, + double timestamp, + const char *sender, + const char *message) +{ + OFono_Callback_List_Incoming_SMS_Node *node; + + EINA_INLIST_FOREACH(cbs_incoming_sms, node) { + node->cb((void *) node->cb_data, sms_class, timestamp, sender, + message); + } +} + +static void _msg_notify(unsigned int sms_class, DBusMessageIter *iter) +{ + DBusMessageIter info; + const char *message = NULL; + const char *sender = NULL; + const char *orig_timestamp = NULL; + const char *local_timestamp = NULL; + time_t st, ut; + double lt, timestamp = 0.0; + + dbus_message_iter_get_basic(iter, &message); + EINA_SAFETY_ON_NULL_RETURN(message); + DBG("Message '%s'", message); + + dbus_message_iter_next(iter); + dbus_message_iter_recurse(iter, &info); + for (; dbus_message_iter_get_arg_type(&info) == DBUS_TYPE_DICT_ENTRY; + dbus_message_iter_next(&info)) { + DBusMessageIter entry, value; + const char *key; + + dbus_message_iter_recurse(&info, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + if (strcmp(key, "Sender") == 0) { + dbus_message_iter_get_basic(&value, &sender); + DBG("Sender %s", sender); + } else if (strcmp(key, "SentTime") == 0) { + dbus_message_iter_get_basic(&value, &orig_timestamp); + DBG("SentTime %s", orig_timestamp); + } else if (strcmp(key, "LocalSentTime") == 0) { + dbus_message_iter_get_basic(&value, &local_timestamp); + DBG("LocalSentTime %s", local_timestamp); + } else + DBG("%s (unused property)", key); + } + + EINA_SAFETY_ON_NULL_RETURN(sender); + EINA_SAFETY_ON_NULL_RETURN(local_timestamp); + + st = _ofono_time_parse(local_timestamp); + ut = time(NULL); + lt = ecore_loop_time_get(); + timestamp = st - ut + lt; + + _notify_ofono_callbacks_incoming_sms(sms_class, timestamp, sender, + message); +} + +static void _msg_immediate(void *data, DBusMessage *msg) +{ + OFono_Modem *m = data; + DBusMessageIter iter; + + if (!msg || !dbus_message_iter_init(msg, &iter)) { + ERR("Could not handle message %p", msg); + return; + } + + DBG("path=%s", m->base.path); + _msg_notify(0, &iter); +} + +static void _msg_incoming(void *data, DBusMessage *msg) +{ + OFono_Modem *m = data; + DBusMessageIter iter; + + if (!msg || !dbus_message_iter_init(msg, &iter)) { + ERR("Could not handle message %p", msg); + return; + } + + DBG("path=%s", m->base.path); + _msg_notify(1, &iter); +} + +static OFono_Sent_SMS *_sent_sms_common_add(OFono_Modem *m, const char *path) +{ + OFono_Sent_SMS *sms = _sent_sms_new(path); + EINA_SAFETY_ON_NULL_RETURN_VAL(sms, NULL); + eina_hash_add(m->sent_sms, sms->base.path, sms); + + _bus_object_signal_listen(&sms->base, + OFONO_PREFIX "Message", + "PropertyChanged", + _sent_sms_property_changed, sms); + return sms; +} + +static OFono_Sent_SMS *_sent_sms_pending_add(OFono_Modem *m, const char *path, + OFono_Sent_SMS_Cb_Context *ctx) +{ + OFono_Sent_SMS *sms; + + DBG("path=%s, ctx=%p", path, ctx); + + sms = _sent_sms_common_add(m, path); + sms->pending_send = ctx; + return sms; +} + +static void _msg_add(OFono_Modem *m, const char *path, DBusMessageIter *prop) +{ + OFono_Sent_SMS *sms; + + DBG("path=%s, prop=%p", path, prop); + + sms = eina_hash_find(m->sent_sms, path); + if (sms) + DBG("SMS already exists %p (%s)", sms, path); + else { + sms = _sent_sms_common_add(m, path); + EINA_SAFETY_ON_NULL_RETURN(sms); + } + + for (; dbus_message_iter_get_arg_type(prop) == DBUS_TYPE_DICT_ENTRY; + dbus_message_iter_next(prop)) { + DBusMessageIter entry, value; + const char *key; + + dbus_message_iter_recurse(prop, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + _sent_sms_property_update(sms, key, &value); + } + + if (sms->pending_send) { + OFono_Sent_SMS_Cb_Context *ctx = sms->pending_send; + if (ctx->cb) + ctx->cb((void *)ctx->data, OFONO_ERROR_NONE, sms); + free(ctx); + sms->pending_send = NULL; + } + + _notify_ofono_callbacks_sent_sms(OFONO_ERROR_NONE, sms); +} + +static void _msg_added(void *data, DBusMessage *msg) +{ + OFono_Modem *m = data; + DBusMessageIter iter, properties; + const char *path; + + if (!msg || !dbus_message_iter_init(msg, &iter)) { + ERR("Could not handle message %p", msg); + return; + } + + dbus_message_iter_get_basic(&iter, &path); + + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &properties); + + _msg_add(m, path, &properties); +} + +static void _msg_remove(OFono_Modem *m, const char *path) +{ + DBG("path=%s", path); + eina_hash_del_by_key(m->sent_sms, path); +} + +static void _msg_removed(void *data, DBusMessage *msg) +{ + OFono_Modem *m = data; + DBusError err; + const char *path; + + if (!msg) { + ERR("Could not handle message %p", msg); + return; + } + + dbus_error_init(&err); + if (!dbus_message_get_args(msg, &err, DBUS_TYPE_OBJECT_PATH, + &path, NULL)) { + ERR("Could not get MessageRemoved arguments: %s: %s", + err.name, err.message); + dbus_error_free(&err); + return; + } + + _msg_remove(m, path); +} + static unsigned int _modem_interfaces_extract(DBusMessageIter *array) { DBusMessageIter entry; @@ -1236,6 +1611,10 @@ static void _modem_update_interfaces(OFono_Modem *m, unsigned int ifaces) if (((m->interfaces & OFONO_API_SUPPL_SERV) == 0) && (ifaces & OFONO_API_SUPPL_SERV) == OFONO_API_SUPPL_SERV) _ofono_suppl_serv_properties_get(m); + + if (((m->interfaces & OFONO_API_MSG) == 0) && + (ifaces & OFONO_API_MSG) == OFONO_API_MSG) + _ofono_msg_properties_get(m); } static void _modem_property_update(OFono_Modem *m, const char *key, @@ -1426,6 +1805,52 @@ static void _ofono_suppl_serv_properties_get(OFono_Modem *m) _ofono_suppl_serv_properties_get_reply, m); } + +static void _ofono_msg_properties_get_reply(void *data, DBusMessage *msg, + DBusError *err) +{ + OFono_Modem *m = data; + DBusMessageIter iter, prop; + + if (dbus_error_is_set(err)) { + DBG("%s: %s", err->name, err->message); + return; + } + + dbus_message_iter_init(msg, &iter); + dbus_message_iter_recurse(&iter, &prop); + + DBG("m=%s", m->base.path); + for (; dbus_message_iter_get_arg_type(&prop) == DBUS_TYPE_DICT_ENTRY; + dbus_message_iter_next(&prop)) { + DBusMessageIter entry, value; + const char *key; + + dbus_message_iter_recurse(&prop, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + _msg_property_update(m, key, &value); + } + + _notify_ofono_callbacks_modem_list(cbs_modem_changed); +} + +static void _ofono_msg_properties_get(OFono_Modem *m) +{ + DBusMessage *msg; + msg = dbus_message_new_method_call(bus_id, m->base.path, + OFONO_PREFIX + OFONO_MSG_IFACE, + "GetProperties"); + DBG("m=%s", m->base.path); + EINA_SAFETY_ON_NULL_RETURN(msg); + + _bus_object_message_send(&m->base, msg, + _ofono_msg_properties_get_reply, m); +} + static void _modem_add(const char *path, DBusMessageIter *prop) { OFono_Modem *m; @@ -1466,6 +1891,18 @@ static void _modem_add(const char *path, DBusMessageIter *prop) "RequestReceived", _suppl_serv_request_recv, m); + _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE, + "PropertyChanged", + _msg_property_changed, m); + _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE, + "ImmediateMessage", _msg_immediate, m); + _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE, + "IncomingMessage", _msg_incoming, m); + _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE, + "MessageAdded", _msg_added, m); + _bus_object_signal_listen(&m->base, OFONO_PREFIX OFONO_MSG_IFACE, + "MessageRemoved", _msg_removed, m); + /* TODO: do we need to listen to BarringActive or Forwarded? */ if (modem_selected && modem_path_wanted && @@ -2644,6 +3081,162 @@ OFono_USSD_State ofono_ussd_state_get(void) return m->ussd_state; } +const char *ofono_service_center_address_get(void) +{ + OFono_Modem *m = _modem_selected_get(); + EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); + return m->serv_center_addr; +} + +Eina_Bool ofono_use_delivery_reports_get(void) +{ + OFono_Modem *m = _modem_selected_get(); + EINA_SAFETY_ON_NULL_RETURN_VAL(m, EINA_FALSE); + return m->use_delivery_reports; +} + +const char *ofono_message_bearer_get(void) +{ + OFono_Modem *m = _modem_selected_get(); + EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); + return m->msg_bearer; +} + +const char *ofono_message_alphabet_get(void) +{ + OFono_Modem *m = _modem_selected_get(); + EINA_SAFETY_ON_NULL_RETURN_VAL(m, NULL); + return m->msg_alphabet; +} + +OFono_Sent_SMS_State ofono_sent_sms_state_get(const OFono_Sent_SMS *sms) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(sms, OFONO_SENT_SMS_STATE_FAILED); + return sms->state; +} + +OFono_Pending *ofono_sent_sms_cancel(OFono_Sent_SMS *sms, OFono_Simple_Cb cb, + const void *data) +{ + OFono_Simple_Cb_Context *ctx = NULL; + OFono_Error err = OFONO_ERROR_OFFLINE; + OFono_Pending *p; + DBusMessage *msg; + + if (cb) { + ctx = calloc(1, sizeof(OFono_Simple_Cb_Context)); + EINA_SAFETY_ON_NULL_GOTO(ctx, error); + ctx->cb = cb; + ctx->data = data; + } + + msg = dbus_message_new_method_call(bus_id, sms->base.path, + OFONO_PREFIX "Message", + "Cancel"); + if (!msg) + goto error; + + INF("Cancel(%s)", sms->base.path); + p = _bus_object_message_send(&sms->base, msg, _ofono_simple_reply, ctx); + return p; + +error: + if (cb) + cb((void *)data, err); + free(ctx); + return NULL; +} + +static void _ofono_sms_send_reply(void *data, DBusMessage *msg, DBusError *err) +{ + OFono_Sent_SMS_Cb_Context *ctx = data; + OFono_Sent_SMS *sms = NULL; + OFono_Error oe = OFONO_ERROR_NONE; + + if (!msg) { + DBG("%s: %s", err->name, err->message); + oe = _ofono_error_parse(err->name); + } else { + DBusError e; + const char *path; + dbus_error_init(&e); + if (!dbus_message_get_args(msg, &e, DBUS_TYPE_OBJECT_PATH, + &path, DBUS_TYPE_INVALID)) { + ERR("Could not get SendMessage reply: %s: %s", + e.name, e.message); + dbus_error_free(&e); + oe = OFONO_ERROR_FAILED; + } else { + sms = eina_hash_find(ctx->modem->sent_sms, path); + DBG("path=%s, existing sms=%p", path, sms); + if (!sms) { + sms = _sent_sms_pending_add(ctx->modem, path, + ctx); + if (sms) { + /* ctx->cb will be dispatched on + * MessageAdded signal handler. + */ + return; + } + } + + ERR("Could not find sms %s", path); + oe = OFONO_ERROR_FAILED; + } + } + + if (ctx->cb) + ctx->cb((void *)ctx->data, oe, sms); + + free(ctx); +} + +OFono_Pending *ofono_sms_send(const char *number, const char *message, + OFono_Sent_SMS_Cb cb, const void *data) +{ + OFono_Sent_SMS_Cb_Context *ctx = NULL; + OFono_Error err = OFONO_ERROR_OFFLINE; + OFono_Pending *p; + DBusMessage *msg; + OFono_Modem *m = _modem_selected_get(); + EINA_SAFETY_ON_NULL_GOTO(m, error); + EINA_SAFETY_ON_NULL_GOTO(number, error); + EINA_SAFETY_ON_NULL_GOTO(message, error); + + if ((m->interfaces & OFONO_API_MSG) == 0) + goto error; + err = OFONO_ERROR_FAILED; + + ctx = calloc(1, sizeof(OFono_Sent_SMS_Cb_Context)); + EINA_SAFETY_ON_NULL_GOTO(ctx, error); + ctx->cb = cb; + ctx->data = data; + ctx->modem = m; + + msg = dbus_message_new_method_call( + bus_id, m->base.path, OFONO_PREFIX OFONO_MSG_IFACE, + "SendMessage"); + if (!msg) + goto error; + + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &number, + DBUS_TYPE_STRING, &message, + DBUS_TYPE_INVALID)) + goto error_message; + + INF("SendMessage(%s, %s)", number, message); + p = _bus_object_message_send(&m->base, msg, _ofono_sms_send_reply, ctx); + return p; + +error_message: + dbus_message_unref(msg); +error: + if (cb) + cb((void *)data, err, NULL); + free(ctx); + return NULL; +} + OFono_Pending *ofono_tones_send(const char *tones, OFono_Simple_Cb cb, const void *data) @@ -2994,6 +3587,56 @@ void ofono_call_removed_cb_del(OFono_Callback_List_Call_Node *node) _ofono_callback_call_list_delete(&cbs_call_removed, node); } +OFono_Callback_List_Sent_SMS_Node * +ofono_sent_sms_changed_cb_add(OFono_Sent_SMS_Cb cb, const void *data) +{ + OFono_Callback_List_Sent_SMS_Node *node; + + EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL); + node = calloc(1, sizeof(OFono_Callback_List_Sent_SMS_Node)); + EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL); + node->cb = cb; + node->cb_data = data; + + cbs_sent_sms_changed = eina_inlist_append(cbs_sent_sms_changed, + EINA_INLIST_GET(node)); + + return node; +} + +void ofono_sent_sms_changed_cb_del(OFono_Callback_List_Sent_SMS_Node *node) +{ + EINA_SAFETY_ON_NULL_RETURN(node); + cbs_sent_sms_changed = eina_inlist_remove(cbs_sent_sms_changed, + EINA_INLIST_GET(node)); + free(node); +} + +OFono_Callback_List_Incoming_SMS_Node * +ofono_incoming_sms_cb_add(OFono_Incoming_SMS_Cb cb, const void *data) +{ + OFono_Callback_List_Incoming_SMS_Node *node; + + EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL); + node = calloc(1, sizeof(OFono_Callback_List_Incoming_SMS_Node)); + EINA_SAFETY_ON_NULL_RETURN_VAL(node, NULL); + node->cb = cb; + node->cb_data = data; + + cbs_incoming_sms = eina_inlist_append(cbs_incoming_sms, + EINA_INLIST_GET(node)); + + return node; +} + +void ofono_incoming_sms_cb_del(OFono_Callback_List_Incoming_SMS_Node *node) +{ + EINA_SAFETY_ON_NULL_RETURN(node); + cbs_incoming_sms = eina_inlist_remove(cbs_incoming_sms, + EINA_INLIST_GET(node)); + free(node); +} + Eina_Bool ofono_voice_is_online(void) { OFono_Modem *m = _modem_selected_get(); diff --git a/utils/ofono.h b/utils/ofono.h index 0f32a6a..6b99c7c 100644 --- a/utils/ofono.h +++ b/utils/ofono.h @@ -64,12 +64,20 @@ typedef enum typedef enum { + OFONO_SENT_SMS_STATE_PENDING = 0, + OFONO_SENT_SMS_STATE_FAILED, + OFONO_SENT_SMS_STATE_SENT +} OFono_Sent_SMS_State; + +typedef enum +{ OFONO_USSD_STATE_IDLE = 0, OFONO_USSD_STATE_ACTIVE, OFONO_USSD_STATE_USER_RESPONSE } OFono_USSD_State; typedef struct _OFono_Call OFono_Call; +typedef struct _OFono_Sent_SMS OFono_Sent_SMS; typedef struct _OFono_Pending OFono_Pending; typedef struct _OFono_Callback_List_USSD_Notify_Node OFono_Callback_List_USSD_Notify_Node; @@ -78,10 +86,15 @@ typedef struct _OFono_Callback_List_Modem_Node OFono_Callback_List_Modem_Node; typedef struct _OFono_Callback_List_Call_Node OFono_Callback_List_Call_Node; typedef struct _OFono_Callback_List_Call_Disconnected_Node OFono_Callback_List_Call_Disconnected_Node; +typedef struct _OFono_Callback_List_Sent_SMS_Node OFono_Callback_List_Sent_SMS_Node; +typedef struct _OFono_Callback_List_Incoming_SMS_Node OFono_Callback_List_Incoming_SMS_Node; + typedef void (*OFono_Simple_Cb)(void *data, OFono_Error error); typedef void (*OFono_String_Cb)(void *data, OFono_Error error, const char *str); typedef void (*OFono_Call_Cb)(void *data, OFono_Error error, OFono_Call *call); +typedef void (*OFono_Sent_SMS_Cb)(void *data, OFono_Error error, OFono_Sent_SMS *sms); +typedef void (*OFono_Incoming_SMS_Cb)(void *data, unsigned int sms_class, double timestamp, const char *sender, const char *message); /* Voice Call: */ OFono_Pending *ofono_call_hangup(OFono_Call *c, OFono_Simple_Cb cb, @@ -174,6 +187,26 @@ OFono_Pending *ofono_ussd_respond(const char *string, OFono_String_Cb cb, const OFono_Pending *ofono_ussd_cancel(OFono_Simple_Cb cb, const void *data); OFono_USSD_State ofono_ussd_state_get(void); +/* SMS (Message) */ +const char *ofono_service_center_address_get(void); +Eina_Bool ofono_use_delivery_reports_get(void); +const char *ofono_message_bearer_get(void); +const char *ofono_message_alphabet_get(void); + +OFono_Pending *ofono_sms_send(const char *number, const char *message, + OFono_Sent_SMS_Cb cb, const void *data); + +OFono_Sent_SMS_State ofono_sent_sms_state_get(const OFono_Sent_SMS *sms); +OFono_Pending *ofono_sent_sms_cancel(OFono_Sent_SMS *sms, OFono_Simple_Cb cb, const void *data); + +OFono_Callback_List_Sent_SMS_Node *ofono_sent_sms_changed_cb_add(OFono_Sent_SMS_Cb cb, + const void *data); +void ofono_sent_sms_changed_cb_del(OFono_Callback_List_Sent_SMS_Node *node); + +OFono_Callback_List_Incoming_SMS_Node *ofono_incoming_sms_cb_add(OFono_Incoming_SMS_Cb cb, + const void *data); +void ofono_incoming_sms_cb_del(OFono_Callback_List_Incoming_SMS_Node *node); + /* Setup: */ void ofono_modem_api_list(FILE *fp, const char *prefix, const char *suffix); void ofono_modem_api_require(const char *spec); -- 2.7.4