~cyphermox/bluez/5.23

« back to all changes in this revision

Viewing changes to .pc/02_disable_hal.patch/audio/telephony-maemo6.c

  • Committer: Package Import Robot
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2012-01-24 05:35:09 UTC
  • mfrom: (1.5.11) (7.1.6 experimental)
  • Revision ID: package-import@ubuntu.com-20120124053509-uwpwqi783lz08wm3
Tags: 4.98-1
* New upstream release.
* Update debian/bluetooth-dbus.conf.
* Update debian/control.
  Add Multi-Arch: foreign to bluez.

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
 
39
39
#include <bluetooth/sdp.h>
40
40
 
41
 
#include "glib-helper.h"
 
41
#include "glib-compat.h"
42
42
#include "log.h"
43
43
#include "telephony.h"
44
44
#include "error.h"
113
113
#define CSD_SIMPB_TYPE_EN                       "EN"
114
114
#define CSD_SIMPB_TYPE_MSISDN                   "MSISDN"
115
115
 
 
116
/* OHM plugin D-Bus definitions */
 
117
#define OHM_BUS_NAME            "com.nokia.NonGraphicFeedback1"
 
118
#define OHM_INTERFACE           "com.nokia.NonGraphicFeedback1"
 
119
#define OHM_PATH                "/com/nokia/NonGraphicFeedback1"
 
120
 
 
121
/* tone-genenerator D-Bus definitions */
 
122
#define TONEGEN_BUS_NAME        "com.Nokia.Telephony.Tones"
 
123
#define TONEGEN_INTERFACE       "com.Nokia.Telephony.Tones"
 
124
#define TONEGEN_PATH            "/com/Nokia/Telephony/Tones"
 
125
 
 
126
/* tone-generator DTMF definitions */
 
127
#define DTMF_ASTERISK   10
 
128
#define DTMF_HASHMARK   11
 
129
#define DTMF_A          12
 
130
#define DTMF_B          13
 
131
#define DTMF_C          14
 
132
#define DTMF_D          15
 
133
 
 
134
#define FEEDBACK_TONE_DURATION                  200
 
135
 
116
136
struct csd_call {
117
137
        char *object_path;
118
138
        int status;
153
173
/* Reference count for determining the call indicator status */
154
174
static GSList *active_calls = NULL;
155
175
 
 
176
/* Queue of DTMF tones to play */
 
177
static GSList *tones = NULL;
 
178
static guint create_tones_timer = 0;
 
179
 
156
180
static char *msisdn = NULL;     /* Subscriber number */
157
181
static char *vmbx = NULL;       /* Voice mailbox number */
158
182
 
205
229
        "???"
206
230
};
207
231
 
 
232
static int send_method_call(const char *dest, const char *path,
 
233
                                const char *interface, const char *method,
 
234
                                DBusPendingCallNotifyFunction cb,
 
235
                                void *user_data, int type, ...)
 
236
{
 
237
        DBusMessage *msg;
 
238
        DBusPendingCall *call;
 
239
        va_list args;
 
240
        struct pending_req *req;
 
241
 
 
242
        msg = dbus_message_new_method_call(dest, path, interface, method);
 
243
        if (!msg) {
 
244
                error("Unable to allocate new D-Bus %s message", method);
 
245
                return -ENOMEM;
 
246
        }
 
247
 
 
248
        va_start(args, type);
 
249
 
 
250
        if (!dbus_message_append_args_valist(msg, type, args)) {
 
251
                dbus_message_unref(msg);
 
252
                va_end(args);
 
253
                return -EIO;
 
254
        }
 
255
 
 
256
        va_end(args);
 
257
 
 
258
        if (!cb) {
 
259
                g_dbus_send_message(connection, msg);
 
260
                return 0;
 
261
        }
 
262
 
 
263
        if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
 
264
                error("Sending %s failed", method);
 
265
                dbus_message_unref(msg);
 
266
                return -EIO;
 
267
        }
 
268
 
 
269
        dbus_pending_call_set_notify(call, cb, user_data, NULL);
 
270
 
 
271
        req = g_new0(struct pending_req, 1);
 
272
        req->call = call;
 
273
        req->user_data = user_data;
 
274
 
 
275
        pending = g_slist_prepend(pending, req);
 
276
        dbus_message_unref(msg);
 
277
 
 
278
        return 0;
 
279
}
 
280
 
208
281
static struct csd_call *find_call(const char *path)
209
282
{
210
283
        GSList *l;
320
393
        return 0;
321
394
}
322
395
 
 
396
static struct pending_req *find_request(const DBusPendingCall *call)
 
397
{
 
398
        GSList *l;
 
399
 
 
400
        for (l = pending; l; l = l->next) {
 
401
                struct pending_req *req = l->data;
 
402
 
 
403
                if (req->call == call)
 
404
                        return req;
 
405
        }
 
406
 
 
407
        return NULL;
 
408
}
 
409
 
 
410
static void pending_req_finalize(void *data)
 
411
{
 
412
        struct pending_req *req = data;
 
413
 
 
414
        if (!dbus_pending_call_get_completed(req->call))
 
415
                dbus_pending_call_cancel(req->call);
 
416
 
 
417
        dbus_pending_call_unref(req->call);
 
418
        g_free(req);
 
419
}
 
420
 
 
421
static void remove_pending(DBusPendingCall *call)
 
422
{
 
423
        struct pending_req *req = find_request(call);
 
424
 
 
425
        pending = g_slist_remove(pending, req);
 
426
        pending_req_finalize(req);
 
427
}
 
428
 
 
429
static void stop_ringtone_reply(DBusPendingCall *call, void *user_data)
 
430
{
 
431
        struct csd_call *coming = user_data;
 
432
 
 
433
        remove_pending(call);
 
434
        answer_call(coming);
 
435
}
 
436
 
 
437
static int stop_ringtone_and_answer(struct csd_call *call)
 
438
{
 
439
        int ret;
 
440
 
 
441
        ret = send_method_call(OHM_BUS_NAME, OHM_PATH,
 
442
                                OHM_INTERFACE, "StopRingtone",
 
443
                                stop_ringtone_reply, call,
 
444
                                DBUS_TYPE_INVALID);
 
445
        if (ret < 0)
 
446
                return answer_call(call);
 
447
 
 
448
        return 0;
 
449
}
 
450
 
323
451
static int split_call(struct csd_call *call)
324
452
{
325
453
        DBusMessage *msg;
451
579
        }
452
580
}
453
581
 
454
 
static void pending_req_finalize(void *data)
455
 
{
456
 
        struct pending_req *req = data;
457
 
 
458
 
        if (!dbus_pending_call_get_completed(req->call))
459
 
                dbus_pending_call_cancel(req->call);
460
 
 
461
 
        dbus_pending_call_unref(req->call);
462
 
        g_free(req);
463
 
}
464
 
 
465
582
static void remove_pending_by_data(gpointer data, gpointer user_data)
466
583
{
467
584
        struct pending_req *req = data;
545
662
                return;
546
663
        }
547
664
 
548
 
        if (answer_call(call) < 0)
 
665
        if (stop_ringtone_and_answer(call) < 0)
549
666
                telephony_answer_call_rsp(telephony_device,
550
667
                                                CME_ERROR_AG_FAILURE);
551
668
        else
552
669
                telephony_answer_call_rsp(telephony_device, CME_ERROR_NONE);
553
670
}
554
671
 
555
 
static int send_method_call(const char *dest, const char *path,
556
 
                                const char *interface, const char *method,
557
 
                                DBusPendingCallNotifyFunction cb,
558
 
                                void *user_data, int type, ...)
559
 
{
560
 
        DBusMessage *msg;
561
 
        DBusPendingCall *call;
562
 
        va_list args;
563
 
        struct pending_req *req;
564
 
 
565
 
        msg = dbus_message_new_method_call(dest, path, interface, method);
566
 
        if (!msg) {
567
 
                error("Unable to allocate new D-Bus %s message", method);
568
 
                return -ENOMEM;
569
 
        }
570
 
 
571
 
        va_start(args, type);
572
 
 
573
 
        if (!dbus_message_append_args_valist(msg, type, args)) {
574
 
                dbus_message_unref(msg);
575
 
                va_end(args);
576
 
                return -EIO;
577
 
        }
578
 
 
579
 
        va_end(args);
580
 
 
581
 
        if (!cb) {
582
 
                g_dbus_send_message(connection, msg);
583
 
                return 0;
584
 
        }
585
 
 
586
 
        if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
587
 
                error("Sending %s failed", method);
588
 
                dbus_message_unref(msg);
589
 
                return -EIO;
590
 
        }
591
 
 
592
 
        dbus_pending_call_set_notify(call, cb, user_data, NULL);
593
 
 
594
 
        req = g_new0(struct pending_req, 1);
595
 
        req->call = call;
596
 
        req->user_data = user_data;
597
 
 
598
 
        pending = g_slist_prepend(pending, req);
599
 
        dbus_message_unref(msg);
600
 
 
601
 
        return 0;
602
 
}
603
 
 
604
 
static struct pending_req *find_request(const DBusPendingCall *call)
605
 
{
606
 
        GSList *l;
607
 
 
608
 
        for (l = pending; l; l = l->next) {
609
 
                struct pending_req *req = l->data;
610
 
 
611
 
                if (req->call == call)
612
 
                        return req;
613
 
        }
614
 
 
615
 
        return NULL;
616
 
}
617
 
 
618
 
static void remove_pending(DBusPendingCall *call)
619
 
{
620
 
        struct pending_req *req = find_request(call);
621
 
 
622
 
        pending = g_slist_remove(pending, req);
623
 
        pending_req_finalize(req);
624
 
}
625
 
 
626
672
static void create_call_reply(DBusPendingCall *call, void *user_data)
627
673
{
628
674
        DBusError err;
705
751
                                                CME_ERROR_AG_FAILURE);
706
752
}
707
753
 
708
 
void telephony_transmit_dtmf_req(void *telephony_device, char tone)
 
754
static void start_dtmf_reply(DBusPendingCall *call, void *user_data)
 
755
{
 
756
        DBusError err;
 
757
        DBusMessage *reply;
 
758
 
 
759
        reply = dbus_pending_call_steal_reply(call);
 
760
 
 
761
        dbus_error_init(&err);
 
762
        if (dbus_set_error_from_message(&err, reply)) {
 
763
                error("csd replied with an error: %s, %s",
 
764
                                err.name, err.message);
 
765
 
 
766
                dbus_error_free(&err);
 
767
        } else
 
768
                send_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH,
 
769
                                CSD_CALL_INTERFACE, "StopDTMF",
 
770
                                NULL, NULL,
 
771
                                DBUS_TYPE_INVALID);
 
772
 
 
773
        dbus_message_unref(reply);
 
774
        remove_pending(call);
 
775
}
 
776
 
 
777
static void start_dtmf(void *telephony_device, char tone)
709
778
{
710
779
        int ret;
711
 
        char buf[2] = { tone, '\0' }, *buf_ptr = buf;
712
 
 
713
 
        DBG("telephony-maemo6: transmit dtmf: %s", buf);
714
 
 
 
780
 
 
781
        /*
 
782
         * Stop tone immediately, modem will place it in queue and play
 
783
         * required time.
 
784
         */
715
785
        ret = send_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH,
716
 
                                CSD_CALL_INTERFACE, "SendDTMF",
717
 
                                NULL, NULL,
718
 
                                DBUS_TYPE_STRING, &buf_ptr,
 
786
                                CSD_CALL_INTERFACE, "StartDTMF",
 
787
                                start_dtmf_reply, NULL,
 
788
                                DBUS_TYPE_BYTE, &tone,
719
789
                                DBUS_TYPE_INVALID);
720
790
        if (ret < 0) {
721
791
                telephony_transmit_dtmf_rsp(telephony_device,
726
796
        telephony_transmit_dtmf_rsp(telephony_device, CME_ERROR_NONE);
727
797
}
728
798
 
 
799
static int tonegen_startevent(char tone)
 
800
{
 
801
        int ret;
 
802
        dbus_uint32_t event_tone;
 
803
        dbus_int32_t dbm0 = -15;
 
804
        dbus_uint32_t duration = 150;
 
805
 
 
806
        switch (tone) {
 
807
        case '*':
 
808
                event_tone = DTMF_ASTERISK;
 
809
                break;
 
810
        case '#':
 
811
                event_tone = DTMF_HASHMARK;
 
812
                break;
 
813
        case 'A':
 
814
                event_tone = DTMF_A;
 
815
                break;
 
816
        case 'B':
 
817
                event_tone = DTMF_B;
 
818
                break;
 
819
        case 'C':
 
820
                event_tone = DTMF_C;
 
821
                break;
 
822
        case 'D':
 
823
                event_tone = DTMF_D;
 
824
                break;
 
825
        default:
 
826
                ret = g_ascii_digit_value(tone);
 
827
                if (ret < 0)
 
828
                        return -EINVAL;
 
829
                event_tone = ret;
 
830
        }
 
831
 
 
832
        ret = send_method_call(TONEGEN_BUS_NAME, TONEGEN_PATH,
 
833
                                TONEGEN_INTERFACE, "StartEventTone",
 
834
                                NULL, NULL,
 
835
                                DBUS_TYPE_UINT32, &event_tone,
 
836
                                DBUS_TYPE_INT32, &dbm0,
 
837
                                DBUS_TYPE_UINT32, &duration,
 
838
                                DBUS_TYPE_INVALID);
 
839
        return ret;
 
840
}
 
841
 
 
842
static gboolean stop_feedback_tone(gpointer user_data)
 
843
{
 
844
        if (g_slist_length(tones) > 0) {
 
845
                gpointer ptone;
 
846
                int ret;
 
847
 
 
848
                send_method_call(TONEGEN_BUS_NAME, TONEGEN_PATH,
 
849
                                TONEGEN_INTERFACE, "StopTone",
 
850
                                NULL, NULL,
 
851
                                DBUS_TYPE_INVALID);
 
852
 
 
853
                ptone = g_slist_nth_data(tones, 0);
 
854
                tones = g_slist_remove(tones, ptone);
 
855
 
 
856
                ret = tonegen_startevent(GPOINTER_TO_UINT(ptone));
 
857
                if (ret < 0)
 
858
                        goto done;
 
859
 
 
860
                return TRUE;
 
861
        }
 
862
done:
 
863
        return FALSE;
 
864
}
 
865
 
 
866
static void tones_timer_notify(gpointer data)
 
867
{
 
868
        send_method_call(TONEGEN_BUS_NAME, TONEGEN_PATH,
 
869
                                TONEGEN_INTERFACE, "StopTone",
 
870
                                NULL, NULL,
 
871
                                DBUS_TYPE_INVALID);
 
872
        g_slist_free(tones);
 
873
        tones = NULL;
 
874
 
 
875
        create_tones_timer = 0;
 
876
}
 
877
 
 
878
static void start_feedback_tone(char tone)
 
879
{
 
880
        if (!create_tones_timer) {
 
881
                int ret;
 
882
 
 
883
                ret = tonegen_startevent(tone);
 
884
                if (ret < 0)
 
885
                        return;
 
886
 
 
887
                create_tones_timer = g_timeout_add_full(G_PRIORITY_DEFAULT,
 
888
                                                FEEDBACK_TONE_DURATION,
 
889
                                                stop_feedback_tone,
 
890
                                                NULL,
 
891
                                                tones_timer_notify);
 
892
        } else {
 
893
                glong dtmf_tone = tone;
 
894
 
 
895
                DBG("add %c to queue", tone);
 
896
                tones = g_slist_append(tones, GUINT_TO_POINTER(dtmf_tone));
 
897
        }
 
898
}
 
899
 
 
900
void telephony_transmit_dtmf_req(void *telephony_device, char tone)
 
901
{
 
902
        DBG("telephony-maemo6: transmit dtmf: %c", tone);
 
903
 
 
904
        start_dtmf(telephony_device, tone);
 
905
 
 
906
        if (!find_call_with_status(CSD_CALL_STATUS_ACTIVE))
 
907
                error("No active call");
 
908
        else
 
909
                start_feedback_tone(tone);
 
910
}
 
911
 
729
912
void telephony_subscriber_number_req(void *telephony_device)
730
913
{
731
914
        DBG("telephony-maemo6: subscriber number request");
752
935
                /* PROCEEDING can happen in outgoing/incoming */
753
936
                if (call->originating)
754
937
                        return CALL_STATUS_DIALING;
755
 
                else
756
 
                        return CALL_STATUS_INCOMING;
 
938
 
 
939
                /*
 
940
                 * PROCEEDING is followed by WAITING CSD status, therefore
 
941
                 * second incoming call status indication is set immediately
 
942
                 * to waiting.
 
943
                 */
 
944
                if (g_slist_length(active_calls) > 0)
 
945
                        return CALL_STATUS_WAITING;
 
946
 
 
947
                return CALL_STATUS_INCOMING;
757
948
        case CSD_CALL_STATUS_COMING:
 
949
                if (g_slist_length(active_calls) > 0)
 
950
                        return CALL_STATUS_WAITING;
 
951
 
758
952
                return CALL_STATUS_INCOMING;
759
953
        case CSD_CALL_STATUS_MO_ALERTING:
760
954
                return CALL_STATUS_ALERTING;
1137
1331
                if (g_slist_length(active_calls) == 0)
1138
1332
                        telephony_update_indicator(maemo_indicators, "call",
1139
1333
                                                        EV_CALL_INACTIVE);
 
1334
 
 
1335
                if (create_tones_timer)
 
1336
                        g_source_remove(create_tones_timer);
1140
1337
                break;
1141
1338
        case CSD_CALL_STATUS_HOLD_INITIATED:
1142
1339
                break;
1157
1354
                break;
1158
1355
        case CSD_CALL_STATUS_TERMINATED:
1159
1356
                if (call->on_hold &&
1160
 
                                !find_call_with_status(CSD_CALL_STATUS_HOLD))
 
1357
                                !find_call_with_status(CSD_CALL_STATUS_HOLD)) {
1161
1358
                        telephony_update_indicator(maemo_indicators,
1162
1359
                                                        "callheld",
1163
1360
                                                        EV_CALLHELD_NONE);
1164
 
                else if (callheld == EV_CALLHELD_MULTIPLE &&
1165
 
                                find_call_with_status(CSD_CALL_STATUS_HOLD))
 
1361
                        return;
 
1362
                }
 
1363
 
 
1364
                if (callheld == EV_CALLHELD_MULTIPLE &&
 
1365
                                find_call_with_status(CSD_CALL_STATUS_HOLD) &&
 
1366
                                !find_call_with_status(CSD_CALL_STATUS_ACTIVE))
1166
1367
                        telephony_update_indicator(maemo_indicators,
1167
1368
                                                        "callheld",
1168
1369
                                                        EV_CALLHELD_ON_HOLD);
1501
1702
        g_free(call->object_path);
1502
1703
        g_free(call->number);
1503
1704
 
 
1705
        g_slist_foreach(pending, remove_pending_by_data, call);
 
1706
 
1504
1707
        g_free(call);
1505
1708
}
1506
1709
 
1656
1859
{
1657
1860
        DBusError err;
1658
1861
        DBusMessage *reply;
1659
 
        DBusMessageIter iter, sub;;
 
1862
        DBusMessageIter iter, sub;
1660
1863
 
1661
1864
        get_calls_active = FALSE;
1662
1865
 
1988
2191
        g_slist_free_full(pending, pending_req_finalize);
1989
2192
        pending = NULL;
1990
2193
 
1991
 
        g_slist_free_full(pending, remove_watch);
 
2194
        g_slist_free_full(watches, remove_watch);
1992
2195
        watches = NULL;
1993
2196
 
1994
2197
        dbus_connection_unref(connection);