summaryrefslogtreecommitdiff
path: root/audio/telephony-dummy.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/telephony-dummy.c')
-rw-r--r--audio/telephony-dummy.c433
1 files changed, 433 insertions, 0 deletions
diff --git a/audio/telephony-dummy.c b/audio/telephony-dummy.c
new file mode 100644
index 0000000..1f89079
--- /dev/null
+++ b/audio/telephony-dummy.c
@@ -0,0 +1,433 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gdbus.h>
+
+#include "log.h"
+#include "telephony.h"
+#include "error.h"
+
+#define TELEPHONY_DUMMY_IFACE "org.bluez.TelephonyTest"
+#define TELEPHONY_DUMMY_PATH "/org/bluez/test"
+
+static DBusConnection *connection = NULL;
+
+static const char *chld_str = "0,1,1x,2,2x,3,4";
+static char *subscriber_number = NULL;
+static char *active_call_number = NULL;
+static int active_call_status = 0;
+static int active_call_dir = 0;
+
+static gboolean events_enabled = FALSE;
+
+static struct indicator dummy_indicators[] =
+{
+ { "battchg", "0-5", 5, TRUE },
+ { "signal", "0-5", 5, TRUE },
+ { "service", "0,1", 1, TRUE },
+ { "call", "0,1", 0, TRUE },
+ { "callsetup", "0-3", 0, TRUE },
+ { "callheld", "0-2", 0, FALSE },
+ { "roam", "0,1", 0, TRUE },
+ { NULL }
+};
+
+void telephony_device_connected(void *telephony_device)
+{
+ DBG("telephony-dummy: device %p connected", telephony_device);
+}
+
+void telephony_device_disconnected(void *telephony_device)
+{
+ DBG("telephony-dummy: device %p disconnected", telephony_device);
+ events_enabled = FALSE;
+}
+
+void telephony_event_reporting_req(void *telephony_device, int ind)
+{
+ events_enabled = ind == 1 ? TRUE : FALSE;
+
+ telephony_event_reporting_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_response_and_hold_req(void *telephony_device, int rh)
+{
+ telephony_response_and_hold_rsp(telephony_device,
+ CME_ERROR_NOT_SUPPORTED);
+}
+
+void telephony_last_dialed_number_req(void *telephony_device)
+{
+ telephony_last_dialed_number_rsp(telephony_device, CME_ERROR_NONE);
+
+ /* Notify outgoing call set-up successfully initiated */
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_OUTGOING);
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_ALERTING);
+
+ active_call_status = CALL_STATUS_ALERTING;
+ active_call_dir = CALL_DIR_OUTGOING;
+}
+
+void telephony_terminate_call_req(void *telephony_device)
+{
+ g_free(active_call_number);
+ active_call_number = NULL;
+
+ telephony_terminate_call_rsp(telephony_device, CME_ERROR_NONE);
+
+ if (telephony_get_indicator(dummy_indicators, "callsetup") > 0)
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_INACTIVE);
+ else
+ telephony_update_indicator(dummy_indicators, "call",
+ EV_CALL_INACTIVE);
+}
+
+void telephony_answer_call_req(void *telephony_device)
+{
+ telephony_answer_call_rsp(telephony_device, CME_ERROR_NONE);
+
+ telephony_update_indicator(dummy_indicators, "call", EV_CALL_ACTIVE);
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_INACTIVE);
+
+ active_call_status = CALL_STATUS_ACTIVE;
+}
+
+void telephony_dial_number_req(void *telephony_device, const char *number)
+{
+ g_free(active_call_number);
+ active_call_number = g_strdup(number);
+
+ DBG("telephony-dummy: dial request to %s", active_call_number);
+
+ telephony_dial_number_rsp(telephony_device, CME_ERROR_NONE);
+
+ /* Notify outgoing call set-up successfully initiated */
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_OUTGOING);
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_ALERTING);
+
+ active_call_status = CALL_STATUS_ALERTING;
+ active_call_dir = CALL_DIR_OUTGOING;
+}
+
+void telephony_transmit_dtmf_req(void *telephony_device, char tone)
+{
+ DBG("telephony-dummy: transmit dtmf: %c", tone);
+ telephony_transmit_dtmf_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_subscriber_number_req(void *telephony_device)
+{
+ DBG("telephony-dummy: subscriber number request");
+ if (subscriber_number)
+ telephony_subscriber_number_ind(subscriber_number,
+ NUMBER_TYPE_TELEPHONY,
+ SUBSCRIBER_SERVICE_VOICE);
+ telephony_subscriber_number_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_list_current_calls_req(void *telephony_device)
+{
+ DBG("telephony-dummy: list current calls request");
+ if (active_call_number)
+ telephony_list_current_call_ind(1, active_call_dir,
+ active_call_status,
+ CALL_MODE_VOICE,
+ CALL_MULTIPARTY_NO,
+ active_call_number,
+ NUMBER_TYPE_TELEPHONY);
+ telephony_list_current_calls_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_operator_selection_req(void *telephony_device)
+{
+ telephony_operator_selection_ind(OPERATOR_MODE_AUTO, "DummyOperator");
+ telephony_operator_selection_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_call_hold_req(void *telephony_device, const char *cmd)
+{
+ DBG("telephony-dymmy: got call hold request %s", cmd);
+ telephony_call_hold_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_nr_and_ec_req(void *telephony_device, gboolean enable)
+{
+ DBG("telephony-dummy: got %s NR and EC request",
+ enable ? "enable" : "disable");
+
+ telephony_nr_and_ec_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_voice_dial_req(void *telephony_device, gboolean enable)
+{
+ DBG("telephony-dummy: got %s voice dial request",
+ enable ? "enable" : "disable");
+
+ g_dbus_emit_signal(connection, TELEPHONY_DUMMY_PATH,
+ TELEPHONY_DUMMY_IFACE, "VoiceDial",
+ DBUS_TYPE_INVALID);
+
+ telephony_voice_dial_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+void telephony_key_press_req(void *telephony_device, const char *keys)
+{
+ DBG("telephony-dummy: got key press request for %s", keys);
+ telephony_key_press_rsp(telephony_device, CME_ERROR_NONE);
+}
+
+/* D-Bus method handlers */
+static DBusMessage *outgoing_call(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *number;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &number,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ DBG("telephony-dummy: outgoing call to %s", number);
+
+ g_free(active_call_number);
+ active_call_number = g_strdup(number);
+
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_OUTGOING);
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_ALERTING);
+
+ active_call_status = CALL_STATUS_ALERTING;
+ active_call_dir = CALL_DIR_OUTGOING;
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *incoming_call(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ const char *number;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &number,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ DBG("telephony-dummy: incoming call to %s", number);
+
+ g_free(active_call_number);
+ active_call_number = g_strdup(number);
+
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_INCOMING);
+
+ active_call_status = CALL_STATUS_INCOMING;
+ active_call_dir = CALL_DIR_INCOMING;
+
+ telephony_incoming_call_ind(number, NUMBER_TYPE_TELEPHONY);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *cancel_call(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ DBG("telephony-dummy: cancel call");
+
+ g_free(active_call_number);
+ active_call_number = NULL;
+
+ if (telephony_get_indicator(dummy_indicators, "callsetup") > 0) {
+ telephony_update_indicator(dummy_indicators, "callsetup",
+ EV_CALLSETUP_INACTIVE);
+ telephony_calling_stopped_ind();
+ }
+
+ if (telephony_get_indicator(dummy_indicators, "call") > 0)
+ telephony_update_indicator(dummy_indicators, "call",
+ EV_CALL_INACTIVE);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *signal_strength(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ dbus_uint32_t strength;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &strength,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ if (strength > 5)
+ return btd_error_invalid_args(msg);
+
+ telephony_update_indicator(dummy_indicators, "signal", strength);
+
+ DBG("telephony-dummy: signal strength set to %u", strength);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *battery_level(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ dbus_uint32_t level;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &level,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ if (level > 5)
+ return btd_error_invalid_args(msg);
+
+ telephony_update_indicator(dummy_indicators, "battchg", level);
+
+ DBG("telephony-dummy: battery level set to %u", level);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *roaming_status(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ dbus_bool_t roaming;
+ int val;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &roaming,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ val = roaming ? EV_ROAM_ACTIVE : EV_ROAM_INACTIVE;
+
+ telephony_update_indicator(dummy_indicators, "roam", val);
+
+ DBG("telephony-dummy: roaming status set to %d", val);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *registration_status(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ dbus_bool_t registration;
+ int val;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &registration,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ val = registration ? EV_SERVICE_PRESENT : EV_SERVICE_NONE;
+
+ telephony_update_indicator(dummy_indicators, "service", val);
+
+ DBG("telephony-dummy: registration status set to %d", val);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static DBusMessage *set_subscriber_number(DBusConnection *conn,
+ DBusMessage *msg,
+ void *data)
+{
+ const char *number;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &number,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ g_free(subscriber_number);
+ subscriber_number = g_strdup(number);
+
+ DBG("telephony-dummy: subscriber number set to %s", number);
+
+ return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable dummy_methods[] = {
+ { "OutgoingCall", "s", "", outgoing_call },
+ { "IncomingCall", "s", "", incoming_call },
+ { "CancelCall", "", "", cancel_call },
+ { "SignalStrength", "u", "", signal_strength },
+ { "BatteryLevel", "u", "", battery_level },
+ { "RoamingStatus", "b", "", roaming_status },
+ { "RegistrationStatus", "b", "", registration_status },
+ { "SetSubscriberNumber","s", "", set_subscriber_number },
+ { }
+};
+
+static GDBusSignalTable dummy_signals[] = {
+ { "VoiceDial", "" },
+ { }
+};
+
+int telephony_init(void)
+{
+ uint32_t features = AG_FEATURE_REJECT_A_CALL |
+ AG_FEATURE_ENHANCED_CALL_STATUS |
+ AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
+
+ DBG("");
+
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+
+ if (g_dbus_register_interface(connection, TELEPHONY_DUMMY_PATH,
+ TELEPHONY_DUMMY_IFACE,
+ dummy_methods, dummy_signals,
+ NULL, NULL, NULL) == FALSE) {
+ error("telephony-dummy interface %s init failed on path %s",
+ TELEPHONY_DUMMY_IFACE, TELEPHONY_DUMMY_PATH);
+ return -1;
+ }
+
+ telephony_ready_ind(features, dummy_indicators, BTRH_NOT_SUPPORTED,
+ chld_str);
+
+ return 0;
+}
+
+void telephony_exit(void)
+{
+ DBG("");
+
+ g_dbus_unregister_interface(connection, TELEPHONY_DUMMY_PATH,
+ TELEPHONY_DUMMY_IFACE);
+ dbus_connection_unref(connection);
+ connection = NULL;
+
+ telephony_deinit();
+}