sim: Reset additional state info
[platform/upstream/ofono.git] / src / message.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <gdbus.h>
28 #include <stdio.h>
29 #include <errno.h>
30
31 #include "ofono.h"
32 #include "message.h"
33
34 struct message {
35         struct ofono_uuid uuid;
36         enum message_state state;
37         struct ofono_atom *atom;
38         void *data;
39 };
40
41 static const char *message_state_to_string(enum message_state s)
42 {
43         switch (s) {
44         case MESSAGE_STATE_PENDING:
45                 return "pending";
46         case MESSAGE_STATE_SENT:
47                 return "sent";
48         case MESSAGE_STATE_FAILED:
49                 return "failed";
50         case MESSAGE_STATE_CANCELLED:
51                 return "cancelled";
52         }
53
54         return NULL;
55 }
56
57 static DBusMessage *message_get_properties(DBusConnection *conn,
58                                                 DBusMessage *msg, void *data)
59 {
60         struct message *m = data;
61         DBusMessage *reply;
62         DBusMessageIter iter;
63         DBusMessageIter dict;
64
65         reply = dbus_message_new_method_return(msg);
66         if (reply == NULL)
67                 return NULL;
68
69         dbus_message_iter_init_append(reply, &iter);
70
71         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
72                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
73                                         &dict);
74         message_append_properties(m, &dict);
75         dbus_message_iter_close_container(&iter, &dict);
76
77         return reply;
78 }
79
80 static DBusMessage *message_cancel(DBusConnection *conn,
81                                         DBusMessage *msg, void *data)
82 {
83         struct message *m = data;
84         int res;
85
86         if (dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID) == FALSE)
87                 return __ofono_error_invalid_args(msg);
88
89         if (m->state != MESSAGE_STATE_PENDING)
90                 return __ofono_error_not_available(msg);
91
92         res = __ofono_sms_txq_cancel(__ofono_atom_get_data(m->atom), &m->uuid);
93
94         switch (res) {
95         case -ENOENT:
96                 return __ofono_error_not_found(msg);
97         case -EPERM:
98                 return __ofono_error_access_denied(msg);
99         case 0:
100                 return dbus_message_new_method_return(msg);
101         default:
102                 return __ofono_error_failed(msg);
103         }
104 }
105
106 static GDBusMethodTable message_methods[] = {
107         { "GetProperties",  "",    "a{sv}",   message_get_properties },
108         { "Cancel",         "",    "",        message_cancel },
109         { }
110 };
111
112 static GDBusSignalTable message_signals[] = {
113         { "PropertyChanged",    "sv" },
114         { }
115 };
116
117 struct message *message_create(const struct ofono_uuid *uuid,
118                                                         struct ofono_atom *atom)
119 {
120         struct message *v;
121
122         v = g_try_new0(struct message, 1);
123         if (v == NULL)
124                 return NULL;
125
126         memcpy(&v->uuid, uuid, sizeof(*uuid));
127
128         v->atom = atom;
129
130         return v;
131 }
132
133 static void message_destroy(gpointer userdata)
134 {
135         struct message *m = userdata;
136
137         g_free(m);
138 }
139
140 gboolean message_dbus_register(struct message *m)
141 {
142         DBusConnection *conn = ofono_dbus_get_connection();
143         const char *path = message_path_from_uuid(m->atom, &m->uuid);
144
145         if (!g_dbus_register_interface(conn, path, OFONO_MESSAGE_INTERFACE,
146                                         message_methods, message_signals,
147                                         NULL, m, message_destroy)) {
148                 ofono_error("Could not register Message %s", path);
149                 message_destroy(m);
150
151                 return FALSE;
152         }
153
154         return TRUE;
155 }
156
157 void message_dbus_unregister(struct message *m)
158 {
159         DBusConnection *conn = ofono_dbus_get_connection();
160         const char *path = message_path_from_uuid(m->atom, &m->uuid);
161
162         g_dbus_unregister_interface(conn, path, OFONO_MESSAGE_INTERFACE);
163
164         return;
165 }
166
167 const struct ofono_uuid *message_get_uuid(const struct message *m)
168 {
169         return &m->uuid;
170 }
171
172 void message_set_state(struct message *m, enum message_state new_state)
173 {
174         DBusConnection *conn = ofono_dbus_get_connection();
175         const char *path;
176         const char *state;
177
178         if (m->state == new_state)
179                 return;
180
181         path = message_path_from_uuid(m->atom, &m->uuid);
182
183         m->state = new_state;
184         state = message_state_to_string(m->state);
185
186         ofono_dbus_signal_property_changed(conn, path, OFONO_MESSAGE_INTERFACE,
187                                                         "State",
188                                                         DBUS_TYPE_STRING,
189                                                         &state);
190 }
191
192 void message_append_properties(struct message *m, DBusMessageIter *dict)
193 {
194         const char *state = message_state_to_string(m->state);
195
196         ofono_dbus_dict_append(dict, "State", DBUS_TYPE_STRING, &state);
197 }
198
199 void message_emit_added(struct message *m, const char *interface)
200 {
201         DBusMessage *signal;
202         DBusMessageIter iter;
203         DBusMessageIter dict;
204         const char *path;
205         const char *atompath = __ofono_atom_get_path(m->atom);
206
207         signal = dbus_message_new_signal(atompath, interface, "MessageAdded");
208         if (signal == NULL)
209                 return;
210
211         path = message_path_from_uuid(m->atom, &m->uuid);
212
213         dbus_message_iter_init_append(signal, &iter);
214
215         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
216
217         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
218                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
219                                         &dict);
220         message_append_properties(m, &dict);
221         dbus_message_iter_close_container(&iter, &dict);
222
223         g_dbus_send_message(ofono_dbus_get_connection(), signal);
224 }
225
226 void message_emit_removed(struct message *m, const char *interface)
227 {
228         DBusConnection *conn = ofono_dbus_get_connection();
229         const char *atompath = __ofono_atom_get_path(m->atom);
230         const char *path = message_path_from_uuid(m->atom, &m->uuid);
231
232         g_dbus_emit_signal(conn, atompath, interface, "MessageRemoved",
233                                                         DBUS_TYPE_OBJECT_PATH,
234                                                         &path,
235                                                         DBUS_TYPE_INVALID);
236 }
237
238 const char *message_path_from_uuid(struct ofono_atom *atom,
239                                                 const struct ofono_uuid *uuid)
240 {
241         static char path[256];
242         const char *atompath = __ofono_atom_get_path(atom);
243
244         snprintf(path, sizeof(path), "%s/message_%s", atompath,
245                                                 ofono_uuid_to_str(uuid));
246
247         return path;
248 }
249
250 void *message_get_data(struct message *m)
251 {
252         return m->data;
253 }
254
255 void message_set_data(struct message *m, void *data)
256 {
257         m->data = data;
258 }