~cyphermox/ubuntu/natty/ofono/release-0.41

« back to all changes in this revision

Viewing changes to drivers/isimodem/phonebook.c

  • Committer: Mathieu Trudel-Lapierre
  • Date: 2011-02-11 02:17:20 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: mathieu-tl@ubuntu.com-20110211021720-cvxc3erw1keomunj
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
#include <glib.h>
32
32
#include <gisi/client.h>
 
33
#include <gisi/message.h>
33
34
#include <gisi/iter.h>
34
35
 
35
36
#include <ofono/log.h>
46
47
        GIsiClient *client;
47
48
};
48
49
 
49
 
static int decode_read_response(const unsigned char *msg, size_t len,
50
 
                                struct ofono_phonebook *pb)
51
 
{
 
50
struct read_resp {
 
51
        uint8_t service_type;
 
52
        uint8_t sb_count;
 
53
        uint8_t data[];
 
54
};
 
55
 
 
56
static gboolean parse_adn(GIsiSubBlockIter *iter, uint16_t *location,
 
57
                                char **name, char **number)
 
58
{
 
59
        uint8_t namelen;
 
60
        uint8_t numlen;
 
61
 
 
62
        if (!g_isi_sb_iter_get_word(iter, location, 4) ||
 
63
                        !g_isi_sb_iter_get_byte(iter, &namelen, 6) ||
 
64
                        !g_isi_sb_iter_get_byte(iter, &numlen, 7))
 
65
                return FALSE;
 
66
 
 
67
        if (!g_isi_sb_iter_get_alpha_tag(iter, name, namelen * 2, 8))
 
68
                return FALSE;
 
69
 
 
70
        if (!g_isi_sb_iter_get_alpha_tag(iter, number, numlen * 2,
 
71
                        8 + namelen * 2)) {
 
72
                g_free(*name);
 
73
                return FALSE;
 
74
        }
 
75
        return TRUE;
 
76
}
 
77
 
 
78
static gboolean parse_sne(GIsiSubBlockIter *iter, char **sne)
 
79
{
 
80
        uint8_t len;
 
81
 
 
82
        if (!g_isi_sb_iter_get_byte(iter, &len, 6))
 
83
                return FALSE;
 
84
 
 
85
        if (!g_isi_sb_iter_get_alpha_tag(iter, sne, len * 2, 8))
 
86
                return FALSE;
 
87
 
 
88
        return TRUE;
 
89
}
 
90
 
 
91
static gboolean parse_anr(GIsiSubBlockIter *iter, char **anr)
 
92
{
 
93
        uint8_t len;
 
94
 
 
95
        if (!g_isi_sb_iter_get_byte(iter, &len, 6))
 
96
                return FALSE;
 
97
 
 
98
        if (!g_isi_sb_iter_get_alpha_tag(iter, anr, len * 2, 8))
 
99
                return FALSE;
 
100
 
 
101
        return TRUE;
 
102
}
 
103
 
 
104
static gboolean parse_email(GIsiSubBlockIter *iter, char **email)
 
105
{
 
106
        uint8_t len;
 
107
 
 
108
        if (!g_isi_sb_iter_get_byte(iter, &len, 6))
 
109
                return FALSE;
 
110
 
 
111
        if (!g_isi_sb_iter_get_alpha_tag(iter, email, len * 2, 8))
 
112
                return FALSE;
 
113
 
 
114
        return TRUE;
 
115
}
 
116
 
 
117
static gboolean decode_response(const GIsiMessage *msg, uint16_t *location,
 
118
                                void *data)
 
119
{
 
120
        struct ofono_phonebook *pb = data;
 
121
        const struct read_resp *resp = g_isi_msg_data(msg);
 
122
        size_t len = g_isi_msg_data_len(msg);
 
123
 
52
124
        GIsiSubBlockIter iter;
53
125
 
54
126
        char *name = NULL;
57
129
        char *anr = NULL;
58
130
        char *email = NULL;
59
131
 
60
 
        int location = -1;
61
 
        guint8 status = 0;
62
 
 
63
 
        if (len < 3 || msg[0] != SIM_PB_RESP_SIM_PB_READ)
64
 
                goto error;
65
 
 
66
 
        if (msg[1] != SIM_PB_READ)
67
 
                goto error;
68
 
 
69
 
        for (g_isi_sb_iter_init_full(&iter, msg, len, 3, TRUE, msg[2]);
70
 
             g_isi_sb_iter_is_valid(&iter);
71
 
             g_isi_sb_iter_next(&iter)) {
 
132
        uint8_t status = 0;
 
133
        gboolean success = FALSE;
 
134
 
 
135
        if (g_isi_msg_id(msg) != SIM_PB_RESP_SIM_PB_READ ||
 
136
                        resp == NULL || len < sizeof(struct read_resp) ||
 
137
                        resp->service_type != SIM_PB_READ)
 
138
                return FALSE;
 
139
 
 
140
        for (g_isi_sb_iter_init_full(&iter, msg, 2, TRUE, resp->sb_count);
 
141
                        g_isi_sb_iter_is_valid(&iter);
 
142
                        g_isi_sb_iter_next(&iter)) {
72
143
 
73
144
                switch (g_isi_sb_iter_get_id(&iter)) {
74
 
 
75
 
                case SIM_PB_ADN: {
76
 
                        guint16 loc;
77
 
                        guint8 namelen;
78
 
                        guint8 numberlen;
79
 
 
80
 
                        if (!g_isi_sb_iter_get_word(&iter, &loc, 4) ||
81
 
                                !g_isi_sb_iter_get_byte(&iter, &namelen, 6) ||
82
 
                                !g_isi_sb_iter_get_byte(&iter, &numberlen, 7))
83
 
                                goto error;
84
 
 
85
 
                        if (!g_isi_sb_iter_get_alpha_tag(&iter, &name,
86
 
                                                namelen * 2, 8))
87
 
                                goto error;
88
 
 
89
 
                        if (!g_isi_sb_iter_get_alpha_tag(&iter, &number,
90
 
                                                numberlen * 2, 8 + namelen * 2))
91
 
                                goto error;
92
 
 
93
 
                        location = loc;
94
 
                        break;
95
 
                }
96
 
 
97
 
                case SIM_PB_SNE: {
98
 
                        guint8 snelen;
99
 
 
100
 
                        if (!g_isi_sb_iter_get_byte(&iter, &snelen, 6))
101
 
                                goto error;
102
 
 
103
 
                        if (!g_isi_sb_iter_get_alpha_tag(&iter, &sne,
104
 
                                                snelen * 2, 8))
105
 
                                goto error;
106
 
                        break;
107
 
                }
108
 
 
109
 
                case SIM_PB_ANR: {
110
 
                        guint8 anrlen;
111
 
 
112
 
                        if (!g_isi_sb_iter_get_byte(&iter, &anrlen, 6))
113
 
                                goto error;
114
 
 
115
 
                        if (!g_isi_sb_iter_get_alpha_tag(&iter, &anr,
116
 
                                                anrlen * 2, 8))
117
 
                                goto error;
118
 
                        break;
119
 
                }
120
 
 
121
 
                case SIM_PB_EMAIL: {
122
 
                        guint8 emaillen;
123
 
 
124
 
                        if (!g_isi_sb_iter_get_byte(&iter, &emaillen, 6))
125
 
                                goto error;
126
 
 
127
 
                        if (!g_isi_sb_iter_get_alpha_tag(&iter, &email,
128
 
                                                emaillen * 2, 8))
129
 
                                goto error;
130
 
                        break;
131
 
                }
 
145
                case SIM_PB_ADN:
 
146
 
 
147
                        if (!parse_adn(&iter, location, &name, &number))
 
148
                                goto error;
 
149
                        success = TRUE;
 
150
                        break;
 
151
 
 
152
                case SIM_PB_SNE:
 
153
 
 
154
                        if (!parse_sne(&iter, &sne))
 
155
                                goto error;
 
156
                        break;
 
157
 
 
158
                case SIM_PB_ANR:
 
159
 
 
160
                        if (!parse_anr(&iter, &anr))
 
161
                                goto error;
 
162
                        break;
 
163
 
 
164
                case SIM_PB_EMAIL:
 
165
 
 
166
                        if (!parse_email(&iter, &email))
 
167
                                goto error;
 
168
                        break;
132
169
 
133
170
                case SIM_PB_STATUS:
134
171
 
135
172
                        if (!g_isi_sb_iter_get_byte(&iter, &status, 4))
136
173
                                goto error;
137
 
 
138
174
                        break;
139
175
 
140
176
                default:
145
181
                }
146
182
        }
147
183
 
148
 
        if (status != SIM_SERV_OK) {
149
 
                DBG("Request failed: %s (0x%02X)",
150
 
                        sim_isi_cause_name(status), status);
151
 
                goto error;
152
 
        }
153
 
 
154
 
        ofono_phonebook_entry(pb, -1, number, -1, name, -1, NULL,
155
 
                                anr, -1, sne, email, NULL, NULL);
156
 
 
 
184
        if (status == SIM_SERV_OK)
 
185
                ofono_phonebook_entry(pb, -1, number, -1, name, -1, NULL,
 
186
                                        anr, -1, sne, email, NULL, NULL);
157
187
error:
158
188
        g_free(name);
159
189
        g_free(number);
161
191
        g_free(anr);
162
192
        g_free(email);
163
193
 
164
 
        return location;
 
194
        return success;
165
195
}
166
196
 
167
 
static void read_next_entry(GIsiClient *client, int location,
168
 
                                GIsiResponseFunc read_cb,
169
 
                                struct isi_cb_data *cbd)
 
197
static void read_next_entry(GIsiClient *client, uint16_t location,
 
198
                                GIsiNotifyFunc notify, void *data)
170
199
{
 
200
        struct isi_cb_data *cbd = data;
171
201
        ofono_phonebook_cb_t cb = cbd->cb;
172
 
        const unsigned char msg[] = {
 
202
        const uint8_t msg[] = {
173
203
                SIM_PB_REQ_SIM_PB_READ,
174
204
                SIM_PB_READ,
175
205
                2,                              /* number of subblocks */
189
219
                0, 0                            /* filler */
190
220
        };
191
221
 
192
 
        if (location < 0)
193
 
                goto error;
194
 
 
195
 
        if (!cbd)
196
 
                goto error;
197
 
 
198
 
        if (g_isi_request_make(client, msg, sizeof(msg), SIM_TIMEOUT,
199
 
                                read_cb, cbd))
 
222
        if (cbd == NULL)
 
223
                goto error;
 
224
 
 
225
        if (g_isi_client_send(client, msg, sizeof(msg), notify, cbd, NULL))
200
226
                return;
201
227
 
202
228
error:
204
230
        g_free(cbd);
205
231
}
206
232
 
207
 
static gboolean read_resp_cb(GIsiClient *client,
208
 
                                const void *restrict data, size_t len,
209
 
                                uint16_t object, void *opaque)
 
233
static void read_resp_cb(const GIsiMessage *msg, void *data)
210
234
{
211
 
        const unsigned char *msg = data;
212
 
        struct isi_cb_data *cbd = opaque;
 
235
        struct isi_cb_data *cbd = data;
 
236
        struct ofono_phonebook *pb = cbd->user;
 
237
        struct pb_data *pbd = ofono_phonebook_get_data(pb);
 
238
 
213
239
        ofono_phonebook_cb_t cb = cbd->cb;
214
 
        int location;
 
240
        uint16_t location;
215
241
 
216
 
        if (!msg) {
217
 
                DBG("ISI client error: %d", g_isi_client_error(client));
218
 
                goto error;
 
242
        if (g_isi_msg_error(msg) < 0) {
 
243
                CALLBACK_WITH_FAILURE(cb, cbd->data);
 
244
                g_free(cbd);
 
245
                return;
219
246
        }
220
247
 
221
 
        location = decode_read_response(data, len, cbd->user);
222
 
        if (location != -1) {
223
 
                read_next_entry(client, location, read_resp_cb, cbd);
224
 
                return TRUE;
 
248
        if (decode_response(msg, &location, cbd->user)) {
 
249
                read_next_entry(pbd->client, location, read_resp_cb, cbd);
 
250
                return;
225
251
        }
226
252
 
227
253
        CALLBACK_WITH_SUCCESS(cb, cbd->data);
228
 
        goto out;
229
 
 
230
 
error:
231
 
        CALLBACK_WITH_FAILURE(cb, cbd->data);
232
 
 
233
 
out:
234
254
        g_free(cbd);
235
 
        return TRUE;
236
255
}
237
256
 
238
257
static void isi_export_entries(struct ofono_phonebook *pb, const char *storage,
240
259
{
241
260
        struct pb_data *pbd = ofono_phonebook_get_data(pb);
242
261
        struct isi_cb_data *cbd = isi_cb_data_new(pb, cb, data);
243
 
        const unsigned char msg[] = {
 
262
        const uint8_t msg[] = {
244
263
                SIM_PB_REQ_SIM_PB_READ,
245
264
                SIM_PB_READ,
246
265
                2,                              /* number of subblocks */
258
277
                0, SIM_PB_EMAIL,
259
278
                0, 0                            /* filler */
260
279
        };
261
 
 
262
 
        if (!cbd || !pbd)
263
 
                goto error;
264
 
 
265
 
        if (strcmp(storage, "SM"))
266
 
                goto error;
267
 
 
268
 
        if (g_isi_request_make(pbd->client, msg, sizeof(msg), SIM_TIMEOUT,
269
 
                                read_resp_cb, cbd))
 
280
        size_t len = sizeof(msg);
 
281
 
 
282
        if (cbd == NULL || pbd == NULL || strcmp(storage, "SM") != 0)
 
283
                goto error;
 
284
 
 
285
        if (g_isi_client_send(pbd->client, msg, len, read_resp_cb, cbd, NULL))
270
286
                return;
271
287
 
272
288
error:
273
 
        if (cbd)
274
 
                g_free(cbd);
275
 
 
276
289
        CALLBACK_WITH_FAILURE(cb, data);
 
290
        g_free(cbd);
277
291
}
278
292
 
279
 
static gboolean isi_phonebook_register(gpointer user)
 
293
static void reachable_cb(const GIsiMessage *msg, void *data)
280
294
{
281
 
        struct ofono_phonebook *pb = user;
 
295
        struct ofono_phonebook *pb = data;
 
296
 
 
297
        if (g_isi_msg_error(msg) < 0)
 
298
                return;
 
299
 
 
300
        ISI_VERSION_DBG(msg);
282
301
 
283
302
        ofono_phonebook_register(pb);
284
 
 
285
 
        return FALSE;
286
 
}
287
 
 
288
 
static void reachable_cb(GIsiClient *client, gboolean alive, uint16_t object,
289
 
                                void *opaque)
290
 
{
291
 
        struct ofono_phonebook *pb = opaque;
292
 
        const char *debug = NULL;
293
 
 
294
 
        if (!alive) {
295
 
                DBG("Unable to bootstrap phonebook driver");
296
 
                return;
297
 
        }
298
 
 
299
 
        DBG("%s (v%03d.%03d) reachable",
300
 
                pn_resource_name(g_isi_client_resource(client)),
301
 
                g_isi_version_major(client),
302
 
                g_isi_version_minor(client));
303
 
 
304
 
        debug = getenv("OFONO_ISI_DEBUG");
305
 
        if (debug && (strcmp(debug, "all") == 0 || strcmp(debug, "sim") == 0))
306
 
                g_isi_client_set_debug(client, sim_debug, NULL);
307
 
 
308
 
        g_idle_add(isi_phonebook_register, pb);
309
303
}
310
304
 
311
305
static int isi_phonebook_probe(struct ofono_phonebook *pb, unsigned int vendor,
312
306
                                void *user)
313
307
{
314
 
        GIsiModem *idx = user;
315
 
        struct pb_data *data = g_try_new0(struct pb_data, 1);
 
308
        GIsiModem *modem = user;
 
309
        struct pb_data *data;
316
310
 
317
 
        if (!data)
 
311
        data = g_try_new0(struct pb_data, 1);
 
312
        if (data == NULL)
318
313
                return -ENOMEM;
319
314
 
320
 
        data->client = g_isi_client_create(idx, PN_SIM);
321
 
        if (!data->client) {
 
315
        data->client = g_isi_client_create(modem, PN_SIM);
 
316
        if (data->client == NULL) {
322
317
                g_free(data);
323
318
                return -ENOMEM;
324
319
        }
325
320
 
326
321
        ofono_phonebook_set_data(pb, data);
327
322
 
328
 
        if (!g_isi_verify(data->client, reachable_cb, pb))
329
 
                DBG("Unable to verify reachability");
 
323
        g_isi_client_verify(data->client, reachable_cb, pb, NULL);
330
324
 
331
325
        return 0;
332
326
}
335
329
{
336
330
        struct pb_data *data = ofono_phonebook_get_data(pb);
337
331
 
338
 
        if (!data)
339
 
                return;
340
 
 
341
332
        ofono_phonebook_set_data(pb, NULL);
 
333
 
 
334
        if (data == NULL)
 
335
                return;
 
336
 
342
337
        g_isi_client_destroy(data->client);
343
338
        g_free(data);
344
339
}
350
345
        .export_entries         = isi_export_entries
351
346
};
352
347
 
353
 
void isi_phonebook_init()
 
348
void isi_phonebook_init(void)
354
349
{
355
350
        ofono_phonebook_driver_register(&driver);
356
351
}
357
352
 
358
 
void isi_phonebook_exit()
 
353
void isi_phonebook_exit(void)
359
354
{
360
355
        ofono_phonebook_driver_unregister(&driver);
361
356
}