+{
+ struct bt_ccp *ccp = user_data;
+
+ DBG(" status %d index %d", tc->call_status, tc->call_index);
+
+ if (tc->call_status == CALL_DISCONNECTED)
+ return -1;
+
+ return bt_ccp_call_answer(ccp, tc->call_index);
+}
+
+static int ct_call_reject(struct telephony_ctrl *tc, void *user_data)
+{
+ struct bt_ccp *ccp = user_data;
+
+ DBG(" status %d index %d", tc->call_status, tc->call_index);
+
+ if (tc->call_status == CALL_DISCONNECTED)
+ return -1;
+
+ return bt_ccp_call_reject(ccp, tc->call_index);
+}
+
+static const struct telephony_control_callback ct_cbs = {
+ .call_answer = &ct_call_answer,
+ .call_reject = &ct_call_reject,
+};
+
+static void cb_call_list_update(struct bt_ccp *ccp, const uint8_t *buf,
+ uint16_t length)
+{
+ struct telephony_ctrl *tc = bt_ccp_get_user_data(ccp);
+ struct ccp_call_list_evt *evt;
+
+ DBG("");
+
+ if (length < sizeof(struct ccp_call_list_evt))
+ return;
+
+ evt = (struct ccp_call_list_evt *)buf;
+ tc->call_index = evt->index;
+ tc->call_status = evt->state;
+
+ DBG(" status %d index %d", tc->call_status, tc->call_index);
+
+ telephony_update_call_Info(tc);
+}
+
+static void cb_incoming_call(struct bt_ccp *ccp, const uint8_t *buf,
+ uint16_t length)
+{
+ struct ccp_incoming_call_evt *evt;
+ struct telephony_ctrl *tc = bt_ccp_get_user_data(ccp);
+
+ DBG("");
+
+ if (length < sizeof(struct ccp_incoming_call_evt))
+ return;
+
+ evt = (struct ccp_incoming_call_evt *)buf;
+ tc->call_index = evt->index;
+ tc->call_status = INCOMING_CALL;
+
+ DBG(" status %d index %d", tc->call_status, tc->call_index);
+
+ telephony_update_call_Info(tc);
+}
+
+static void cb_terminate_call(struct bt_ccp *ccp, const uint8_t *buf,
+ uint16_t length)
+{
+ struct ccp_call_terminate_evt *evt;
+ struct telephony_ctrl *tc = bt_ccp_get_user_data(ccp);
+
+ DBG("");
+
+ if (length < sizeof(struct ccp_call_terminate_evt))
+ return;
+
+ evt = (struct ccp_call_terminate_evt *)buf;
+ tc->call_index = evt->index;
+ tc->call_status = CALL_DISCONNECTED;
+
+ DBG(" status %d index %d", tc->call_status, tc->call_index);
+
+ telephony_update_call_Info(tc);
+}
+
+static const struct bt_ccp_event_callback cbs = {
+ .incoming_call = cb_incoming_call,
+ .terminate_call = cb_terminate_call,
+ .call_list_update = cb_call_list_update
+};
+
+static int ccp_accept(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ struct bt_gatt_client *client = btd_device_get_gatt_client(device);
+ struct ccp_data *data = btd_service_get_user_data(service);
+ char addr[18];
+
+ ba2str(device_get_address(device), addr);
+ DBG("%s", addr);
+
+ bt_ccp_attach(data->ccp, client);
+
+ data->tc = telephony_create_device(device_get_path(device), 0);
+ if (!data->tc) {
+ DBG("Unable to create telephony device object");
+ data->tc = NULL;
+ return -EINVAL;
+ }
+
+ telephony_set_callbacks(data->tc, &ct_cbs, data->ccp);
+ bt_ccp_set_user_data(data->ccp, data->tc);
+ bt_ccp_set_event_callbacks(data->ccp, &cbs, data->tc);
+ btd_service_connecting_complete(service, 0);
+
+ return 0;
+}
+
static void ccp_debug(const char *str, void *user_data)
{
DBG_IDX(0xffff, "%s", str);
@@ -140,28 +264,6 @@ static void ccp_remove(struct btd_service *service)
ccp_data_remove(data);
}
-static int ccp_accept(struct btd_service *service)
-{
- struct btd_device *device = btd_service_get_device(service);
- struct bt_gatt_client *client = btd_device_get_gatt_client(device);
- struct ccp_data *data = btd_service_get_user_data(service);
- char addr[18];
-
- ba2str(device_get_address(device), addr);
- DBG("%s", addr);
-
- if (!bt_ccp_attach(data->ccp, client)) {
- error("CCP unable to attach");
- return -EINVAL;
- }
-
- /* TODO: register telephony operations here */
-
- btd_service_connecting_complete(service, 0);
-
- return 0;
-}
-
static int ccp_connect(struct btd_service *service)
{
struct btd_device *device = btd_service_get_device(service);
diff --git a/profiles/audio/telephony.c b/profiles/audio/telephony.c
new file mode 100644
index 000000000000..68f27b5471cc
--- /dev/null
+++ b/profiles/audio/telephony.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2024 Intel Corporation
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include "gdbus/gdbus.h"
+
+#include "src/log.h"
+#include "src/dbus-common.h"
+#include "src/error.h"
+#include "telephony.h"
+
+#define BLUEZ_TELEPHONY_INTERFACE "org.bluez.telephonyCtrl"
+
+struct call_callback {
+ const struct telephony_control_callback *cbs;
+ void *user_data;
+};
+
+void telephony_update_call_Info(struct telephony_ctrl *tc)
+{
+ DBG("");
+ g_dbus_emit_property_changed(btd_get_dbus_connection(), tc->path,
+ BLUEZ_TELEPHONY_INTERFACE, "call_state");
+}
+
+static DBusMessage *telephony_answer_call(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct telephony_ctrl *tc = data;
+ struct call_callback *cb = tc->cb;
+ int err;
+
+ DBG("");
+ if (!cb->cbs->call_answer)
+ return btd_error_not_supported(msg);
+
+ err = cb->cbs->call_answer(tc, cb->user_data);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *telephony_reject_call(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct telephony_ctrl *tc = data;
+ struct call_callback *cb = tc->cb;
+ int err;
+
+ DBG("");
+
+ if (!cb->cbs->call_reject)
+ return btd_error_not_supported(msg);
+
+ err = cb->cbs->call_reject(tc, cb->user_data);
+ if (err < 0)
+ return btd_error_failed(msg, strerror(-err));
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static gboolean ccp_get_index(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct telephony_ctrl *tc = data;
+ uint32_t index = tc->call_index;
+
+ DBG("");
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &index);
+
+ return TRUE;
+}
+
+static const GDBusSignalTable telephony_signals[] = {
+};
+
+/* methods exposed to client to perform call operations */
+static const GDBusMethodTable telephony_methods[] = {
+ { GDBUS_METHOD("answer", NULL, NULL, telephony_answer_call) },
+ { GDBUS_METHOD("reject", NULL, NULL, telephony_reject_call) },
+ { }
+};
+
+/*
+ * Inform registered clients on property changed events
+ * use g_dbus_emit_property_changed() API
+ */
+static const GDBusPropertyTable telephony_properties[] = {
+ { "call_state", "u", ccp_get_index, NULL, NULL },
+ { }
+};
+
+void telephony_destroy_device(struct telephony_ctrl *tc)
+{
+ DBG("%s", tc->path);
+
+ g_dbus_unregister_interface(btd_get_dbus_connection(),
+ tc->path, BLUEZ_TELEPHONY_INTERFACE);
+
+ if (tc->path)
+ g_free(tc->cb);
+ if (tc->path)
+ g_free(tc->path);
+ if (tc->device)
+ g_free(tc->device);
+
+ if (tc)
+ g_free(tc);
+}
+
+struct telephony_ctrl *telephony_create_device(const char *path, uint16_t id)
+{
+ struct telephony_ctrl *tc;
+
+ DBG("");
+ tc = g_new0(struct telephony_ctrl, 1);
+ tc->device = g_strdup(path);
+ tc->path = g_strdup_printf("%s/Caller%u", path, id);
+
+ if (!g_dbus_register_interface(btd_get_dbus_connection(),
+ tc->path, BLUEZ_TELEPHONY_INTERFACE,
+ telephony_methods,
+ telephony_signals,
+ telephony_properties, tc, NULL)) {
+ error("D-Bus failed to register %s path", tc->path);
+ telephony_destroy_device(tc);
+ return NULL;
+ }
+
+ DBG("%s", tc->path);
+
+ return tc;
+}
+
+void telephony_set_callbacks(struct telephony_ctrl *tp,
+ const struct telephony_control_callback *cbs,
+ void *user_data)
+{
+ struct call_callback *cb;
+
+ DBG("");
+
+ if (tp->cb)
+ g_free(tp->cb);
+
+ cb = g_new0(struct call_callback, 1);
+ cb->cbs = cbs;
+ cb->user_data = user_data;
+
+ tp->cb = cb;
+}
diff --git a/profiles/audio/telephony.h b/profiles/audio/telephony.h
new file mode 100644
index 000000000000..e321fb881beb
--- /dev/null
+++ b/profiles/audio/telephony.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2024 Intel Corporation
+ *
+ */
+
+struct telephony_ctrl {
+ char *device; /* Device path */
+ char *path; /* Telephony object path */
+ char *status;
+ uint8_t call_status; /* call status of active call*/
+ uint8_t call_index; /* call index of active call */
+ struct call_callback *cb;
+};
+
+struct telephony_control_callback {
+ int (*call_answer)(struct telephony_ctrl *tc, void *user_data);
+ int (*call_reject)(struct telephony_ctrl *tc, void *user_data);
+};
+
+struct telephony_ctrl *telephony_create_device(const char *path, uint16_t id);
+
+void telephony_set_callbacks(struct telephony_ctrl *tc,
+ const struct telephony_control_callback *cbs,
+ void *user_data);
+
+void telephony_destroy_device(struct telephony_ctrl *tc);
+
+void telephony_set_incom_call_settings(struct telephony_ctrl *tc,
+ const char *key, void *data, size_t len);
+void telephony_set_call_termination(struct telephony_ctrl *tc,
+ const char *key, void *data, size_t len);
+
+void telephony_update_call_Info(struct telephony_ctrl *tc);
+
+struct ccp_call_list_evt {
+ uint8_t length;
+ uint8_t index;
+ uint8_t state;
+ uint8_t flag;
+};
+
+struct ccp_incoming_call_evt {
+ uint8_t length;
+ uint8_t index;
+};
+
+struct ccp_call_terminate_evt {
+ uint8_t length;
+ uint8_t index;
+ uint8_t reason;
+};
+
+enum call_state {
+ INCOMING_CALL = 0,
+ DIALLING_CALL,
+ ALERTING_CALL,
+ ACTIVE_CALL,
+ LOCAL_HOLD,
+ REMOTE_HOLD,
+ CALL_DISCONNECTED = 10
+};
diff --git a/src/shared/ccp.c b/src/shared/ccp.c
index 8e1b0b58f93b..25bb39713a13 100644
--- a/src/shared/ccp.c
+++ b/src/shared/ccp.c
@@ -3,7 +3,7 @@
*
* BlueZ - Bluetooth protocol stack for Linux
*
- * Copyright (C) 2022 Intel Corporation. All rights reserved.
+ * Copyright (C) 2023 Intel Corporation. All rights reserved.
*
*/
@@ -112,6 +112,55 @@ struct bt_ccs {
};
static struct queue *ccp_db;
+static struct bt_ccs *ccp_get_ccs(struct bt_ccp *ccp)
+{
+ if (!ccp)
+ return NULL;
+
+ if (ccp->rdb->ccs)
+ return ccp->rdb->ccs;
+
+ ccp->rdb->ccs = new0(struct bt_ccs, 1);
+ ccp->rdb->ccs->mdb = ccp->rdb;
+
+ return ccp->rdb->ccs;
+}
+
+static unsigned int ccp_send(struct bt_ccp *ccp, uint8_t index,
+ uint8_t operation)
+{
+ int ret;
+ uint16_t handle;
+ uint8_t cmd[2];
+ struct bt_ccs *ccs = ccp_get_ccs(ccp);
+
+ cmd[0] = operation;
+ cmd[1] = index;
+
+ if (!ccp->client)
+ return -1;
+
+ if (!gatt_db_attribute_get_char_data(ccs->call_ctrl_point, NULL,
+ &handle, NULL, NULL, NULL))
+ return -1;
+
+ ret = bt_gatt_client_write_without_response(ccp->client, handle, false,
+ cmd, 2);
+ if (!ret)
+ return -1;
+
+ return 0;
+}
+
+unsigned int bt_ccp_call_answer(struct bt_ccp *ccp, uint8_t index)
+{
+ return ccp_send(ccp, index, 0);
+}
+
+unsigned int bt_ccp_call_reject(struct bt_ccp *ccp, uint8_t index)
+{
+ return ccp_send(ccp, index, 1);
+}
static void ccp_debug(struct bt_ccp *ccp, const char *format, ...)
{
@@ -429,20 +478,6 @@ static struct bt_ccs *ccs_new(struct gatt_db *db)
return ccs;
}
-static struct bt_ccs *ccp_get_ccs(struct bt_ccp *ccp)
-{
- if (!ccp)
- return NULL;
-
- if (ccp->rdb->ccs)
- return ccp->rdb->ccs;
-
- ccp->rdb->ccs = new0(struct bt_ccs, 1);
- ccp->rdb->ccs->mdb = ccp->rdb;
-
- return ccp->rdb->ccs;
-}
-
static void ccp_pending_destroy(void *data)
{
struct bt_ccp_pending *pending = data;
@@ -503,6 +538,8 @@ static void ccp_cb_register(uint16_t att_ecode, void *user_data)
{
struct bt_ccp *ccp = user_data;
+ DBG(ccp, "");
+
if (att_ecode)
DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
@@ -515,27 +552,41 @@ static void ccp_cb_notify(uint16_t value_handle, const uint8_t *value,
/* TODO: generic handler for non-mandatory CCP notifications */
}
-static void ccp_cb_status_flag_register(uint16_t att_ecode, void *user_data)
+static void ccp_tc_update_call_list(struct bt_ccp *ccp,
+ const uint8_t *value, uint16_t length)
{
- struct bt_ccp *ccp = user_data;
+ struct event_callback *cb = ccp->cb;
- if (att_ecode)
- DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+ DBG(ccp, " ");
+
+ if (cb && cb->cbs && cb->cbs->call_list_update)
+ cb->cbs->call_list_update(ccp, value, length);
}
-static void ccp_cb_status_flag_notify(uint16_t value_handle,
- const uint8_t *value,
- uint16_t length, void *user_data)
+static void ccp_tc_handle_incoming_call(struct bt_ccp *ccp,
+ const uint8_t *value, uint16_t length)
{
- struct bt_ccp *ccp = user_data;
+ struct event_callback *cb = ccp->cb;
- DBG(ccp, "");
+ DBG(ccp, " ");
- if (!length)
- return;
+ if (cb && cb->cbs && cb->cbs->incoming_call)
+ cb->cbs->incoming_call(ccp, value, length);
}
-static void ccp_cb_terminate_register(uint16_t att_ecode, void *user_data)
+static void ccp_tc_handle_terminate_call(struct bt_ccp *ccp,
+ const uint8_t *value, uint16_t length)
+{
+ struct event_callback *cb = ccp->cb;
+
+ DBG(ccp, " ");
+
+ if (cb && cb->cbs && cb->cbs->terminate_call)
+ cb->cbs->terminate_call(ccp, value, length);
+}
+
+/* callback registered function */
+static void ccp_cb_status_flag_register(uint16_t att_ecode, void *user_data)
{
struct bt_ccp *ccp = user_data;
@@ -543,20 +594,15 @@ static void ccp_cb_terminate_register(uint16_t att_ecode, void *user_data)
DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
}
-static void ccp_cb_terminate_notify(uint16_t value_handle, const uint8_t *value,
- uint16_t length, void *user_data)
+static void ccp_cb_terminate_register(uint16_t att_ecode, void *user_data)
{
struct bt_ccp *ccp = user_data;
- DBG(ccp, "");
-
- if (!length)
- return;
-
- /* TODO: update call state in Local context */
+ if (att_ecode)
+ DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
}
-static void ccp_cb_bearer_name_register(uint16_t att_ecode, void *user_data)
+static void ccp_cb_call_list_register(uint16_t att_ecode, void *user_data)
{
struct bt_ccp *ccp = user_data;
@@ -566,21 +612,17 @@ static void ccp_cb_bearer_name_register(uint16_t att_ecode, void *user_data)
DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
}
-static void ccp_cb_bearer_name_notify(uint16_t value_handle,
- const uint8_t *value,
- uint16_t length, void *user_data)
+static void ccp_cb_call_state_register(uint16_t att_ecode, void *user_data)
{
struct bt_ccp *ccp = user_data;
DBG(ccp, "");
- if (!length)
- return;
-
- /* TODO: update call details in Local context */
+ if (att_ecode)
+ DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
}
-static void ccp_cb_call_list_register(uint16_t att_ecode, void *user_data)
+static void ccp_cb_incom_call_register(uint16_t att_ecode, void *user_data)
{
struct bt_ccp *ccp = user_data;
@@ -590,51 +632,52 @@ static void ccp_cb_call_list_register(uint16_t att_ecode, void *user_data)
DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
}
-static void ccp_cb_call_list_notify(uint16_t value_handle, const uint8_t *value,
- uint16_t length, void *user_data)
+static void ccp_cb_bearer_name_register(uint16_t att_ecode, void *user_data)
{
struct bt_ccp *ccp = user_data;
DBG(ccp, "");
- if (!length)
- return;
-
- /* TODO: update call list in Local context */
+ if (att_ecode)
+ DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
}
-static void ccp_cb_call_state_register(uint16_t att_ecode, void *user_data)
+static void ccp_cb_status_flag_notify(uint16_t value_handle,
+ const uint8_t *value,
+ uint16_t length, void *user_data)
{
struct bt_ccp *ccp = user_data;
+ DBG(ccp, "length %d", length);
- DBG(ccp, "");
-
- if (att_ecode)
- DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+ if (!length)
+ return;
}
-static void ccp_cb_call_state_notify(uint16_t value_handle,
- const uint8_t *value,
- uint16_t length, void *user_data)
+static void ccp_cb_terminate_notify(uint16_t value_handle,
+ const uint8_t *value,
+ uint16_t length, void *user_data)
{
struct bt_ccp *ccp = user_data;
- DBG(ccp, "");
+ DBG(ccp, "length %d", length);
if (!length)
return;
- /* TODO: update call state in Local context */
+ ccp_tc_handle_terminate_call(ccp, value, length);
}
-static void ccp_cb_incom_call_register(uint16_t att_ecode, void *user_data)
+static void ccp_cb_call_list_notify(uint16_t value_handle, const uint8_t *value,
+ uint16_t length, void *user_data)
{
struct bt_ccp *ccp = user_data;
- DBG(ccp, "");
+ DBG(ccp, "length %d", length);
- if (att_ecode)
- DBG(ccp, "ccp cb notification failed: 0x%04x", att_ecode);
+ if (!length)
+ return;
+
+ ccp_tc_update_call_list(ccp, value, length);
}
static void ccp_cb_incom_call_notify(uint16_t value_handle,
@@ -643,12 +686,12 @@ static void ccp_cb_incom_call_notify(uint16_t value_handle,
{
struct bt_ccp *ccp = user_data;
- DBG(ccp, "");
+ DBG(ccp, "length %d", length);
if (!length)
return;
- /* TODO: Handle incoming call notofiation, Answer/reject etc */
+ ccp_tc_handle_incoming_call(ccp, value, length);
}
static void bt_ccp_incom_call_attach(struct bt_ccp *ccp)
@@ -691,7 +734,7 @@ static void bt_ccp_call_state_attach(struct bt_ccp *ccp)
bt_gatt_client_register_notify(ccp->client,
value_handle,
ccp_cb_call_state_register,
- ccp_cb_call_state_notify, ccp,
+ NULL, ccp,
NULL);
}
@@ -735,7 +778,7 @@ static void bt_ccp_name_attach(struct bt_ccp *ccp)
bt_gatt_client_register_notify(ccp->client,
value_handle,
ccp_cb_bearer_name_register,
- ccp_cb_bearer_name_notify, ccp,
+ NULL, ccp,
NULL);
}
@@ -799,7 +842,7 @@ static void bt_ccp_uci_attach(struct bt_ccp *ccp)
ccp->bearer_uci_id = bt_gatt_client_register_notify(ccp->client,
value_handle,
ccp_cb_register,
- ccp_cb_notify, ccp,
+ NULL, ccp,
NULL);
}
@@ -820,7 +863,7 @@ static void bt_ccp_technology_attach(struct bt_ccp *ccp)
ccp->bearer_technology_id =
bt_gatt_client_register_notify(ccp->client,
value_handle, ccp_cb_register,
- ccp_cb_notify, ccp, NULL);
+ NULL, ccp, NULL);
}
static void bt_ccp_strength_attach(struct bt_ccp *ccp)
@@ -839,7 +882,7 @@ static void bt_ccp_strength_attach(struct bt_ccp *ccp)
ccp->signal_strength_id =
bt_gatt_client_register_notify(ccp->client, value_handle,
- ccp_cb_register, ccp_cb_notify,
+ ccp_cb_register, NULL,
ccp, NULL);
}
@@ -859,7 +902,7 @@ static void bt_ccp_ccid_attach(struct bt_ccp *ccp)
ccp->ccid_id = bt_gatt_client_register_notify(ccp->client,
value_handle,
ccp_cb_register,
- ccp_cb_notify, ccp, NULL);
+ NULL, ccp, NULL);
}
static void bt_ccp_tar_uri_attach(struct bt_ccp *ccp)
@@ -879,7 +922,7 @@ static void bt_ccp_tar_uri_attach(struct bt_ccp *ccp)
ccp->target_bearer_uri_id =
bt_gatt_client_register_notify(ccp->client,
value_handle, ccp_cb_register,
- ccp_cb_notify, ccp,
+ NULL, ccp,
NULL);
}
@@ -900,7 +943,7 @@ static void bt_ccp_ctrl_point_attach(struct bt_ccp *ccp)
ccp->call_control_pt_id =
bt_gatt_client_register_notify(ccp->client,
value_handle, ccp_cb_register,
- ccp_cb_notify, ccp, NULL);
+ NULL, ccp, NULL);
}
static void bt_ccp_ctrl_opcode_attach(struct bt_ccp *ccp)
@@ -920,7 +963,7 @@ static void bt_ccp_ctrl_opcode_attach(struct bt_ccp *ccp)
ccp->call_control_opt_opcode_id =
bt_gatt_client_register_notify(ccp->client,
value_handle, ccp_cb_register,
- ccp_cb_notify, ccp, NULL);
+ NULL, ccp, NULL);
}
static void bt_ccp_friendly_name_attach(struct bt_ccp *ccp)
@@ -940,7 +983,7 @@ static void bt_ccp_friendly_name_attach(struct bt_ccp *ccp)
ccp->friendly_name_id =
bt_gatt_client_register_notify(ccp->client,
value_handle, ccp_cb_register,
- ccp_cb_notify, ccp, NULL);
+ NULL, ccp, NULL);
}
static void bt_ccp_signal_intrvl_attach(struct bt_ccp *ccp)
@@ -960,7 +1003,7 @@ static void bt_ccp_signal_intrvl_attach(struct bt_ccp *ccp)
ccp->signal_reporting_intrvl_id =
bt_gatt_client_register_notify(ccp->client,
value_handle, ccp_cb_register,
- ccp_cb_notify, ccp, NULL);
+ NULL, ccp, NULL);
}
static void bt_ccp_uri_list_attach(struct bt_ccp *ccp)
@@ -980,7 +1023,7 @@ static void bt_ccp_uri_list_attach(struct bt_ccp *ccp)
ccp->bearer_uri_schemes_list_id =
bt_gatt_client_register_notify(ccp->client,
value_handle, ccp_cb_register,
- ccp_cb_notify, ccp, NULL);
+ NULL, ccp, NULL);
}
static void foreach_ccs_char(struct gatt_db_attribute *attr, void *user_data)
@@ -988,7 +1031,8 @@ static void foreach_ccs_char(struct gatt_db_attribute *attr, void *user_data)
struct bt_ccp *ccp = user_data;
struct bt_ccs *ccs;
uint16_t value_handle;
- bt_uuid_t uuid;
+ bt_uuid_t uuid, uuid16;
+ uint16_t be16;
if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
NULL, NULL, &uuid))
@@ -998,105 +1042,122 @@ static void foreach_ccs_char(struct gatt_db_attribute *attr, void *user_data)
if (!ccs || ccs->call_state)
return;
- if (bt_uuid16_cmp(&uuid, BEARER_PROVIDER_NAME_CHRC_UUID)) {
+ uuid16.type = uuid.type;
+
+ if (uuid.type == BT_UUID16) {
+ DBG(ccp, "uuid %x", uuid.value.u16);
+ uuid16.value.u16 = uuid.value.u16;
+ } else if (uuid.type == BT_UUID128) {
+ DBG(ccp, "uuid is u128 ");
+ uuid16.type = BT_UUID16;
+ memcpy(&be16, &uuid.value.u128.data[2], 2);
+ uuid16.value.u16 = htons(be16);
+ } else {
+ DBG(ccp, "unexpected uuid type %d", uuid16.type);
+ return;
+ }
+
+ DBG(ccp, "uuid read from gatt database %x", uuid16.value.u16);
+
+ if (bt_uuid16_cmp(&uuid16, BEARER_PROVIDER_NAME_CHRC_UUID)) {
DBG(ccp, "Found Bearer Name, handle 0x%04x", value_handle);
ccs->bearer_name = attr;
bt_ccp_name_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, BEARER_UCI_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, BEARER_UCI_CHRC_UUID)) {
DBG(ccp, "Found Bearer Uci, handle 0x%04x", value_handle);
ccs->bearer_uci = attr;
bt_ccp_uci_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, BEARER_TECH_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, BEARER_TECH_CHRC_UUID)) {
DBG(ccp, "Found Bearer Technology, handle %x", value_handle);
ccs->bearer_technology = attr;
bt_ccp_technology_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, BEARER_SIGNAL_STR_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, BEARER_SIGNAL_STR_CHRC_UUID)) {
DBG(ccp, "Found Signal Strength, handle 0x%04x", value_handle);
ccs->signal_strength = attr;
bt_ccp_strength_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, BEARER_SIGNAL_INTRVL_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, BEARER_SIGNAL_INTRVL_CHRC_UUID)) {
DBG(ccp, "Found Signal Interval, handle 0x%04x", value_handle);
ccs->signal_reporting_intrvl = attr;
bt_ccp_signal_intrvl_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, CALL_STATUS_FLAG_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, CALL_STATUS_FLAG_CHRC_UUID)) {
DBG(ccp, "Found Status Flag, handle 0x%04x", value_handle);
ccs->status_flag = attr;
bt_ccp_status_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, BEARER_URI_SCHEME_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, BEARER_URI_SCHEME_CHRC_UUID)) {
DBG(ccp, "Found URI Scheme, handle 0x%04x", value_handle);
ccs->bearer_uri_schemes_list = attr;
bt_ccp_uri_list_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, CURR_CALL_LIST_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, CURR_CALL_LIST_CHRC_UUID)) {
DBG(ccp, "Found Call List, handle 0x%04x", value_handle);
ccs->current_call_list = attr;
bt_ccp_call_list_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, BEARER_CCID_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, BEARER_CCID_CHRC_UUID)) {
DBG(ccp, "Found CCID, handle 0x%04x", value_handle);
ccs->ccid = attr;
bt_ccp_ccid_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, INCOM_CALL_TARGET_URI_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, INCOM_CALL_TARGET_URI_CHRC_UUID)) {
DBG(ccp, "Found Bearer Uri, handle 0x%04x", value_handle);
ccs->target_bearer_uri = attr;
bt_ccp_tar_uri_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, CALL_CTRL_POINT_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, CALL_CTRL_POINT_CHRC_UUID)) {
DBG(ccp, "Found Control Point, handle 0x%04x", value_handle);
ccs->call_ctrl_point = attr;
bt_ccp_ctrl_point_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, CALL_CTRL_POINT_OPT_OPCODE_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, CALL_CTRL_POINT_OPT_OPCODE_CHRC_UUID)) {
DBG(ccp, "Found Control opcode, handle 0x%04x", value_handle);
ccs->call_ctrl_opt_opcode = attr;
bt_ccp_ctrl_opcode_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, TERMINATION_REASON_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, TERMINATION_REASON_CHRC_UUID)) {
DBG(ccp, "Found Termination Reason, handle %x", value_handle);
ccs->termination_reason = attr;
bt_ccp_term_reason_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, INCOMING_CALL_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, INCOMING_CALL_CHRC_UUID)) {
DBG(ccp, "Found Incoming call, handle 0x%04x", value_handle);
ccs->incoming_call = attr;
bt_ccp_incom_call_attach(ccp);
}
- if (bt_uuid16_cmp(&uuid, CALL_FRIENDLY_NAME_CHRC_UUID)) {
+ if (bt_uuid16_cmp(&uuid16, CALL_FRIENDLY_NAME_CHRC_UUID)) {
DBG(ccp, "Found Friendly name, handle 0x%04x", value_handle);
ccs->friendly_name = attr;
diff --git a/src/shared/ccp.h b/src/shared/ccp.h
index 28b8b034ece3..3298abe9014c 100644
--- a/src/shared/ccp.h
+++ b/src/shared/ccp.h
@@ -3,7 +3,7 @@
*
* BlueZ - Bluetooth protocol stack for Linux
*
- * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ * Copyright (C) 2023 Intel Corporation. All rights reserved.
*
*/
@@ -18,14 +18,18 @@ struct bt_ccp;
struct bt_ccp_db;
struct bt_ccp_session_info;
-typedef void (*bt_ccp_debug_func_t)(const char *str, void *user_data);
-typedef void (*bt_ccp_destroy_func_t)(void *user_data);
-
struct bt_ccp_event_callback {
- void (*call_state)(struct bt_ccp *ccp, const uint8_t *value,
- uint16_t length);
+ void (*incoming_call)(struct bt_ccp *ccp,
+ const uint8_t *value, uint16_t len);
+ void (*terminate_call)(struct bt_ccp *ccp,
+ const uint8_t *value, uint16_t len);
+ void (*call_list_update)(struct bt_ccp *ccp,
+ const uint8_t *value, uint16_t len);
};
+typedef void (*bt_ccp_debug_func_t)(const char *str, void *user_data);
+typedef void (*bt_ccp_destroy_func_t)(void *user_data);
+
void bt_ccp_set_event_callbacks(struct bt_ccp *ccp,
const struct bt_ccp_event_callback *cbs,
void *user_data);
@@ -43,3 +47,6 @@ void bt_ccp_unref(struct bt_ccp *ccp);
bool bt_ccp_set_user_data(struct bt_ccp *ccp, void *user_data);
void *bt_ccp_get_user_data(struct bt_ccp *ccp);
+
+unsigned int bt_ccp_call_answer(struct bt_ccp *ccp, uint8_t index);
+unsigned int bt_ccp_call_reject(struct bt_ccp *ccp, uint8_t index);