Upgrade ofono to 1.11 and merge to 2.0alpha
[profile/ivi/ofono.git] / drivers / ifxmodem / voicecall.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 #define _GNU_SOURCE
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <errno.h>
31
32 #include <glib.h>
33
34 #include <ofono/log.h>
35 #include <ofono/modem.h>
36 #include <ofono/voicecall.h>
37
38 #include "gatchat.h"
39 #include "gatresult.h"
40
41 #include "common.h"
42 #include "ifxmodem.h"
43
44 static const char *none_prefix[] = { NULL };
45 static const char *xlema_prefix[] = { "+XLEMA:", NULL };
46
47 struct voicecall_data {
48         GSList *calls;
49         unsigned int local_release;
50         GAtChat *chat;
51         char **en_list;
52 };
53
54 struct release_id_req {
55         struct ofono_voicecall *vc;
56         ofono_voicecall_cb_t cb;
57         void *data;
58         int id;
59 };
60
61 struct change_state_req {
62         struct ofono_voicecall *vc;
63         ofono_voicecall_cb_t cb;
64         void *data;
65         int affected_types;
66 };
67
68 static int class_to_call_type(int cls)
69 {
70         switch (cls) {
71         case 1:
72                 return 0;
73         case 4:
74                 return 2;
75         case 8:
76                 return 9;
77         default:
78                 return 1;
79         }
80 }
81
82 static struct ofono_call *create_call(struct ofono_voicecall *vc, int type,
83                                         int direction, int status,
84                                         const char *num, int num_type,
85                                         int clip, int id)
86 {
87         struct voicecall_data *d = ofono_voicecall_get_data(vc);
88         struct ofono_call *call;
89
90         /* Generate a call structure for the waiting call */
91         call = g_try_new(struct ofono_call, 1);
92         if (call == NULL)
93                 return NULL;
94
95         ofono_call_init(call);
96
97         call->id = id;
98         call->type = type;
99         call->direction = direction;
100         call->status = status;
101
102         if (clip != 2) {
103                 strncpy(call->phone_number.number, num,
104                         OFONO_MAX_PHONE_NUMBER_LENGTH);
105                 call->phone_number.type = num_type;
106         }
107
108         call->clip_validity = clip;
109
110         d->calls = g_slist_insert_sorted(d->calls, call, at_util_call_compare);
111
112         return call;
113 }
114
115 static void xcallstat_notify(GAtResult *result, gpointer user_data)
116 {
117         struct ofono_voicecall *vc = user_data;
118         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
119         GAtResultIter iter;
120         int id;
121         int status;
122         GSList *l;
123         struct ofono_call *new_call;
124         struct ofono_call *existing_call = NULL;
125
126         g_at_result_iter_init(&iter, result);
127
128         if (g_at_result_iter_next(&iter, "+XCALLSTAT:") == FALSE)
129                 return;
130
131         if (g_at_result_iter_next_number(&iter, &id) == FALSE)
132                 return;
133
134         if (g_at_result_iter_next_number(&iter, &status) == FALSE)
135                 return;
136
137         l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(id),
138                                 at_util_call_compare_by_id);
139
140         if (l == NULL && status != CALL_STATUS_DIALING &&
141                                 status != CALL_STATUS_INCOMING &&
142                                 status != CALL_STATUS_WAITING) {
143                 ofono_error("Received XCALLSTAT for an untracked"
144                                 " call, this indicates a bug!");
145                 return;
146         }
147
148         if (l)
149                 existing_call = l->data;
150
151         switch (status) {
152         case CALL_STATUS_DISCONNECTED:
153         {
154                 enum ofono_disconnect_reason reason;
155
156                 existing_call->status = status;
157
158                 if (vd->local_release & (1 << existing_call->id))
159                         reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
160                 else
161                         reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
162
163                 ofono_voicecall_disconnected(vc, existing_call->id,
164                                                 reason, NULL);
165
166                 vd->local_release &= ~(1 << existing_call->id);
167                 vd->calls = g_slist_remove(vd->calls, l->data);
168                 g_free(existing_call);
169                 break;
170         }
171         case CALL_STATUS_DIALING:
172         case CALL_STATUS_WAITING:
173         case CALL_STATUS_INCOMING:
174         {
175                 int direction;
176
177                 /* Handle the following situation:
178                  * Active Call + Waiting Call. Active Call is Released.
179                  * The Waiting call becomes Incoming. In this case, no
180                  * need to create a new call. Call status change will be
181                  * triggered from clip_notify.
182                  */
183                 if (existing_call) {
184                         existing_call->status = status;
185                         return;
186                 }
187
188                 if (status == CALL_STATUS_DIALING)
189                         direction = CALL_DIRECTION_MOBILE_ORIGINATED;
190                 else
191                         direction = CALL_DIRECTION_MOBILE_TERMINATED;
192
193                 new_call = create_call(vc, 0, direction, status,
194                                         NULL, 128,
195                                         CLIP_VALIDITY_NOT_AVAILABLE, id);
196                 if (new_call == NULL) {
197                         ofono_error("Unable to malloc. "
198                                         "Call management is fubar");
199                         return;
200                 }
201
202                 new_call->id = id;
203                 break;
204         }
205         case CALL_STATUS_ALERTING:
206         case CALL_STATUS_ACTIVE:
207         case CALL_STATUS_HELD:
208         default:
209                 /* For connected status, simply reset back to active */
210                 if (status == 7)
211                         status = CALL_STATUS_ACTIVE;
212
213                 existing_call->status = status;
214                 ofono_voicecall_notify(vc, existing_call);
215                 break;
216         }
217 }
218
219 static void xem_notify(GAtResult *result, gpointer user_data)
220 {
221         //struct ofono_voicecall *vc = user_data;
222         //struct voicecall_data *vd = ofono_voicecall_get_data(vc);
223         GAtResultIter iter;
224         int state;
225
226         g_at_result_iter_init(&iter, result);
227
228         if (g_at_result_iter_next(&iter, "+XEM:") == FALSE)
229                 return;
230
231         if (g_at_result_iter_next_number(&iter, &state) == FALSE)
232                 return;
233
234         DBG("state %d", state);
235
236         switch (state) {
237         case 0:
238                 ofono_info("Emergency call is finished");
239                 break;
240         case 1:
241                 ofono_info("Emergency call is entered");
242                 break;
243         }
244 }
245
246 static void generic_cb(gboolean ok, GAtResult *result, gpointer user_data)
247 {
248         struct change_state_req *req = user_data;
249         struct voicecall_data *vd = ofono_voicecall_get_data(req->vc);
250         struct ofono_error error;
251
252         decode_at_error(&error, g_at_result_final_response(result));
253
254         if (ok && req->affected_types) {
255                 GSList *l;
256                 struct ofono_call *call;
257
258                 for (l = vd->calls; l; l = l->next) {
259                         call = l->data;
260
261                         if (req->affected_types & (1 << call->status))
262                                 vd->local_release |= (1 << call->id);
263                 }
264         }
265
266         req->cb(&error, req->data);
267 }
268
269 static void release_id_cb(gboolean ok, GAtResult *result,
270                                 gpointer user_data)
271 {
272         struct release_id_req *req = user_data;
273         struct voicecall_data *vd = ofono_voicecall_get_data(req->vc);
274         struct ofono_error error;
275
276         decode_at_error(&error, g_at_result_final_response(result));
277
278         if (ok)
279                 vd->local_release |= 1 << req->id;
280
281         req->cb(&error, req->data);
282 }
283
284 static void atd_cb(gboolean ok, GAtResult *result, gpointer user_data)
285 {
286         struct cb_data *cbd = user_data;
287         ofono_voicecall_cb_t cb = cbd->cb;
288         struct ofono_error error;
289
290         decode_at_error(&error, g_at_result_final_response(result));
291
292         /* Let oFono core will generate a call with the dialed number
293          * inside its dial callback.
294          */
295         cb(&error, cbd->data);
296 }
297
298 static void ifx_dial(struct ofono_voicecall *vc,
299                         const struct ofono_phone_number *ph,
300                         enum ofono_clir_option clir, ofono_voicecall_cb_t cb,
301                         void *data)
302 {
303         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
304         struct cb_data *cbd = cb_data_new(cb, data);
305         char buf[256];
306
307         cbd->user = vc;
308
309         if (ph->type == 145)
310                 snprintf(buf, sizeof(buf), "ATD+%s", ph->number);
311         else
312                 snprintf(buf, sizeof(buf), "ATD%s", ph->number);
313
314         switch (clir) {
315         case OFONO_CLIR_OPTION_INVOCATION:
316                 strcat(buf, "I");
317                 break;
318         case OFONO_CLIR_OPTION_SUPPRESSION:
319                 strcat(buf, "i");
320                 break;
321         default:
322                 break;
323         }
324
325         strcat(buf, ";");
326
327         if (g_at_chat_send(vd->chat, buf, none_prefix,
328                                 atd_cb, cbd, g_free) > 0)
329                 return;
330
331         g_free(cbd);
332
333         CALLBACK_WITH_FAILURE(cb, data);
334 }
335
336 static void ifx_template(const char *cmd, struct ofono_voicecall *vc,
337                         GAtResultFunc result_cb, unsigned int affected_types,
338                         ofono_voicecall_cb_t cb, void *data)
339 {
340         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
341         struct change_state_req *req = g_try_new0(struct change_state_req, 1);
342
343         if (req == NULL)
344                 goto error;
345
346         req->vc = vc;
347         req->cb = cb;
348         req->data = data;
349         req->affected_types = affected_types;
350
351         if (g_at_chat_send(vd->chat, cmd, none_prefix,
352                                 result_cb, req, g_free) > 0)
353                 return;
354
355 error:
356         g_free(req);
357
358         CALLBACK_WITH_FAILURE(cb, data);
359 }
360
361 static void ifx_answer(struct ofono_voicecall *vc,
362                         ofono_voicecall_cb_t cb, void *data)
363 {
364         ifx_template("ATA", vc, generic_cb, 0, cb, data);
365 }
366
367 static void ifx_ath(struct ofono_voicecall *vc,
368                         ofono_voicecall_cb_t cb, void *data)
369 {
370         /* Hangup active + held call, but not waiting */
371         ifx_template("ATH", vc, generic_cb, 0x1f, cb, data);
372 }
373
374 static void ifx_chup(struct ofono_voicecall *vc,
375                         ofono_voicecall_cb_t cb, void *data)
376 {
377         /* Hangup active + but not held or waiting */
378         ifx_template("AT+CHUP", vc, generic_cb, 0x1d, cb, data);
379 }
380
381 static void ifx_hold_all_active(struct ofono_voicecall *vc,
382                                 ofono_voicecall_cb_t cb, void *data)
383 {
384         ifx_template("AT+CHLD=2", vc, generic_cb, 0, cb, data);
385 }
386
387 static void ifx_release_all_held(struct ofono_voicecall *vc,
388                                 ofono_voicecall_cb_t cb, void *data)
389 {
390         unsigned int held_status = 1 << CALL_STATUS_HELD;
391         ifx_template("AT+CHLD=0", vc, generic_cb, held_status, cb, data);
392 }
393
394 static void ifx_set_udub(struct ofono_voicecall *vc,
395                         ofono_voicecall_cb_t cb, void *data)
396 {
397         unsigned int incoming_or_waiting =
398                 (1 << CALL_STATUS_INCOMING) | (1 << CALL_STATUS_WAITING);
399
400         ifx_template("AT+CHLD=0", vc, generic_cb, incoming_or_waiting,
401                         cb, data);
402 }
403
404 static void ifx_release_all_active(struct ofono_voicecall *vc,
405                                         ofono_voicecall_cb_t cb, void *data)
406 {
407         ifx_template("AT+CHLD=1", vc, generic_cb, 0x1, cb, data);
408 }
409
410 static void ifx_release_specific(struct ofono_voicecall *vc, int id,
411                                 ofono_voicecall_cb_t cb, void *data)
412 {
413         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
414         struct release_id_req *req = g_try_new0(struct release_id_req, 1);
415         char buf[32];
416
417         if (req == NULL)
418                 goto error;
419
420         req->vc = vc;
421         req->cb = cb;
422         req->data = data;
423         req->id = id;
424
425         snprintf(buf, sizeof(buf), "AT+CHLD=1%d", id);
426
427         if (g_at_chat_send(vd->chat, buf, none_prefix,
428                                 release_id_cb, req, g_free) > 0)
429                 return;
430
431 error:
432         g_free(req);
433
434         CALLBACK_WITH_FAILURE(cb, data);
435 }
436
437 static void ifx_private_chat(struct ofono_voicecall *vc, int id,
438                                 ofono_voicecall_cb_t cb, void *data)
439 {
440         char buf[32];
441
442         snprintf(buf, sizeof(buf), "AT+CHLD=2%d", id);
443         ifx_template(buf, vc, generic_cb, 0, cb, data);
444 }
445
446 static void ifx_create_multiparty(struct ofono_voicecall *vc,
447                                         ofono_voicecall_cb_t cb, void *data)
448 {
449         ifx_template("AT+CHLD=3", vc, generic_cb, 0, cb, data);
450 }
451
452 static void ifx_transfer(struct ofono_voicecall *vc,
453                         ofono_voicecall_cb_t cb, void *data)
454 {
455         /* Held & Active */
456         unsigned int transfer = 0x1 | 0x2;
457
458         /* Transfer can puts held & active calls together and disconnects
459          * from both.  However, some networks support transferring of
460          * dialing/ringing calls as well.
461          */
462         transfer |= 0x4 | 0x8;
463
464         ifx_template("AT+CHLD=4", vc, generic_cb, transfer, cb, data);
465 }
466
467 static void ifx_deflect(struct ofono_voicecall *vc,
468                         const struct ofono_phone_number *ph,
469                         ofono_voicecall_cb_t cb, void *data)
470 {
471         char buf[128];
472         unsigned int incoming_or_waiting =
473                 (1 << CALL_STATUS_INCOMING) | (1 << CALL_STATUS_WAITING);
474
475         snprintf(buf, sizeof(buf), "AT+CTFR=%s,%d", ph->number, ph->type);
476         ifx_template(buf, vc, generic_cb, incoming_or_waiting, cb, data);
477 }
478
479 static void ifx_swap_without_accept(struct ofono_voicecall *vc,
480                                 ofono_voicecall_cb_t cb, void *data)
481 {
482         ifx_template("AT+CHLD=6", vc, generic_cb, 0, cb, data);
483 }
484
485 static void vts_cb(gboolean ok, GAtResult *result, gpointer user_data)
486 {
487         struct cb_data *cbd = user_data;
488         ofono_voicecall_cb_t cb = cbd->cb;
489         struct ofono_error error;
490
491         decode_at_error(&error, g_at_result_final_response(result));
492         cb(&error, cbd->data);
493 }
494
495 static void ifx_send_dtmf(struct ofono_voicecall *vc, const char *dtmf,
496                         ofono_voicecall_cb_t cb, void *data)
497 {
498         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
499         struct cb_data *cbd = cb_data_new(cb, data);
500         int len = strlen(dtmf);
501         int s;
502         int i;
503         char *buf;
504
505         /* strlen("+VTS=T\;") = 7 + initial AT + null */
506         buf = g_try_new(char, len * 7 + 3);
507         if (buf == NULL)
508                 goto error;
509
510         s = sprintf(buf, "AT+VTS=%c", dtmf[0]);
511
512         for (i = 1; i < len; i++)
513                 s += sprintf(buf + s, ";+VTS=%c", dtmf[i]);
514
515         s = g_at_chat_send(vd->chat, buf, none_prefix,
516                                 vts_cb, cbd, g_free);
517
518         g_free(buf);
519
520         if (s > 0)
521                 return;
522
523 error:
524         g_free(cbd);
525
526         CALLBACK_WITH_FAILURE(cb, data);
527 }
528
529 static void cring_notify(GAtResult *result, gpointer user_data)
530 {
531         struct ofono_voicecall *vc = user_data;
532         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
533         GAtResultIter iter;
534         const char *line;
535         GSList *l;
536         struct ofono_call *call;
537
538         /* Handle the following situation:
539          * Active Call + Waiting Call.  Active Call is Released.  The Waiting
540          * call becomes Incoming and CRING indications are signaled.
541          * Sometimes these arrive before the actual state change notification.
542          * If this happens, simply ignore the CRING when a waiting call
543          * exists (cannot have waiting + incoming in GSM)
544          */
545         if (g_slist_find_custom(vd->calls,
546                                 GINT_TO_POINTER(CALL_STATUS_WAITING),
547                                 at_util_call_compare_by_status))
548                 return;
549
550         l = g_slist_find_custom(vd->calls,
551                                 GINT_TO_POINTER(CALL_STATUS_INCOMING),
552                                 at_util_call_compare_by_status);
553         if (l == NULL) {
554                 ofono_error("CRING received before XCALLSTAT!!!");
555                 return;
556         }
557
558         g_at_result_iter_init(&iter, result);
559
560         if (!g_at_result_iter_next(&iter, "+CRING:"))
561                 return;
562
563         line = g_at_result_iter_raw_line(&iter);
564         if (line == NULL)
565                 return;
566
567         call = l->data;
568
569         /* Ignore everything that is not voice for now */
570         if (!strcasecmp(line, "VOICE"))
571                 call->type = 0;
572         else
573                 call->type = 9;
574
575         /* Assume the CLIP always arrives, and we signal the call there */
576         DBG("cring_notify");
577 }
578
579 static void clip_notify(GAtResult *result, gpointer user_data)
580 {
581         struct ofono_voicecall *vc = user_data;
582         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
583         GAtResultIter iter;
584         const char *num;
585         int type, validity;
586         GSList *l;
587         struct ofono_call *call;
588
589         l = g_slist_find_custom(vd->calls,
590                                 GINT_TO_POINTER(CALL_STATUS_INCOMING),
591                                 at_util_call_compare_by_status);
592         if (l == NULL) {
593                 ofono_error("CLIP for unknown call");
594                 return;
595         }
596
597         g_at_result_iter_init(&iter, result);
598
599         if (!g_at_result_iter_next(&iter, "+CLIP:"))
600                 return;
601
602         if (!g_at_result_iter_next_string(&iter, &num))
603                 return;
604
605         if (!g_at_result_iter_next_number(&iter, &type))
606                 return;
607
608         if (strlen(num) > 0)
609                 validity = 0;
610         else
611                 validity = 2;
612
613         /* Skip subaddr, satype and alpha */
614         g_at_result_iter_skip_next(&iter);
615         g_at_result_iter_skip_next(&iter);
616         g_at_result_iter_skip_next(&iter);
617
618         /* If we have CLI validity field, override our guessed value */
619         g_at_result_iter_next_number(&iter, &validity);
620
621         DBG("clip_notify: %s %d %d", num, type, validity);
622
623         call = l->data;
624
625         strncpy(call->phone_number.number, num,
626                 OFONO_MAX_PHONE_NUMBER_LENGTH);
627         call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
628         call->phone_number.type = type;
629         call->clip_validity = validity;
630
631         if (call->type == 0)
632                 ofono_voicecall_notify(vc, call);
633 }
634
635 static void cnap_notify(GAtResult *result, gpointer user_data)
636 {
637         struct ofono_voicecall *vc = user_data;
638         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
639         GAtResultIter iter;
640         const char *name;
641         int validity;
642         GSList *l;
643         struct ofono_call *call;
644
645         /*
646          * Currently, its not clear which URC will contain the
647          * calling party name for the waiting call.
648          */
649         l = g_slist_find_custom(vd->calls,
650                                 GINT_TO_POINTER(CALL_STATUS_INCOMING),
651                                 at_util_call_compare_by_status);
652         if (l == NULL) {
653                 ofono_error("CNAP for unknown call");
654                 return;
655         }
656
657         g_at_result_iter_init(&iter, result);
658
659         if (!g_at_result_iter_next(&iter, "+CNAP:"))
660                 return;
661
662         if (!g_at_result_iter_next_string(&iter, &name))
663                 return;
664
665         if (strlen(name) > 0)
666                 validity = CNAP_VALIDITY_VALID;
667         else
668                 validity = CNAP_VALIDITY_NOT_AVAILABLE;
669
670         /* If we have CNI validity field, override our guessed value */
671         g_at_result_iter_next_number(&iter, &validity);
672
673         DBG("%s %d", name, validity);
674
675         call = l->data;
676
677         strncpy(call->name, name, OFONO_MAX_CALLER_NAME_LENGTH);
678         call->name[OFONO_MAX_CALLER_NAME_LENGTH] = '\0';
679         call->cnap_validity = validity;
680
681         if (call->type == 0)
682                 ofono_voicecall_notify(vc, call);
683 }
684
685 static void ccwa_notify(GAtResult *result, gpointer user_data)
686 {
687         struct ofono_voicecall *vc = user_data;
688         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
689         GAtResultIter iter;
690         const char *num;
691         int num_type, validity, cls;
692         GSList *l;
693         struct ofono_call *call;
694
695         l = g_slist_find_custom(vd->calls,
696                                 GINT_TO_POINTER(CALL_STATUS_WAITING),
697                                 at_util_call_compare_by_status);
698         if (l == NULL) {
699                 ofono_error("CCWA received before XCALLSTAT!!!");
700                 return;
701         }
702
703         g_at_result_iter_init(&iter, result);
704
705         if (!g_at_result_iter_next(&iter, "+CCWA:"))
706                 return;
707
708         if (!g_at_result_iter_next_string(&iter, &num))
709                 return;
710
711         if (!g_at_result_iter_next_number(&iter, &num_type))
712                 return;
713
714         if (!g_at_result_iter_next_number(&iter, &cls))
715                 return;
716
717         /* Skip alpha field */
718         g_at_result_iter_skip_next(&iter);
719
720         if (strlen(num) > 0)
721                 validity = 0;
722         else
723                 validity = 2;
724
725         /* If we have CLI validity field, override our guessed value */
726         g_at_result_iter_next_number(&iter, &validity);
727
728         DBG("ccwa_notify: %s %d %d %d", num, num_type, cls, validity);
729
730         call = l->data;
731
732         call->type = class_to_call_type(cls);
733         strncpy(call->phone_number.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH);
734         call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
735         call->phone_number.type = num_type;
736         call->clip_validity = validity;
737
738         if (call->type == 0) /* Only notify voice calls */
739                 ofono_voicecall_notify(vc, call);
740 }
741
742 static void xcolp_notify(GAtResult *result, gpointer user_data)
743 {
744         struct ofono_voicecall *vc = user_data;
745         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
746         GAtResultIter iter;
747         const char *num;
748         int type, call_id;
749         GSList *l;
750         struct ofono_call *call;
751
752         g_at_result_iter_init(&iter, result);
753
754         if (!g_at_result_iter_next(&iter, "+XCOLP:"))
755                 return;
756
757         if (!g_at_result_iter_next_number(&iter, &call_id))
758                 return;
759
760         if (!g_at_result_iter_next_string(&iter, &num))
761                 return;
762
763         if (!g_at_result_iter_next_number(&iter, &type))
764                 return;
765
766         if (strlen(num) == 0) {
767                 ofono_error("XCOLP received with invalid number!!!");
768                 return;
769         }
770
771         DBG("xcolp_notify: %d %s %d", call_id, num, type);
772
773         l = g_slist_find_custom(vd->calls,
774                                 GINT_TO_POINTER(call_id),
775                                 at_util_call_compare_by_id);
776         if (l == NULL) {
777                 ofono_error("XCOLP for unknown call");
778                 return;
779         }
780
781         call = l->data;
782
783         strncpy(call->phone_number.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH);
784         call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
785         call->phone_number.type = type;
786         call->clip_validity = CLIP_VALIDITY_VALID;
787
788         ofono_voicecall_notify(vc, call);
789 }
790
791 static void xlema_notify(GAtResult *result, gpointer user_data)
792 {
793         struct ofono_voicecall *vc = user_data;
794         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
795         GAtResultIter iter;
796         int index, total_cnt;
797         const char *number;
798         int len;
799         int count = (vd->en_list == NULL) ? 0 : g_strv_length(vd->en_list);
800
801         g_at_result_iter_init(&iter, result);
802
803         if (!g_at_result_iter_next(&iter, "+XLEMA:"))
804                 return;
805
806         if (!g_at_result_iter_next_number(&iter, &index))
807                 return;
808
809         if (!g_at_result_iter_next_number(&iter, &total_cnt))
810                 return;
811
812         if (!g_at_result_iter_next_string(&iter, &number))
813                 return;
814
815         /* Skip category */
816         if (g_at_result_iter_skip_next(&iter) == FALSE)
817                 goto done;
818
819         /* Skip presence */
820         if (g_at_result_iter_skip_next(&iter) == FALSE)
821                 goto done;
822
823         /* If we succeed here, then the number is from NVM or NITZ */
824         if (g_at_result_iter_skip_next(&iter) == FALSE)
825                 goto done;
826
827         if (vd->en_list == NULL)
828                 vd->en_list = g_new0(char *, total_cnt + 1);
829
830         len = strspn(number, "0123456789");
831         vd->en_list[count] = g_strndup(number, len);
832
833         if (number[len] != '\0')
834                 ofono_warn("Malformed emergency number: %.*s", len, number);
835
836 done:
837         if (index != total_cnt)
838                 return;
839
840         if (vd->en_list) {
841                 ofono_voicecall_en_list_notify(vc, vd->en_list);
842
843                 g_strfreev(vd->en_list);
844                 vd->en_list = NULL;
845         }
846 }
847
848 static void xlema_read(gboolean ok, GAtResult *result, gpointer user_data)
849 {
850         struct ofono_voicecall *vc = user_data;
851         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
852         GAtResultIter iter;
853         int num = 0;
854         int index, total_cnt;
855         const char *number;
856         int len;
857
858         if (!ok) {
859                 DBG("Emergency number list read failed");
860                 return;
861         }
862
863         g_at_result_iter_init(&iter, result);
864
865         while (g_at_result_iter_next(&iter, "+XLEMA:"))
866                 num += 1;
867
868         vd->en_list = g_new0(char *, num + 1);
869
870         num = 0;
871         g_at_result_iter_init(&iter, result);
872
873         while (g_at_result_iter_next(&iter, "+XLEMA:")) {
874                 if (!g_at_result_iter_next_number(&iter, &index))
875                         continue;
876
877                 if (!g_at_result_iter_next_number(&iter, &total_cnt))
878                         continue;
879
880                 if (!g_at_result_iter_next_string(&iter, &number))
881                         continue;
882
883                 len = strspn(number, "0123456789");
884                 vd->en_list[num++] = g_strndup(number, len);
885
886                 if (number[len] != '\0')
887                         ofono_warn("Malformed emergency number: %.*s",
888                                                         len, number);
889         }
890
891         ofono_voicecall_en_list_notify(vc, vd->en_list);
892
893         g_strfreev(vd->en_list);
894         vd->en_list = NULL;
895 }
896
897 static void cssi_notify(GAtResult *result, gpointer user_data)
898 {
899         struct ofono_voicecall *vc = user_data;
900         GAtResultIter iter;
901         int code, index;
902
903         g_at_result_iter_init(&iter, result);
904
905         if (!g_at_result_iter_next(&iter, "+CSSI:"))
906                 return;
907
908         if (!g_at_result_iter_next_number(&iter, &code))
909                 return;
910
911         if (!g_at_result_iter_next_number(&iter, &index))
912                 index = 0;
913
914         ofono_voicecall_ssn_mo_notify(vc, 0, code, index);
915 }
916
917 static void cssu_notify(GAtResult *result, gpointer user_data)
918 {
919         struct ofono_voicecall *vc = user_data;
920         GAtResultIter iter;
921         int code;
922         int index;
923         const char *num;
924         struct ofono_phone_number ph;
925
926         ph.number[0] = '\0';
927         ph.type = 129;
928
929         g_at_result_iter_init(&iter, result);
930
931         if (!g_at_result_iter_next(&iter, "+CSSU:"))
932                 return;
933
934         if (!g_at_result_iter_next_number(&iter, &code))
935                 return;
936
937         if (!g_at_result_iter_next_number_default(&iter, -1, &index))
938                 goto out;
939
940         if (!g_at_result_iter_next_string(&iter, &num))
941                 goto out;
942
943         strncpy(ph.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH);
944
945         if (!g_at_result_iter_next_number(&iter, &ph.type))
946                 return;
947
948 out:
949         ofono_voicecall_ssn_mt_notify(vc, 0, code, index, &ph);
950 }
951
952 static void ifx_voicecall_initialized(gboolean ok, GAtResult *result,
953                                         gpointer user_data)
954 {
955         struct ofono_voicecall *vc = user_data;
956         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
957
958         DBG("voicecall_init: registering to notifications");
959
960         g_at_chat_register(vd->chat, "+CRING:", cring_notify, FALSE, vc, NULL);
961         g_at_chat_register(vd->chat, "+CLIP:", clip_notify, FALSE, vc, NULL);
962         g_at_chat_register(vd->chat, "+CNAP:", cnap_notify, FALSE, vc, NULL);
963         g_at_chat_register(vd->chat, "+CCWA:", ccwa_notify, FALSE, vc, NULL);
964         g_at_chat_register(vd->chat, "+XEM:", xem_notify, FALSE, vc, NULL);
965         g_at_chat_register(vd->chat, "+XCALLSTAT:", xcallstat_notify,
966                                                         FALSE, vc, NULL);
967         g_at_chat_register(vd->chat, "+XCOLP:", xcolp_notify, FALSE, vc, NULL);
968         g_at_chat_register(vd->chat, "+XLEMA:", xlema_notify, FALSE, vc, NULL);
969         g_at_chat_register(vd->chat, "+CSSI:", cssi_notify, FALSE, vc, NULL);
970         g_at_chat_register(vd->chat, "+CSSU:", cssu_notify, FALSE, vc, NULL);
971         /* Enable emergency number list notification */
972         g_at_chat_send(vd->chat, "AT+XLEMA=1", xlema_prefix, xlema_read, vc,
973                                                                         NULL);
974
975         ofono_voicecall_register(vc);
976 }
977
978 static int ifx_voicecall_probe(struct ofono_voicecall *vc, unsigned int vendor,
979                                 void *data)
980 {
981         GAtChat *chat = data;
982         struct voicecall_data *vd;
983
984         vd = g_try_new0(struct voicecall_data, 1);
985         if (vd == NULL)
986                 return -ENOMEM;
987
988         vd->chat = g_at_chat_clone(chat);
989
990         ofono_voicecall_set_data(vc, vd);
991
992         g_at_chat_send(vd->chat, "AT+XCALLSTAT=1", none_prefix, NULL, NULL,
993                         NULL);
994         g_at_chat_send(vd->chat, "AT+XEMC=1", none_prefix, NULL, NULL, NULL);
995         g_at_chat_send(vd->chat, "AT+XCOLP=1", none_prefix, NULL, NULL, NULL);
996
997         g_at_chat_send(vd->chat, "AT+CRC=1", none_prefix, NULL, NULL, NULL);
998         g_at_chat_send(vd->chat, "AT+CLIP=1", none_prefix, NULL, NULL, NULL);
999         g_at_chat_send(vd->chat, "AT+CNAP=1", none_prefix, NULL, NULL, NULL);
1000         g_at_chat_send(vd->chat, "AT+CSSN=1,1", none_prefix, NULL, NULL, NULL);
1001         g_at_chat_send(vd->chat, "AT+CCWA=1", none_prefix,
1002                                 ifx_voicecall_initialized, vc, NULL);
1003
1004         return 0;
1005 }
1006
1007 static void ifx_voicecall_remove(struct ofono_voicecall *vc)
1008 {
1009         struct voicecall_data *vd = ofono_voicecall_get_data(vc);
1010
1011         g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
1012         g_slist_free(vd->calls);
1013
1014         g_strfreev(vd->en_list);
1015
1016         ofono_voicecall_set_data(vc, NULL);
1017
1018         g_at_chat_unref(vd->chat);
1019         g_free(vd);
1020 }
1021
1022 static struct ofono_voicecall_driver driver = {
1023         .name                   = "ifxmodem",
1024         .probe                  = ifx_voicecall_probe,
1025         .remove                 = ifx_voicecall_remove,
1026         .dial                   = ifx_dial,
1027         .answer                 = ifx_answer,
1028         .hangup_all             = ifx_ath,
1029         .hangup_active          = ifx_chup,
1030         .hold_all_active        = ifx_hold_all_active,
1031         .release_all_held       = ifx_release_all_held,
1032         .set_udub               = ifx_set_udub,
1033         .release_all_active     = ifx_release_all_active,
1034         .release_specific       = ifx_release_specific,
1035         .private_chat           = ifx_private_chat,
1036         .create_multiparty      = ifx_create_multiparty,
1037         .transfer               = ifx_transfer,
1038         .deflect                = ifx_deflect,
1039         .swap_without_accept    = ifx_swap_without_accept,
1040         .send_tones             = ifx_send_dtmf
1041 };
1042
1043 void ifx_voicecall_init(void)
1044 {
1045         ofono_voicecall_driver_register(&driver);
1046 }
1047
1048 void ifx_voicecall_exit(void)
1049 {
1050         ofono_voicecall_driver_unregister(&driver);
1051 }