113
113
#define CSD_SIMPB_TYPE_EN "EN"
114
114
#define CSD_SIMPB_TYPE_MSISDN "MSISDN"
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"
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"
126
/* tone-generator DTMF definitions */
127
#define DTMF_ASTERISK 10
128
#define DTMF_HASHMARK 11
134
#define FEEDBACK_TONE_DURATION 200
116
136
struct csd_call {
117
137
char *object_path;
153
173
/* Reference count for determining the call indicator status */
154
174
static GSList *active_calls = NULL;
176
/* Queue of DTMF tones to play */
177
static GSList *tones = NULL;
178
static guint create_tones_timer = 0;
156
180
static char *msisdn = NULL; /* Subscriber number */
157
181
static char *vmbx = NULL; /* Voice mailbox number */
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, ...)
238
DBusPendingCall *call;
240
struct pending_req *req;
242
msg = dbus_message_new_method_call(dest, path, interface, method);
244
error("Unable to allocate new D-Bus %s message", method);
248
va_start(args, type);
250
if (!dbus_message_append_args_valist(msg, type, args)) {
251
dbus_message_unref(msg);
259
g_dbus_send_message(connection, msg);
263
if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
264
error("Sending %s failed", method);
265
dbus_message_unref(msg);
269
dbus_pending_call_set_notify(call, cb, user_data, NULL);
271
req = g_new0(struct pending_req, 1);
273
req->user_data = user_data;
275
pending = g_slist_prepend(pending, req);
276
dbus_message_unref(msg);
208
281
static struct csd_call *find_call(const char *path)
396
static struct pending_req *find_request(const DBusPendingCall *call)
400
for (l = pending; l; l = l->next) {
401
struct pending_req *req = l->data;
403
if (req->call == call)
410
static void pending_req_finalize(void *data)
412
struct pending_req *req = data;
414
if (!dbus_pending_call_get_completed(req->call))
415
dbus_pending_call_cancel(req->call);
417
dbus_pending_call_unref(req->call);
421
static void remove_pending(DBusPendingCall *call)
423
struct pending_req *req = find_request(call);
425
pending = g_slist_remove(pending, req);
426
pending_req_finalize(req);
429
static void stop_ringtone_reply(DBusPendingCall *call, void *user_data)
431
struct csd_call *coming = user_data;
433
remove_pending(call);
437
static int stop_ringtone_and_answer(struct csd_call *call)
441
ret = send_method_call(OHM_BUS_NAME, OHM_PATH,
442
OHM_INTERFACE, "StopRingtone",
443
stop_ringtone_reply, call,
446
return answer_call(call);
323
451
static int split_call(struct csd_call *call)
325
453
DBusMessage *msg;
454
static void pending_req_finalize(void *data)
456
struct pending_req *req = data;
458
if (!dbus_pending_call_get_completed(req->call))
459
dbus_pending_call_cancel(req->call);
461
dbus_pending_call_unref(req->call);
465
582
static void remove_pending_by_data(gpointer data, gpointer user_data)
467
584
struct pending_req *req = data;
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);
552
669
telephony_answer_call_rsp(telephony_device, CME_ERROR_NONE);
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, ...)
561
DBusPendingCall *call;
563
struct pending_req *req;
565
msg = dbus_message_new_method_call(dest, path, interface, method);
567
error("Unable to allocate new D-Bus %s message", method);
571
va_start(args, type);
573
if (!dbus_message_append_args_valist(msg, type, args)) {
574
dbus_message_unref(msg);
582
g_dbus_send_message(connection, msg);
586
if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
587
error("Sending %s failed", method);
588
dbus_message_unref(msg);
592
dbus_pending_call_set_notify(call, cb, user_data, NULL);
594
req = g_new0(struct pending_req, 1);
596
req->user_data = user_data;
598
pending = g_slist_prepend(pending, req);
599
dbus_message_unref(msg);
604
static struct pending_req *find_request(const DBusPendingCall *call)
608
for (l = pending; l; l = l->next) {
609
struct pending_req *req = l->data;
611
if (req->call == call)
618
static void remove_pending(DBusPendingCall *call)
620
struct pending_req *req = find_request(call);
622
pending = g_slist_remove(pending, req);
623
pending_req_finalize(req);
626
672
static void create_call_reply(DBusPendingCall *call, void *user_data)
705
751
CME_ERROR_AG_FAILURE);
708
void telephony_transmit_dtmf_req(void *telephony_device, char tone)
754
static void start_dtmf_reply(DBusPendingCall *call, void *user_data)
759
reply = dbus_pending_call_steal_reply(call);
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);
766
dbus_error_free(&err);
768
send_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH,
769
CSD_CALL_INTERFACE, "StopDTMF",
773
dbus_message_unref(reply);
774
remove_pending(call);
777
static void start_dtmf(void *telephony_device, char tone)
711
char buf[2] = { tone, '\0' }, *buf_ptr = buf;
713
DBG("telephony-maemo6: transmit dtmf: %s", buf);
782
* Stop tone immediately, modem will place it in queue and play
715
785
ret = send_method_call(CSD_CALL_BUS_NAME, CSD_CALL_PATH,
716
CSD_CALL_INTERFACE, "SendDTMF",
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);
721
791
telephony_transmit_dtmf_rsp(telephony_device,
726
796
telephony_transmit_dtmf_rsp(telephony_device, CME_ERROR_NONE);
799
static int tonegen_startevent(char tone)
802
dbus_uint32_t event_tone;
803
dbus_int32_t dbm0 = -15;
804
dbus_uint32_t duration = 150;
808
event_tone = DTMF_ASTERISK;
811
event_tone = DTMF_HASHMARK;
826
ret = g_ascii_digit_value(tone);
832
ret = send_method_call(TONEGEN_BUS_NAME, TONEGEN_PATH,
833
TONEGEN_INTERFACE, "StartEventTone",
835
DBUS_TYPE_UINT32, &event_tone,
836
DBUS_TYPE_INT32, &dbm0,
837
DBUS_TYPE_UINT32, &duration,
842
static gboolean stop_feedback_tone(gpointer user_data)
844
if (g_slist_length(tones) > 0) {
848
send_method_call(TONEGEN_BUS_NAME, TONEGEN_PATH,
849
TONEGEN_INTERFACE, "StopTone",
853
ptone = g_slist_nth_data(tones, 0);
854
tones = g_slist_remove(tones, ptone);
856
ret = tonegen_startevent(GPOINTER_TO_UINT(ptone));
866
static void tones_timer_notify(gpointer data)
868
send_method_call(TONEGEN_BUS_NAME, TONEGEN_PATH,
869
TONEGEN_INTERFACE, "StopTone",
875
create_tones_timer = 0;
878
static void start_feedback_tone(char tone)
880
if (!create_tones_timer) {
883
ret = tonegen_startevent(tone);
887
create_tones_timer = g_timeout_add_full(G_PRIORITY_DEFAULT,
888
FEEDBACK_TONE_DURATION,
893
glong dtmf_tone = tone;
895
DBG("add %c to queue", tone);
896
tones = g_slist_append(tones, GUINT_TO_POINTER(dtmf_tone));
900
void telephony_transmit_dtmf_req(void *telephony_device, char tone)
902
DBG("telephony-maemo6: transmit dtmf: %c", tone);
904
start_dtmf(telephony_device, tone);
906
if (!find_call_with_status(CSD_CALL_STATUS_ACTIVE))
907
error("No active call");
909
start_feedback_tone(tone);
729
912
void telephony_subscriber_number_req(void *telephony_device)
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;
756
return CALL_STATUS_INCOMING;
940
* PROCEEDING is followed by WAITING CSD status, therefore
941
* second incoming call status indication is set immediately
944
if (g_slist_length(active_calls) > 0)
945
return CALL_STATUS_WAITING;
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;
758
952
return CALL_STATUS_INCOMING;
759
953
case CSD_CALL_STATUS_MO_ALERTING:
760
954
return CALL_STATUS_ALERTING;
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,
1163
1360
EV_CALLHELD_NONE);
1164
else if (callheld == EV_CALLHELD_MULTIPLE &&
1165
find_call_with_status(CSD_CALL_STATUS_HOLD))
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,
1168
1369
EV_CALLHELD_ON_HOLD);