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

« back to all changes in this revision

Viewing changes to drivers/isimodem/call-settings.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:
84
84
                break;
85
85
 
86
86
        default:
87
 
                DBG("Unknown BSC value %d, please report\n", bsc);
 
87
                DBG("Unknown BSC value %d, please report", bsc);
88
88
                break;
89
89
        }
90
90
}
91
91
 
92
 
static gboolean query_resp_cb(GIsiClient *client,
93
 
                                const void *restrict data, size_t len,
94
 
                                uint16_t object, void *opaque)
95
 
{
96
 
        GIsiSubBlockIter iter;
97
 
        const unsigned char *msg = data;
98
 
        struct isi_cb_data *cbd = opaque;
 
92
static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid)
 
93
{
 
94
        if (g_isi_msg_error(msg) < 0) {
 
95
                DBG("Error: %s", strerror(-g_isi_msg_error(msg)));
 
96
                return FALSE;
 
97
        }
 
98
 
 
99
        if (g_isi_msg_id(msg) != msgid) {
 
100
                DBG("Unexpected msg: %s",
 
101
                        ss_message_id_name(g_isi_msg_id(msg)));
 
102
                return FALSE;
 
103
        }
 
104
        return TRUE;
 
105
}
 
106
 
 
107
static gboolean decode_gsm_bsc_info(GIsiSubBlockIter *iter, uint32_t *mask)
 
108
{
 
109
        uint8_t num;
 
110
        uint8_t *bsc;
 
111
        uint8_t i;
 
112
 
 
113
        if (!g_isi_sb_iter_get_byte(iter, &num, 2) ||
 
114
                        !g_isi_sb_iter_get_struct(iter, (void **) &bsc, num, 3))
 
115
                return FALSE;
 
116
 
 
117
        for (i = 0; i < num; i++)
 
118
                update_status_mask(mask, bsc[i]);
 
119
 
 
120
        return TRUE;
 
121
}
 
122
 
 
123
static void query_resp_cb(const GIsiMessage *msg, void *data)
 
124
{
 
125
        struct isi_cb_data *cbd = data;
99
126
        ofono_call_settings_status_cb_t cb = cbd->cb;
100
 
        guint32 mask = 0;
101
 
 
102
 
        if (!msg) {
103
 
                DBG("ISI client error: %d", g_isi_client_error(client));
104
 
                goto error;
105
 
        }
106
 
 
107
 
        if (len < 7 || msg[0] != SS_SERVICE_COMPLETED_RESP)
108
 
                goto error;
109
 
 
110
 
        if (msg[1] != SS_INTERROGATION)
111
 
                goto error;
112
 
 
113
 
        for (g_isi_sb_iter_init(&iter, msg, len, 7);
114
 
                g_isi_sb_iter_is_valid(&iter);
115
 
                g_isi_sb_iter_next(&iter)) {
116
 
 
117
 
                switch (g_isi_sb_iter_get_id(&iter)) {
118
 
 
119
 
                case SS_STATUS_RESULT:
120
 
                        break;
121
 
 
122
 
                case SS_GSM_ADDITIONAL_INFO:
123
 
                        break;
124
 
 
125
 
                case SS_GSM_BSC_INFO: {
126
 
 
127
 
                        guint8 bsc;
128
 
                        guint8 count;
129
 
                        guint8 i;
130
 
 
131
 
                        if (!g_isi_sb_iter_get_byte(&iter, &count, 2))
132
 
                                goto error;
133
 
 
134
 
                        for (i = 0; i < count; i++) {
135
 
                                if (!g_isi_sb_iter_get_byte(&iter, &bsc, 3 + i))
136
 
                                        goto error;
137
 
                                update_status_mask(&mask, bsc);
138
 
                        }
139
 
                        break;
140
 
                }
141
 
                default:
142
 
                        DBG("Skipping sub-block: %s (%zd bytes)",
143
 
                                ss_subblock_name(g_isi_sb_iter_get_id(&iter)),
144
 
                                g_isi_sb_iter_get_len(&iter));
145
 
                        break;
146
 
                }
147
 
        }
148
 
 
149
 
        DBG("status_mask %d\n", mask);
150
 
        CALLBACK_WITH_SUCCESS(cb, mask, cbd->data);
151
 
        goto out;
 
127
        GIsiSubBlockIter iter;
 
128
        uint8_t service;
 
129
        uint32_t mask = 0;
 
130
 
 
131
        if (!check_response_status(msg, SS_SERVICE_COMPLETED_RESP))
 
132
                goto error;
 
133
 
 
134
        if (!g_isi_msg_data_get_byte(msg, 0, &service) ||
 
135
                        service != SS_INTERROGATION)
 
136
                goto error;
 
137
 
 
138
        for (g_isi_sb_iter_init(&iter, msg, 6);
 
139
                        g_isi_sb_iter_is_valid(&iter);
 
140
                        g_isi_sb_iter_next(&iter)) {
 
141
 
 
142
                if (g_isi_sb_iter_get_id(&iter) != SS_GSM_BSC_INFO)
 
143
                        continue;
 
144
 
 
145
                if (!decode_gsm_bsc_info(&iter, &mask))
 
146
                        goto error;
 
147
 
 
148
                CALLBACK_WITH_SUCCESS(cb, mask, cbd->data);
 
149
                return;
 
150
        }
152
151
 
153
152
error:
154
153
        CALLBACK_WITH_FAILURE(cb, 0, cbd->data);
155
 
 
156
 
out:
157
 
        g_free(cbd);
158
 
        return TRUE;
159
 
 
160
154
}
161
155
 
162
156
static void isi_cw_query(struct ofono_call_settings *cs, int cls,
165
159
        struct settings_data *sd = ofono_call_settings_get_data(cs);
166
160
        struct isi_cb_data *cbd = isi_cb_data_new(cs, cb, data);
167
161
 
168
 
        unsigned char msg[] = {
 
162
        const uint8_t msg[] = {
169
163
                SS_SERVICE_REQ,
170
164
                SS_INTERROGATION,
171
165
                SS_ALL_TELE_AND_BEARER,
175
169
                0 /* Subblock count */
176
170
        };
177
171
 
178
 
        DBG("waiting class %d\n", cls);
179
 
 
180
 
        if (!cbd || !sd)
 
172
        if (cbd == NULL || sd == NULL)
181
173
                goto error;
182
174
 
183
 
        if (g_isi_request_make(sd->client, msg, sizeof(msg), SS_TIMEOUT,
184
 
                                query_resp_cb, cbd))
 
175
        if (g_isi_client_send(sd->client, msg, sizeof(msg),
 
176
                                query_resp_cb, cbd, g_free))
185
177
                return;
186
178
 
187
179
error:
189
181
        g_free(cbd);
190
182
}
191
183
 
192
 
static gboolean set_resp_cb(GIsiClient *client,
193
 
                                const void *restrict data, size_t len,
194
 
                                uint16_t object, void *opaque)
 
184
static void set_resp_cb(const GIsiMessage *msg, void *data)
195
185
{
196
 
        GIsiSubBlockIter iter;
197
 
        const unsigned char *msg = data;
198
 
        struct isi_cb_data *cbd = opaque;
 
186
        struct isi_cb_data *cbd = data;
199
187
        ofono_call_settings_set_cb_t cb = cbd->cb;
200
 
 
201
 
        if (len < 7 || msg[0] != SS_SERVICE_COMPLETED_RESP)
202
 
                goto error;
203
 
 
204
 
        if (msg[1] != SS_ACTIVATION && msg[1] != SS_DEACTIVATION)
205
 
                goto error;
206
 
 
207
 
        for (g_isi_sb_iter_init(&iter, msg, len, 7);
208
 
                g_isi_sb_iter_is_valid(&iter);
209
 
                g_isi_sb_iter_next(&iter)) {
210
 
 
211
 
                switch (g_isi_sb_iter_get_id(&iter)) {
212
 
 
213
 
                case SS_GSM_ADDITIONAL_INFO:
214
 
                        break;
215
 
 
216
 
                case SS_GSM_DATA: {
217
 
 
218
 
                        guint8 status;
219
 
 
220
 
                        if (!g_isi_sb_iter_get_byte(&iter, &status, 2))
221
 
                                goto error;
222
 
 
223
 
                        if ((status & SS_GSM_ACTIVE)
224
 
                                && (msg[1] == SS_DEACTIVATION))
225
 
                                goto error;
226
 
 
227
 
                        if (!(status & SS_GSM_ACTIVE)
228
 
                                && (msg[1] == SS_ACTIVATION))
229
 
                                goto error;
230
 
 
231
 
                        break;
232
 
                }
233
 
                default:
234
 
                        DBG("Skipping sub-block: %s (%zd bytes)",
235
 
                                ss_subblock_name(g_isi_sb_iter_get_id(&iter)),
236
 
                                g_isi_sb_iter_get_len(&iter));
237
 
                        break;
238
 
                }
 
188
        GIsiSubBlockIter iter;
 
189
        uint8_t service;
 
190
        uint8_t status;
 
191
 
 
192
        if (!check_response_status(msg, SS_SERVICE_COMPLETED_RESP))
 
193
                goto error;
 
194
 
 
195
        if (!g_isi_msg_data_get_byte(msg, 0, &service))
 
196
                goto error;
 
197
 
 
198
        if (service != SS_ACTIVATION && service != SS_DEACTIVATION)
 
199
                goto error;
 
200
 
 
201
        for (g_isi_sb_iter_init(&iter, msg, 6);
 
202
                        g_isi_sb_iter_is_valid(&iter);
 
203
                        g_isi_sb_iter_next(&iter)) {
 
204
 
 
205
                if (g_isi_sb_iter_get_id(&iter) != SS_GSM_DATA)
 
206
                        continue;
 
207
 
 
208
                if (!g_isi_sb_iter_get_byte(&iter, &status, 2))
 
209
                        goto error;
 
210
 
 
211
                if ((status & SS_GSM_ACTIVE) && (service == SS_DEACTIVATION))
 
212
                        goto error;
 
213
 
 
214
                if (!(status & SS_GSM_ACTIVE) && (service == SS_ACTIVATION))
 
215
                        goto error;
 
216
 
 
217
                CALLBACK_WITH_SUCCESS(cb, cbd->data);
 
218
                return;
239
219
        }
240
220
 
241
 
        CALLBACK_WITH_SUCCESS(cb, cbd->data);
242
 
        goto out;
243
 
 
244
221
error:
245
222
        CALLBACK_WITH_FAILURE(cb, cbd->data);
246
 
 
247
 
out:
248
 
        g_free(cbd);
249
 
        return TRUE;
250
 
 
251
223
}
252
224
 
253
225
static void isi_cw_set(struct ofono_call_settings *cs, int mode, int cls,
256
228
        struct settings_data *sd = ofono_call_settings_get_data(cs);
257
229
        struct isi_cb_data *cbd = isi_cb_data_new(cs, cb, data);
258
230
 
259
 
        unsigned char msg[] = {
 
231
        const uint8_t msg[] = {
260
232
                SS_SERVICE_REQ,
261
233
                mode ? SS_ACTIVATION : SS_DEACTIVATION,
262
234
                SS_ALL_TELE_AND_BEARER,
266
238
                0  /* Subblock count */
267
239
        };
268
240
 
269
 
        DBG("waiting mode %d class %d\n", mode, cls);
270
 
 
271
 
        if (!cbd || !sd)
 
241
        if (cbd == NULL || sd == NULL)
272
242
                goto error;
273
243
 
274
 
        if (g_isi_request_make(sd->client, msg, sizeof(msg), SS_TIMEOUT,
275
 
                                set_resp_cb, cbd))
 
244
        if (g_isi_client_send(sd->client, msg, sizeof(msg),
 
245
                                set_resp_cb, cbd, g_free))
276
246
                return;
277
247
 
278
248
error:
280
250
        g_free(cbd);
281
251
}
282
252
 
283
 
static gboolean isi_call_settings_register(gpointer user)
 
253
static void reachable_cb(const GIsiMessage *msg, void *data)
284
254
{
285
 
        struct ofono_call_settings *cs = user;
 
255
        struct ofono_call_settings *cs = data;
 
256
 
 
257
        if (g_isi_msg_error(msg) < 0)
 
258
                return;
 
259
 
 
260
        ISI_VERSION_DBG(msg);
286
261
 
287
262
        ofono_call_settings_register(cs);
288
 
 
289
 
        return FALSE;
290
 
}
291
 
 
292
 
static void reachable_cb(GIsiClient *client, gboolean alive, uint16_t object,
293
 
                                void *opaque)
294
 
{
295
 
        struct ofono_call_settings *cs = opaque;
296
 
        const char *debug = NULL;
297
 
 
298
 
        if (!alive) {
299
 
                DBG("Unable to bootstrap call settings driver");
300
 
                return;
301
 
        }
302
 
 
303
 
        DBG("%s (v%03d.%03d) reachable",
304
 
                pn_resource_name(g_isi_client_resource(client)),
305
 
                g_isi_version_major(client),
306
 
                g_isi_version_minor(client));
307
 
 
308
 
        debug = getenv("OFONO_ISI_DEBUG");
309
 
        if (debug && (strcmp(debug, "all") == 0 || strcmp(debug, "ss") == 0))
310
 
                g_isi_client_set_debug(client, ss_debug, NULL);
311
 
 
312
 
        g_idle_add(isi_call_settings_register, cs);
313
 
}
314
 
 
 
263
}
315
264
 
316
265
static int isi_call_settings_probe(struct ofono_call_settings *cs,
317
266
                                        unsigned int vendor, void *user)
318
267
{
319
 
        GIsiModem *idx = user;
320
 
        struct settings_data *data;
321
 
 
322
 
        data = g_try_new0(struct settings_data, 1);
323
 
 
324
 
        if (!data)
325
 
                return -ENOMEM;
326
 
 
327
 
        data->client = g_isi_client_create(idx, PN_SS);
328
 
 
329
 
        if (!data->client)
330
 
                return -ENOMEM;
331
 
 
332
 
        ofono_call_settings_set_data(cs, data);
333
 
 
334
 
        if (!g_isi_verify(data->client, reachable_cb, cs))
335
 
                DBG("Unable to verify reachability");
 
268
        GIsiModem *modem = user;
 
269
        struct settings_data *sd;
 
270
 
 
271
        sd = g_try_new0(struct settings_data, 1);
 
272
        if (sd == NULL)
 
273
                return -ENOMEM;
 
274
 
 
275
        sd->client = g_isi_client_create(modem, PN_SS);
 
276
        if (sd->client == NULL) {
 
277
                g_free(sd);
 
278
                return -ENOMEM;
 
279
        }
 
280
 
 
281
        ofono_call_settings_set_data(cs, sd);
 
282
 
 
283
        g_isi_client_verify(sd->client, reachable_cb, cs, NULL);
336
284
 
337
285
        return 0;
338
286
}
341
289
{
342
290
        struct settings_data *data = ofono_call_settings_get_data(cs);
343
291
 
344
 
        if (!data)
345
 
                return;
346
 
 
347
292
        ofono_call_settings_set_data(cs, NULL);
 
293
 
 
294
        if (data == NULL)
 
295
                return;
 
296
 
348
297
        g_isi_client_destroy(data->client);
349
298
        g_free(data);
350
299
}
362
311
        .cw_set                 = isi_cw_set
363
312
};
364
313
 
365
 
void isi_call_settings_init()
 
314
void isi_call_settings_init(void)
366
315
{
367
316
        ofono_call_settings_driver_register(&driver);
368
317
}
369
318
 
370
 
void isi_call_settings_exit()
 
319
void isi_call_settings_exit(void)
371
320
{
372
321
        ofono_call_settings_driver_unregister(&driver);
373
322
}