2022-10-06 14:39:01

by Abhay Maheta

[permalink] [raw]
Subject: [PATCH BlueZ 0/4] Media Control Profile Client

This series of patches adds support for Media Control Profile for LE Audio.
These patches primarily foces on Media Control Client Role.

Abhay Maheta (4):
lib/uuid: Add GMCS UUIDs
shared/mcp: Add initial code for handling MCP
profiles: Add initial code for mcp plugin
monitor/att: Add decoding support for GMCS

Makefile.am | 1 +
Makefile.plugins | 5 +
configure.ac | 4 +
lib/uuid.h | 15 +
monitor/att.c | 511 +++++++++++++++
profiles/audio/mcp.c | 429 +++++++++++++
src/shared/mcp.c | 1408 ++++++++++++++++++++++++++++++++++++++++++
src/shared/mcp.h | 60 ++
src/shared/mcs.h | 65 ++
9 files changed, 2498 insertions(+)
create mode 100644 profiles/audio/mcp.c
create mode 100644 src/shared/mcp.c
create mode 100644 src/shared/mcp.h
create mode 100644 src/shared/mcs.h

--
2.25.1


2022-10-06 14:39:01

by Abhay Maheta

[permalink] [raw]
Subject: [PATCH BlueZ 3/4] profiles: Add initial code for mcp plugin

This adds initial code for mcp plugin which handles Media Control Profile
and Generic Media Control Service for Client Role.
---
Makefile.plugins | 5 +
configure.ac | 4 +
profiles/audio/mcp.c | 429 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 438 insertions(+)
create mode 100644 profiles/audio/mcp.c

diff --git a/Makefile.plugins b/Makefile.plugins
index a3654980f..20cac384e 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -122,6 +122,11 @@ builtin_modules += bap
builtin_sources += profiles/audio/bap.c
endif

+if MCP
+builtin_modules += mcp
+builtin_sources += profiles/audio/mcp.c
+endif
+
if VCP
builtin_modules += vcp
builtin_sources += profiles/audio/vcp.c
diff --git a/configure.ac b/configure.ac
index 79645e691..363a222a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -199,6 +199,10 @@ AC_ARG_ENABLE(bap, AS_HELP_STRING([--disable-bap],
[disable BAP profile]), [enable_bap=${enableval}])
AM_CONDITIONAL(BAP, test "${enable_bap}" != "no")

+AC_ARG_ENABLE(mcp, AS_HELP_STRING([--disable-mcp],
+ [disable MCP profile]), [enable_mcp=${enableval}])
+AM_CONDITIONAL(MCP, test "${enable_mcp}" != "no")
+
AC_ARG_ENABLE(vcp, AS_HELP_STRING([--disable-vcp],
[disable VCP profile]), [enable_vcp=${enableval}])
AM_CONDITIONAL(VCP, test "${enable_vcp}" != "no")
diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c
new file mode 100644
index 000000000..0a8d83198
--- /dev/null
+++ b/profiles/audio/mcp.c
@@ -0,0 +1,429 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "gdbus/gdbus.h"
+
+#include "lib/bluetooth.h"
+#include "lib/hci.h"
+#include "lib/sdp.h"
+#include "lib/uuid.h"
+
+#include "src/dbus-common.h"
+#include "src/shared/util.h"
+#include "src/shared/att.h"
+#include "src/shared/queue.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/mcp.h"
+#include "src/shared/mcs.h"
+
+#include "btio/btio.h"
+#include "src/plugin.h"
+#include "src/adapter.h"
+#include "src/gatt-database.h"
+#include "src/device.h"
+#include "src/profile.h"
+#include "src/service.h"
+#include "src/log.h"
+#include "src/error.h"
+#include "player.h"
+
+#define GMCS_UUID_STR "00001849-0000-1000-8000-00805f9b34fb"
+
+struct mcp_data {
+ struct btd_device *device;
+ struct btd_service *service;
+ struct bt_mcp *mcp;
+ unsigned int state_id;
+
+ struct media_player *mp;
+};
+
+static void mcp_debug(const char *str, void *user_data)
+{
+ DBG_IDX(0xffff, "%s", str);
+}
+
+static char *name2utf8(const uint8_t *name, uint16_t len)
+{
+ char utf8_name[HCI_MAX_NAME_LENGTH + 2];
+ int i;
+
+ if (g_utf8_validate((const char *) name, len, NULL))
+ return g_strndup((char *) name, len);
+
+ len = MIN(len, sizeof(utf8_name) - 1);
+
+ memset(utf8_name, 0, sizeof(utf8_name));
+ strncpy(utf8_name, (char *) name, len);
+
+ /* Assume ASCII, and replace all non-ASCII with spaces */
+ for (i = 0; utf8_name[i] != '\0'; i++) {
+ if (!isascii(utf8_name[i]))
+ utf8_name[i] = ' ';
+ }
+
+ /* Remove leading and trailing whitespace characters */
+ g_strstrip(utf8_name);
+
+ return g_strdup(utf8_name);
+}
+
+static const char *mcp_status_val_to_string(uint8_t status)
+{
+ switch (status) {
+ case BT_MCS_STATUS_PLAYING:
+ return "playing";
+ case BT_MCS_STATUS_PAUSED:
+ return "paused";
+ case BT_MCS_STATUS_INACTIVE:
+ return "stopped";
+ case BT_MCS_STATUS_SEEKING:
+ /* TODO: find a way for fwd/rvs seeking, probably by storing
+ * control point operation sent before
+ */
+ return "forward-seek";
+ default:
+ return "error";
+ }
+}
+
+static struct mcp_data *mcp_data_new(struct btd_device *device)
+{
+ struct mcp_data *data;
+
+ data = new0(struct mcp_data, 1);
+ data->device = device;
+
+ return data;
+}
+
+static void cb_player_name(struct bt_mcp *mcp, const uint8_t *value,
+ uint16_t length)
+{
+ char *name;
+ struct media_player *mp = bt_mcp_get_user_data(mcp);
+
+ name = name2utf8(value, length);
+ DBG("Media Player Name %s", (const char *)name);
+
+ media_player_set_name(mp, name);
+
+ g_free(name);
+}
+
+void cb_track_changed(struct bt_mcp *mcp)
+{
+ DBG("Track Changed");
+ /* Since track changed has happened
+ * track title notification is expected
+ */
+}
+
+void cb_track_title(struct bt_mcp *mcp, const uint8_t *value,
+ uint16_t length)
+{
+ char *name;
+ uint16_t len;
+ struct media_player *mp = bt_mcp_get_user_data(mcp);
+
+ name = name2utf8(value, length);
+ len = strlen(name);
+
+ DBG("Track Title %s", (const char *)name);
+
+ media_player_set_metadata(mp, NULL, "Title", name, len);
+ media_player_metadata_changed(mp);
+
+ g_free(name);
+}
+
+void cb_track_duration(struct bt_mcp *mcp, int32_t duration)
+{
+ struct media_player *mp = bt_mcp_get_user_data(mcp);
+ unsigned char buf[10];
+
+ /* MCP defines duration is int32 but api takes it as uint32 */
+ sprintf(buf, "%d", duration);
+ media_player_set_metadata(mp, NULL, "Duration", buf, sizeof(buf));
+ media_player_metadata_changed(mp);
+}
+
+void cb_track_position(struct bt_mcp *mcp, int32_t duration)
+{
+ struct media_player *mp = bt_mcp_get_user_data(mcp);
+
+ /* MCP defines duration is int32 but api takes it as uint32 */
+ media_player_set_position(mp, duration);
+}
+
+void cb_media_state(struct bt_mcp *mcp, uint8_t status)
+{
+ struct media_player *mp = bt_mcp_get_user_data(mcp);
+
+ media_player_set_status(mp, mcp_status_val_to_string(status));
+}
+
+static const struct bt_mcp_event_callback cbs = {
+ .player_name = &cb_player_name,
+ .track_changed = &cb_track_changed,
+ .track_title = &cb_track_title,
+ .track_duration = &cb_track_duration,
+ .track_position = &cb_track_position,
+ .playback_speed = NULL,
+ .seeking_speed = NULL,
+ .play_order = NULL,
+ .play_order_supported = NULL,
+ .media_state = &cb_media_state,
+ .content_control_id = NULL,
+};
+
+static int ct_play(struct media_player *mp, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ return bt_mcp_play(mcp);
+}
+
+static int ct_pause(struct media_player *mp, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ return bt_mcp_pause(mcp);
+}
+
+static int ct_stop(struct media_player *mp, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ return bt_mcp_stop(mcp);
+}
+
+static const struct media_player_callback ct_cbs = {
+ .set_setting = NULL,
+ .play = &ct_play,
+ .pause = &ct_pause,
+ .stop = &ct_stop,
+ .next = NULL,
+ .previous = NULL,
+ .fast_forward = NULL,
+ .rewind = NULL,
+ .press = NULL,
+ .hold = NULL,
+ .release = NULL,
+ .list_items = NULL,
+ .change_folder = NULL,
+ .search = NULL,
+ .play_item = NULL,
+ .add_to_nowplaying = NULL,
+ .total_items = NULL,
+};
+
+static int mcp_probe(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ struct btd_adapter *adapter = device_get_adapter(device);
+ struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+ struct mcp_data *data = btd_service_get_user_data(service);
+ char addr[18];
+
+ ba2str(device_get_address(device), addr);
+ DBG("%s", addr);
+
+ /* Ignore, if we were probed for this device already */
+ if (data) {
+ error("Profile probed twice for the same device!");
+ return -EINVAL;
+ }
+
+ data = mcp_data_new(device);
+ data->service = service;
+
+ data->mcp = bt_mcp_new(btd_gatt_database_get_db(database),
+ btd_device_get_gatt_db(device));
+
+ bt_mcp_set_debug(data->mcp, mcp_debug, NULL, NULL);
+ btd_service_set_user_data(service, data);
+
+ return 0;
+}
+
+static void mcp_data_free(struct mcp_data *data)
+{
+ DBG("");
+
+ if (data->service) {
+ btd_service_set_user_data(data->service, NULL);
+ bt_mcp_set_user_data(data->mcp, NULL);
+ }
+
+ if (data->mp) {
+ media_player_destroy(data->mp);
+ data->mp = NULL;
+ }
+
+ bt_mcp_unref(data->mcp);
+ free(data);
+}
+
+static void mcp_data_remove(struct mcp_data *data)
+{
+ DBG("data %p", data);
+
+ mcp_data_free(data);
+}
+
+static void mcp_remove(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ struct mcp_data *data;
+ char addr[18];
+
+ ba2str(device_get_address(device), addr);
+ DBG("%s", addr);
+
+ data = btd_service_get_user_data(service);
+ if (!data) {
+ error("MCP service not handled by profile");
+ return;
+ }
+
+ mcp_data_remove(data);
+}
+
+static int mcp_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 mcp_data *data = btd_service_get_user_data(service);
+ char addr[18];
+
+ ba2str(device_get_address(device), addr);
+ DBG("%s", addr);
+
+ bt_mcp_attach(data->mcp, client);
+
+ data->mp = media_player_controller_create(device_get_path(device), 0);
+ if (data->mp == NULL) {
+ DBG("Unable to create Media Player");
+ return -EINVAL;
+ }
+
+ media_player_set_callbacks(data->mp, &ct_cbs, data->mcp);
+
+ bt_mcp_set_user_data(data->mcp, data->mp);
+ bt_mcp_set_event_callbacks(data->mcp, &cbs, data->mp);
+ btd_service_connecting_complete(service, 0);
+
+ return 0;
+}
+
+static int mcp_connect(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ char addr[18];
+
+ ba2str(device_get_address(device), addr);
+ DBG("%s", addr);
+
+ return 0;
+}
+
+static int mcp_disconnect(struct btd_service *service)
+{
+ struct btd_device *device = btd_service_get_device(service);
+ struct mcp_data *data = btd_service_get_user_data(service);
+ char addr[18];
+
+ ba2str(device_get_address(device), addr);
+ DBG("%s", addr);
+
+ if (data->mp) {
+ media_player_destroy(data->mp);
+ data->mp = NULL;
+ }
+
+ bt_mcp_detach(data->mcp);
+
+ btd_service_disconnecting_complete(service, 0);
+
+ return 0;
+}
+
+static int media_control_server_probe(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+ struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+ bt_mcp_register(btd_gatt_database_get_db(database));
+ return 0;
+}
+
+static void media_control_server_remove(struct btd_profile *p,
+ struct btd_adapter *adapter)
+{
+
+}
+
+static struct btd_profile mcp_profile = {
+ .name = "mcp",
+ .priority = BTD_PROFILE_PRIORITY_MEDIUM,
+ .remote_uuid = GMCS_UUID_STR,
+ .device_probe = mcp_probe,
+ .device_remove = mcp_remove,
+ .accept = mcp_accept,
+ .connect = mcp_connect,
+ .disconnect = mcp_disconnect,
+
+ .adapter_probe = media_control_server_probe,
+ .adapter_remove = media_control_server_remove,
+};
+
+static int mcp_init(void)
+{
+ DBG("");
+
+ if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
+ warn("D-Bus experimental not enabled");
+ return -ENOTSUP;
+ }
+
+ btd_profile_register(&mcp_profile);
+ return 0;
+}
+
+static void mcp_exit(void)
+{
+ DBG("");
+
+ if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
+ btd_profile_unregister(&mcp_profile);
+ }
+}
+
+BLUETOOTH_PLUGIN_DEFINE(mcp, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
+ mcp_init, mcp_exit)
--
2.25.1

2022-10-06 14:39:01

by Abhay Maheta

[permalink] [raw]
Subject: [PATCH BlueZ 1/4] lib/uuid: Add GMCS UUIDs

This adds GMCS UUIDs which will be used by Media Control Profile.
---
lib/uuid.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/lib/uuid.h b/lib/uuid.h
index f667a74b9..d5e5665e4 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -171,6 +171,21 @@ extern "C" {
#define VOL_CP_CHRC_UUID 0x2B7E
#define VOL_FLAG_CHRC_UUID 0x2B7F

+#define GMCS_UUID 0x1849
+#define MEDIA_PLAYER_NAME_CHRC_UUID 0x2b93
+#define MEDIA_TRACK_CHNGD_CHRC_UUID 0x2b96
+#define MEDIA_TRACK_TITLE_CHRC_UUID 0x2b97
+#define MEDIA_TRACK_DURATION_CHRC_UUID 0x2b98
+#define MEDIA_TRACK_POSTION_CHRC_UUID 0x2b99
+#define MEDIA_PLAYBACK_SPEED_CHRC_UUID 0x2b9a
+#define MEDIA_SEEKING_SPEED_CHRC_UUID 0x2b9b
+#define MEDIA_PLAYING_ORDER_CHRC_UUID 0x2ba1
+#define MEDIA_PLAY_ORDER_SUPPRTD_CHRC_UUID 0x2ba2
+#define MEDIA_STATE_CHRC_UUID 0x2ba3
+#define MEDIA_CP_CHRC_UUID 0x2ba4
+#define MEDIA_CP_OP_SUPPORTED_CHRC_UUID 0x2ba5
+#define MEDIA_CONTENT_CONTROL_ID_CHRC_UUID 0x2bba
+
typedef struct {
enum {
BT_UUID_UNSPEC = 0,
--
2.25.1

2022-10-06 14:39:01

by Abhay Maheta

[permalink] [raw]
Subject: [PATCH BlueZ 4/4] monitor/att: Add decoding support for GMCS

This adds decoding support for GMCS attributes.

< ACL Data TX: Handle 3585 flags 0x00 dlen 7
ATT: Read Request (0x0a) len 2
Handle: 0x0056 Type: Media Control Point Opcodes Supported (0x2ba5)
> ACL Data RX: Handle 3585 flags 0x02 dlen 9
ATT: Read Response (0x0b) len 4
Value: 33180000
Handle: 0x0056 Type: Media Control Point Opcodes Supported (0x2ba5)
Supported Opcodes: 0x00001833
Play (0x00000001)
Pause (0x00000002)
Stop (0x00000010)
Move Relative (0x00000020)
Previous Track (0x00000800)
Next Track (0x00001000)
---
monitor/att.c | 511 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 511 insertions(+)

diff --git a/monitor/att.c b/monitor/att.c
index f5fc32cb0..1bb9f58f6 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -14,6 +14,7 @@
#endif

#define _GNU_SOURCE
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -22,6 +23,8 @@
#include <errno.h>
#include <linux/limits.h>

+#include <glib.h>
+
#include "lib/bluetooth.h"
#include "lib/uuid.h"
#include "lib/hci.h"
@@ -1746,6 +1749,497 @@ static void vol_flag_notify(const struct l2cap_frame *frame)
print_vcs_flag(frame);
}

+static char *name2utf8(const uint8_t *name, uint16_t len)
+{
+ char utf8_name[HCI_MAX_NAME_LENGTH + 2];
+ int i;
+
+ if (g_utf8_validate((const char *) name, len, NULL))
+ return g_strndup((char *) name, len);
+
+ len = MIN(len, sizeof(utf8_name) - 1);
+
+ memset(utf8_name, 0, sizeof(utf8_name));
+ strncpy(utf8_name, (char *) name, len);
+
+ /* Assume ASCII, and replace all non-ASCII with spaces */
+ for (i = 0; utf8_name[i] != '\0'; i++) {
+ if (!isascii(utf8_name[i]))
+ utf8_name[i] = ' ';
+ }
+
+ /* Remove leading and trailing whitespace characters */
+ g_strstrip(utf8_name);
+
+ return g_strdup(utf8_name);
+}
+
+static void print_mp_name(const struct l2cap_frame *frame)
+{
+ char *name;
+
+ name = name2utf8((uint8_t *)frame->data, frame->size);
+
+ print_field(" Media Player Name: %s", name);
+}
+
+static void mp_name_read(const struct l2cap_frame *frame)
+{
+ print_mp_name(frame);
+}
+
+static void mp_name_notify(const struct l2cap_frame *frame)
+{
+ print_mp_name(frame);
+}
+
+static void print_track_changed(const struct l2cap_frame *frame)
+{
+ print_field(" Track Changed");
+}
+
+static void track_changed_notify(const struct l2cap_frame *frame)
+{
+ print_track_changed(frame);
+}
+
+static void print_track_title(const struct l2cap_frame *frame)
+{
+ char *name;
+
+ name = name2utf8((uint8_t *)frame->data, frame->size);
+
+ print_field(" Track Title: %s", name);
+}
+
+static void track_title_read(const struct l2cap_frame *frame)
+{
+ print_track_title(frame);
+}
+
+static void track_title_notify(const struct l2cap_frame *frame)
+{
+ print_track_title(frame);
+}
+
+static void print_track_duration(const struct l2cap_frame *frame)
+{
+ int32_t duration;
+
+ if (!l2cap_frame_get_le32((void *)frame, (uint32_t *)&duration)) {
+ print_text(COLOR_ERROR, " Track Duration: invalid size");
+ goto done;
+ }
+
+ print_field(" Track Duration: %u", duration);
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void track_duration_read(const struct l2cap_frame *frame)
+{
+ print_track_duration(frame);
+}
+
+static void track_duration_notify(const struct l2cap_frame *frame)
+{
+ print_track_duration(frame);
+}
+
+static void print_track_position(const struct l2cap_frame *frame)
+{
+ int32_t position;
+
+ if (!l2cap_frame_get_le32((void *)frame, (uint32_t *)&position)) {
+ print_text(COLOR_ERROR, " Track Position: invalid size");
+ goto done;
+ }
+
+ print_field(" Track Position: %u", position);
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void track_position_read(const struct l2cap_frame *frame)
+{
+ print_track_position(frame);
+}
+
+static void track_position_write(const struct l2cap_frame *frame)
+{
+ print_track_position(frame);
+}
+
+static void track_position_notify(const struct l2cap_frame *frame)
+{
+ print_track_position(frame);
+}
+
+static void print_playback_speed(const struct l2cap_frame *frame)
+{
+ int8_t playback_speed;
+
+ if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&playback_speed)) {
+ print_text(COLOR_ERROR, " Playback Speed: invalid size");
+ goto done;
+ }
+
+ print_field(" Playback Speed: %u", playback_speed);
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void playback_speed_read(const struct l2cap_frame *frame)
+{
+ print_playback_speed(frame);
+}
+
+static void playback_speed_write(const struct l2cap_frame *frame)
+{
+ print_playback_speed(frame);
+}
+
+static void playback_speed_notify(const struct l2cap_frame *frame)
+{
+ print_playback_speed(frame);
+}
+
+static void print_seeking_speed(const struct l2cap_frame *frame)
+{
+ int8_t seeking_speed;
+
+ if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&seeking_speed)) {
+ print_text(COLOR_ERROR, " Seeking Speed: invalid size");
+ goto done;
+ }
+
+ print_field(" Seeking Speed: %u", seeking_speed);
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void seeking_speed_read(const struct l2cap_frame *frame)
+{
+ print_seeking_speed(frame);
+}
+
+static void seeking_speed_notify(const struct l2cap_frame *frame)
+{
+ print_seeking_speed(frame);
+}
+
+const char *play_order_str(uint8_t order)
+{
+ switch (order) {
+ case 0x01:
+ return "Single once";
+ case 0x02:
+ return "Single repeat";
+ case 0x03:
+ return "In order once";
+ case 0x04:
+ return "In order repeat";
+ case 0x05:
+ return "Oldest once";
+ case 0x06:
+ return "Oldest repeat";
+ case 0x07:
+ return "Newest once";
+ case 0x08:
+ return "Newest repeat";
+ case 0x09:
+ return "Shuffle once";
+ case 0x0A:
+ return "Shuffle repeat";
+ default:
+ return "RFU";
+ }
+}
+
+static void print_playing_order(const struct l2cap_frame *frame)
+{
+ int8_t playing_order;
+
+ if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&playing_order)) {
+ print_text(COLOR_ERROR, " Playing Order: invalid size");
+ goto done;
+ }
+
+ print_field(" Playing Order: %s", play_order_str(playing_order));
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void playing_order_read(const struct l2cap_frame *frame)
+{
+ print_playing_order(frame);
+}
+
+static void playing_order_write(const struct l2cap_frame *frame)
+{
+ print_playing_order(frame);
+}
+
+static void playing_order_notify(const struct l2cap_frame *frame)
+{
+ print_playing_order(frame);
+}
+
+static const struct bitfield_data playing_orders_table[] = {
+ { 0, "Single once (0x0001)" },
+ { 1, "Single repeat (0x0002)" },
+ { 2, "In order once (0x0004)" },
+ { 3, "In Order Repeat (0x0008)" },
+ { 4, "Oldest once (0x0010)" },
+ { 5, "Oldest repeat (0x0020)" },
+ { 6, "Newest once (0x0040)" },
+ { 7, "Newest repeat (0x0080)" },
+ { 8, "Shuffle once (0x0100)" },
+ { 9, "Shuffle repeat (0x0200)" },
+ { 10, "RFU (0x0400)" },
+ { 11, "RFU (0x0800)" },
+ { 12, "RFU (0x1000)" },
+ { 13, "RFU (0x2000)" },
+ { 14, "RFU (0x4000)" },
+ { 15, "RFU (0x8000)" },
+ { }
+};
+
+static void print_playing_orders_supported(const struct l2cap_frame *frame)
+{
+ uint16_t supported_orders;
+ uint16_t mask;
+
+ if (!l2cap_frame_get_le16((void *)frame, &supported_orders)) {
+ print_text(COLOR_ERROR, " Supported Playing Orders: invalid size");
+ goto done;
+ }
+
+ print_field(" Supported Playing Orders: 0x%4.4x", supported_orders);
+
+ mask = print_bitfield(8, supported_orders, playing_orders_table);
+ if (mask)
+ print_text(COLOR_WHITE_BG, " Unknown fields (0x%4.4x)",
+ mask);
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void playing_orders_supported_read(const struct l2cap_frame *frame)
+{
+ print_playing_orders_supported(frame);
+}
+
+const char *media_state_str(uint8_t state)
+{
+ switch (state) {
+ case 0x00:
+ return "Inactive";
+ case 0x01:
+ return "Playing";
+ case 0x02:
+ return "Paused";
+ case 0x03:
+ return "Seeking";
+ default:
+ return "RFU";
+ }
+}
+
+static void print_media_state(const struct l2cap_frame *frame)
+{
+ int8_t state;
+
+ if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&state)) {
+ print_text(COLOR_ERROR, " Media State: invalid size");
+ goto done;
+ }
+
+ print_field(" Media State: %s", media_state_str(state));
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void media_state_read(const struct l2cap_frame *frame)
+{
+ print_media_state(frame);
+}
+
+static void media_state_notify(const struct l2cap_frame *frame)
+{
+ print_media_state(frame);
+}
+
+struct media_cp_opcode {
+ uint8_t opcode;
+ const char *opcode_str;
+} media_cp_opcode_table[] = {
+ {0x01, "Play"},
+ {0x02 , "Pause"},
+ {0x03 , "Fast Rewind"},
+ {0x04 , "Fast Forward"},
+ {0x05 , "Stop"},
+ {0x10 , "Move Relative"},
+ {0x20 , "Previous Segment"},
+ {0x21 , "Next Segment"},
+ {0x22 , "First Segment"},
+ {0x23 , "Last Segment"},
+ {0x24 , "Goto Segment"},
+ {0x30 , "Previous Track"},
+ {0x31 , "Next Track"},
+ {0x32 , "First Track"},
+ {0x33 , "Last Track"},
+ {0x34 , "Goto Track"},
+ {0x40 , "Previous Group"},
+ {0x41 , "Next Group"},
+ {0x42 , "First Group"},
+ {0x43 , "Last Group"},
+ {0x44 , "Goto Group"},
+};
+
+const char *cp_opcode_str(uint8_t opcode)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(media_cp_opcode_table); i++) {
+ const char *str = media_cp_opcode_table[i].opcode_str;
+
+ if (opcode == media_cp_opcode_table[i].opcode)
+ return str;
+ }
+
+ return "RFU";
+}
+
+static void print_media_cp(const struct l2cap_frame *frame)
+{
+ int8_t opcode;
+
+ if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&opcode)) {
+ print_text(COLOR_ERROR, " Media Control Point: invalid size");
+ goto done;
+ }
+
+ print_field(" Media Control Point: %s", cp_opcode_str(opcode));
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void media_cp_write(const struct l2cap_frame *frame)
+{
+ print_media_cp(frame);
+}
+
+static void media_cp_notify(const struct l2cap_frame *frame)
+{
+ print_media_cp(frame);
+}
+
+static const struct bitfield_data supported_opcodes_table[] = {
+ {0 , "Play (0x00000001)" },
+ {1 , "Pause (0x00000002)" },
+ {2 , "Fast Rewind (0x00000004)" },
+ {3 , "Fast Forward (0x00000008)" },
+ {4 , "Stop (0x00000010)" },
+ {5 , "Move Relative (0x00000020)" },
+ {6 , "Previous Segment (0x00000040)" },
+ {7 , "Next Segment (0x00000080)" },
+ {8 , "First Segment (0x00000100)" },
+ {9 , "Last Segment (0x00000200)" },
+ {10 , "Goto Segment (0x00000400)" },
+ {11 , "Previous Track (0x00000800)" },
+ {12 , "Next Track (0x00001000)" },
+ {13 , "First Track (0x00002000)" },
+ {14 , "Last Track (0x00004000)" },
+ {15 , "Goto Track (0x00008000)" },
+ {16 , "Previous Group (0x00010000)" },
+ {17 , "Next Group (0x00020000)" },
+ {18 , "First Group (0x00040000)" },
+ {19 , "Last Group (0x00080000)" },
+ {20 , "Goto Group (0x00100000)" },
+ {21 , "RFU (0x00200000)" },
+ {22 , "RFU (0x00400000)" },
+ {23 , "RFU (0x00800000)" },
+ {24 , "RFU (0x01000000)" },
+ {25 , "RFU (0x02000000)" },
+ {26 , "RFU (0x04000000)" },
+ {27 , "RFU (0x08000000)" },
+ {28 , "RFU (0x10000000)" },
+ {29 , "RFU (0x20000000)" },
+ {30 , "RFU (0x40000000)" },
+ {31 , "RFU (0x80000000)" },
+ { }
+};
+
+static void print_media_cp_op_supported(const struct l2cap_frame *frame)
+{
+ uint32_t supported_opcodes;
+ uint32_t mask;
+
+ if (!l2cap_frame_get_le32((void *)frame, &supported_opcodes)) {
+ print_text(COLOR_ERROR, " value: invalid size");
+ goto done;
+ }
+
+ print_field(" Supported Opcodes: 0x%8.8x", supported_opcodes);
+
+ mask = print_bitfield(8, supported_opcodes, supported_opcodes_table);
+ if (mask)
+ print_text(COLOR_WHITE_BG, " Unknown fields (0x%4.4x)",
+ mask);
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void media_cp_op_supported_read(const struct l2cap_frame *frame)
+{
+ print_media_cp_op_supported(frame);
+}
+
+static void media_cp_op_supported_notify(const struct l2cap_frame *frame)
+{
+ print_media_cp_op_supported(frame);
+}
+
+static void print_content_control_id(const struct l2cap_frame *frame)
+{
+ int8_t ccid;
+
+ if (!l2cap_frame_get_u8((void *)frame, (uint8_t *)&ccid)) {
+ print_text(COLOR_ERROR, " Content Control ID: invalid size");
+ goto done;
+ }
+
+ print_field(" Content Control ID: 0x%2.2x", ccid);
+
+done:
+ if (frame->size)
+ print_hex_field(" Data", frame->data, frame->size);
+}
+
+static void content_control_id_read(const struct l2cap_frame *frame)
+{
+ print_content_control_id(frame);
+}
+
#define GATT_HANDLER(_uuid, _read, _write, _notify) \
{ \
.uuid = { \
@@ -1776,6 +2270,23 @@ struct gatt_handler {
GATT_HANDLER(0x2b7d, vol_state_read, NULL, vol_state_notify),
GATT_HANDLER(0x2b7e, NULL, vol_cp_write, NULL),
GATT_HANDLER(0x2b7f, vol_flag_read, NULL, vol_flag_notify),
+ GATT_HANDLER(0x2b93, mp_name_read, NULL, mp_name_notify),
+ GATT_HANDLER(0x2b96, NULL, NULL, track_changed_notify),
+ GATT_HANDLER(0x2b97, track_title_read, NULL, track_title_notify),
+ GATT_HANDLER(0x2b98, track_duration_read, NULL, track_duration_notify),
+ GATT_HANDLER(0x2b99, track_position_read, track_position_write,
+ track_position_notify),
+ GATT_HANDLER(0x2b9a, playback_speed_read, playback_speed_write,
+ playback_speed_notify),
+ GATT_HANDLER(0x2b9b, seeking_speed_read, NULL, seeking_speed_notify),
+ GATT_HANDLER(0x2ba1, playing_order_read, playing_order_write,
+ playing_order_notify),
+ GATT_HANDLER(0x2ba2, playing_orders_supported_read, NULL, NULL),
+ GATT_HANDLER(0x2ba3, media_state_read, NULL, media_state_notify),
+ GATT_HANDLER(0x2ba4, NULL, media_cp_write, media_cp_notify),
+ GATT_HANDLER(0x2ba5, media_cp_op_supported_read, NULL,
+ media_cp_op_supported_notify),
+ GATT_HANDLER(0x2bba, content_control_id_read, NULL, NULL),
};

static struct gatt_handler *get_handler(struct gatt_db_attribute *attr)
--
2.25.1

2022-10-06 14:39:01

by Abhay Maheta

[permalink] [raw]
Subject: [PATCH BlueZ 2/4] shared/mcp: Add initial code for handling MCP

This adds initial code for Media Control Profile for Client Role.
---
Makefile.am | 1 +
src/shared/mcp.c | 1408 ++++++++++++++++++++++++++++++++++++++++++++++
src/shared/mcp.h | 60 ++
src/shared/mcs.h | 65 +++
4 files changed, 1534 insertions(+)
create mode 100644 src/shared/mcp.c
create mode 100644 src/shared/mcp.h
create mode 100644 src/shared/mcs.h

diff --git a/Makefile.am b/Makefile.am
index 27715c73d..23f6c1b98 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -231,6 +231,7 @@ shared_sources = src/shared/io.h src/shared/timeout.h \
src/shared/gap.h src/shared/gap.c \
src/shared/log.h src/shared/log.c \
src/shared/bap.h src/shared/bap.c src/shared/ascs.h \
+ src shared/mcs.h src/shared/mcp.h src/shared/mcp.c \
src/shared/vcp.c src/shared/vcp.h \
src/shared/lc3.h src/shared/tty.h

diff --git a/src/shared/mcp.c b/src/shared/mcp.c
new file mode 100644
index 000000000..20f18d2c0
--- /dev/null
+++ b/src/shared/mcp.c
@@ -0,0 +1,1408 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define _GNU_SOURCE
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "lib/bluetooth.h"
+#include "lib/uuid.h"
+#include "lib/hci.h"
+
+#include "src/shared/queue.h"
+#include "src/shared/util.h"
+#include "src/shared/timeout.h"
+#include "src/shared/att.h"
+#include "src/shared/gatt-db.h"
+#include "src/shared/gatt-server.h"
+#include "src/shared/gatt-client.h"
+#include "src/shared/mcp.h"
+#include "src/shared/mcs.h"
+
+#define DBG(_mcp, fmt, arg...) \
+ mcp_debug(_mcp, "%s:%s() " fmt, __FILE__, __func__, ## arg)
+
+struct bt_mcp_db {
+ struct gatt_db *db;
+ struct bt_mcs *mcs;
+};
+
+struct bt_mcp_pending {
+ unsigned int id;
+ struct bt_mcp *mcp;
+ bt_gatt_client_read_callback_t func;
+ void *user_data;
+};
+
+struct event_callback {
+ const struct bt_mcp_event_callback *cbs;
+ void *user_data;
+};
+
+struct bt_mcp_session_info {
+ uint8_t content_control_id;
+ uint32_t cp_op_supported;
+};
+
+struct bt_mcp {
+ int ref_count;
+ struct bt_gatt_client *client;
+ struct bt_mcp_db *ldb;
+ struct bt_mcp_db *rdb;
+ unsigned int mp_name_id;
+ unsigned int track_changed_id;
+ unsigned int track_title_id;
+ unsigned int track_duration_id;
+ unsigned int track_position_id;
+ unsigned int media_state_id;
+ unsigned int media_cp_id;
+ unsigned int media_cp_op_supported_id;
+
+ struct bt_mcp_session_info session;
+ struct event_callback *cb;
+
+ struct queue *pending;
+
+ bt_mcp_debug_func_t debug_func;
+ bt_mcp_destroy_func_t debug_destroy;
+ void *debug_data;
+ void *user_data;
+};
+
+struct bt_mcs {
+ struct bt_mcp_db *mdb;
+ struct gatt_db_attribute *service;
+ struct gatt_db_attribute *mp_name;
+ struct gatt_db_attribute *track_changed;
+ struct gatt_db_attribute *track_changed_ccc;
+ struct gatt_db_attribute *track_title;
+ struct gatt_db_attribute *track_duration;
+ struct gatt_db_attribute *track_position;
+ struct gatt_db_attribute *playback_speed;
+ struct gatt_db_attribute *seeking_speed;
+ struct gatt_db_attribute *play_order;
+ struct gatt_db_attribute *play_order_supported;
+ struct gatt_db_attribute *media_state;
+ struct gatt_db_attribute *media_state_ccc;
+ struct gatt_db_attribute *media_cp;
+ struct gatt_db_attribute *media_cp_ccc;
+ struct gatt_db_attribute *media_cp_op_supportd;
+ struct gatt_db_attribute *content_control_id;
+ struct gatt_db_attribute *content_control_id_ccc;
+};
+
+static struct queue *mcp_db;
+
+static void mcp_debug(struct bt_mcp *mcp, const char *format, ...)
+{
+ va_list ap;
+
+ if (!mcp || !format || !mcp->debug_func)
+ return;
+
+ va_start(ap, format);
+ util_debug_va(mcp->debug_func, mcp->debug_data, format, ap);
+ va_end(ap);
+}
+
+static bool mcp_db_match(const void *data, const void *match_data)
+{
+ const struct bt_mcp_db *mdb = data;
+ const struct gatt_db *db = match_data;
+
+ return (mdb->db == db);
+}
+
+static void mcp_db_free(void *data)
+{
+ struct bt_mcp_db *bdb = data;
+
+ if (!bdb)
+ return;
+
+ gatt_db_unref(bdb->db);
+
+ free(bdb->mcs);
+ free(bdb);
+}
+
+static void mcp_free(void *data)
+{
+ struct bt_mcp *mcp = data;
+
+ DBG(mcp, "");
+
+ bt_mcp_detach(mcp);
+
+ mcp_db_free(mcp->rdb);
+
+ queue_destroy(mcp->pending, NULL);
+
+ free(mcp);
+}
+
+struct bt_mcp *bt_mcp_ref(struct bt_mcp *mcp)
+{
+ if (!mcp)
+ return NULL;
+
+ __sync_fetch_and_add(&mcp->ref_count, 1);
+
+ return mcp;
+}
+
+void bt_mcp_unref(struct bt_mcp *mcp)
+{
+ if (!mcp)
+ return;
+
+ if (__sync_sub_and_fetch(&mcp->ref_count, 1))
+ return;
+
+ mcp_free(mcp);
+}
+
+bool bt_mcp_set_user_data(struct bt_mcp *mcp, void *user_data)
+{
+ if (!mcp)
+ return false;
+
+ mcp->user_data = user_data;
+
+ return true;
+}
+
+void *bt_mcp_get_user_data(struct bt_mcp *mcp)
+{
+ if (!mcp)
+ return NULL;
+
+ return mcp->user_data;
+}
+
+bool bt_mcp_set_debug(struct bt_mcp *mcp, bt_mcp_debug_func_t func,
+ void *user_data, bt_mcp_destroy_func_t destroy)
+{
+ if (!mcp)
+ return false;
+
+ if (mcp->debug_destroy)
+ mcp->debug_destroy(mcp->debug_data);
+
+ mcp->debug_func = func;
+ mcp->debug_destroy = destroy;
+ mcp->debug_data = user_data;
+
+ return true;
+}
+
+static void mcs_mp_name_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ char mp_name[] = "";
+ struct iovec iov;
+
+ iov.iov_base = mp_name;
+ iov.iov_len = sizeof(mp_name);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_track_title_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ char track_title[] = "";
+ struct iovec iov;
+
+ iov.iov_base = track_title;
+ iov.iov_len = 0;
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_track_duration_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ int32_t track_duration = 0xFFFFFFFF;
+ struct iovec iov;
+
+ iov.iov_base = &track_duration;
+ iov.iov_len = sizeof(track_duration);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_track_position_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ int32_t track_position = 0xFFFFFFFF;
+ struct iovec iov;
+
+ iov.iov_base = &track_position;
+ iov.iov_len = sizeof(track_position);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_track_position_write(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ const uint8_t *value, size_t len,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ gatt_db_attribute_write_result(attrib, id,
+ BT_ATT_ERROR_INSUFFICIENT_RESOURCES);
+}
+
+static void mcs_playback_speed_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ int8_t playback_speed = 0x00;
+ struct iovec iov;
+
+ iov.iov_base = &playback_speed;
+ iov.iov_len = sizeof(playback_speed);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_playback_speed_write(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ const uint8_t *value, size_t len,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ gatt_db_attribute_write_result(attrib, id,
+ BT_ATT_ERROR_INSUFFICIENT_RESOURCES);
+}
+
+static void mcs_seeking_speed_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ int8_t seeking_speed = 0x00;
+ struct iovec iov;
+
+ iov.iov_base = &seeking_speed;
+ iov.iov_len = sizeof(seeking_speed);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_playing_order_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ uint8_t playing_order = 0x01;
+ struct iovec iov;
+
+ iov.iov_base = &playing_order;
+ iov.iov_len = sizeof(playing_order);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_playing_order_write(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ const uint8_t *value, size_t len,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ gatt_db_attribute_write_result(attrib, id,
+ BT_ATT_ERROR_INSUFFICIENT_RESOURCES);
+}
+
+static void mcs_playing_order_supported_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ uint16_t playing_order_supported = 0x01;
+ struct iovec iov;
+
+ iov.iov_base = &playing_order_supported;
+ iov.iov_len = sizeof(playing_order_supported);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_media_state_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ uint8_t media_state = 0x00;
+ struct iovec iov;
+
+ iov.iov_base = &media_state;
+ iov.iov_len = sizeof(media_state);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_media_cp_write(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ const uint8_t *value, size_t len,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ gatt_db_attribute_write_result(attrib, id,
+ BT_ATT_ERROR_INSUFFICIENT_RESOURCES);
+}
+
+static void mcs_media_cp_op_supported_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ uint32_t cp_op_supported = 0x00000000;
+ struct iovec iov;
+
+ iov.iov_base = &cp_op_supported;
+ iov.iov_len = sizeof(cp_op_supported);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static void mcs_media_content_control_id_read(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ uint8_t content_control_id = 0x00;
+ struct iovec iov;
+
+ iov.iov_base = &content_control_id;
+ iov.iov_len = sizeof(content_control_id);
+
+ gatt_db_attribute_read_result(attrib, id, 0, iov.iov_base,
+ iov.iov_len);
+}
+
+static struct bt_mcs *mcs_new(struct gatt_db *db)
+{
+ struct bt_mcs *mcs;
+ bt_uuid_t uuid;
+
+ if (!db)
+ return NULL;
+
+ mcs = new0(struct bt_mcs, 1);
+
+ /* Populate DB with MCS attributes */
+ bt_uuid16_create(&uuid, GMCS_UUID);
+ mcs->service = gatt_db_add_service(db, &uuid, true, 31);
+
+ bt_uuid16_create(&uuid, MEDIA_PLAYER_NAME_CHRC_UUID);
+ mcs->mp_name = gatt_db_service_add_characteristic(mcs->service, &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ mcs_mp_name_read, NULL,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_TRACK_CHNGD_CHRC_UUID);
+ mcs->track_changed = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_NONE,
+ BT_GATT_CHRC_PROP_NOTIFY,
+ NULL, NULL,
+ mcs);
+
+ mcs->track_changed_ccc = gatt_db_service_add_ccc(mcs->service,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+ bt_uuid16_create(&uuid, MEDIA_TRACK_TITLE_CHRC_UUID);
+ mcs->track_title = gatt_db_service_add_characteristic(mcs->service, &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ mcs_track_title_read, NULL,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_TRACK_DURATION_CHRC_UUID);
+ mcs->track_duration = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ mcs_track_duration_read, NULL,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_TRACK_POSTION_CHRC_UUID);
+ mcs->track_position = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_WRITE |
+ BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP,
+ mcs_track_position_read, mcs_track_position_write,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_PLAYBACK_SPEED_CHRC_UUID);
+ mcs->playback_speed = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_WRITE |
+ BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP,
+ mcs_playback_speed_read, mcs_playback_speed_write,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_SEEKING_SPEED_CHRC_UUID);
+ mcs->seeking_speed = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ mcs_seeking_speed_read, NULL,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_PLAYING_ORDER_CHRC_UUID);
+ mcs->play_order = gatt_db_service_add_characteristic(mcs->service, &uuid,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE,
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_WRITE |
+ BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP,
+ mcs_playing_order_read, mcs_playing_order_write,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_PLAY_ORDER_SUPPRTD_CHRC_UUID);
+ mcs->play_order_supported = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ mcs_playing_order_supported_read, NULL,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_STATE_CHRC_UUID);
+ mcs->media_state = gatt_db_service_add_characteristic(mcs->service, &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_NOTIFY,
+ mcs_media_state_read, NULL,
+ mcs);
+
+ mcs->media_state_ccc = gatt_db_service_add_ccc(mcs->service,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+ bt_uuid16_create(&uuid, MEDIA_CP_CHRC_UUID);
+ mcs->media_cp = gatt_db_service_add_characteristic(mcs->service, &uuid,
+ BT_ATT_PERM_WRITE,
+ BT_GATT_CHRC_PROP_WRITE | BT_GATT_CHRC_PROP_NOTIFY |
+ BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP,
+ NULL, mcs_media_cp_write,
+ mcs);
+
+ mcs->media_cp_ccc = gatt_db_service_add_ccc(mcs->service,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+ bt_uuid16_create(&uuid, MEDIA_CP_OP_SUPPORTED_CHRC_UUID);
+ mcs->media_cp_op_supportd = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ,
+ mcs_media_cp_op_supported_read, NULL,
+ mcs);
+
+ bt_uuid16_create(&uuid, MEDIA_CONTENT_CONTROL_ID_CHRC_UUID);
+ mcs->content_control_id = gatt_db_service_add_characteristic(mcs->service,
+ &uuid,
+ BT_ATT_PERM_READ,
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_NOTIFY,
+ mcs_media_content_control_id_read, NULL,
+ mcs);
+
+ mcs->content_control_id_ccc = gatt_db_service_add_ccc(mcs->service,
+ BT_ATT_PERM_READ | BT_ATT_PERM_WRITE);
+
+ gatt_db_service_set_active(mcs->service, false);
+
+ return mcs;
+}
+
+static struct bt_mcs *mcp_get_mcs(struct bt_mcp *mcp)
+{
+ if (!mcp)
+ return NULL;
+
+ if (mcp->rdb->mcs)
+ return mcp->rdb->mcs;
+
+ mcp->rdb->mcs = new0(struct bt_mcs, 1);
+ mcp->rdb->mcs->mdb = mcp->rdb;
+
+ return mcp->rdb->mcs;
+}
+
+static unsigned int mcp_send(struct bt_mcp *mcp, uint8_t operation)
+{
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+ int ret;
+ uint16_t handle;
+
+ DBG(mcp, "mcs %p", mcs);
+
+ if (!mcp->client)
+ return -1;
+
+ if (!gatt_db_attribute_get_char_data(mcs->media_cp, NULL, &handle,
+ NULL, NULL, NULL))
+ return -1;
+
+ ret = bt_gatt_client_write_without_response(mcp->client, handle, false,
+ &operation, sizeof(uint8_t));
+ if (!ret)
+ return -1;
+
+ return 0;
+}
+
+unsigned int bt_mcp_play(struct bt_mcp *mcp)
+{
+ if (!(mcp->session.cp_op_supported & BT_MCS_CMD_PLAY_SUPPORTED))
+ return -ENOTSUP;
+
+ DBG(mcp, "mcp %p", mcp);
+
+ return mcp_send(mcp, BT_MCS_CMD_PLAY);
+}
+
+unsigned int bt_mcp_pause(struct bt_mcp *mcp)
+{
+ if (!(mcp->session.cp_op_supported & BT_MCS_CMD_PAUSE_SUPPORTED))
+ return -ENOTSUP;
+
+ DBG(mcp, "mcp %p", mcp);
+
+ return mcp_send(mcp, BT_MCS_CMD_PAUSE);
+}
+
+unsigned int bt_mcp_stop(struct bt_mcp *mcp)
+{
+ if (!(mcp->session.cp_op_supported & BT_MCS_CMD_STOP_SUPPORTED))
+ return -ENOTSUP;
+
+ DBG(mcp, "mcp %p", mcp);
+
+ return mcp_send(mcp, BT_MCS_CMD_STOP);
+}
+
+static void mcp_mp_set_player_name(struct bt_mcp *mcp, const uint8_t *value,
+ uint16_t length)
+{
+ struct event_callback *cb = mcp->cb;
+
+ if (cb && cb->cbs && cb->cbs->player_name)
+ cb->cbs->player_name(mcp, value, length);
+}
+
+static void mcp_mp_set_track_title(struct bt_mcp *mcp, const uint8_t *value,
+ uint16_t length)
+{
+ struct event_callback *cb = mcp->cb;
+
+ if (cb && cb->cbs && cb->cbs->track_title)
+ cb->cbs->track_title(mcp, value, length);
+}
+
+static void mcp_mp_set_title_duration(struct bt_mcp *mcp, int32_t duration)
+{
+ struct event_callback *cb = mcp->cb;
+
+ DBG(mcp, "Track Duration 0x%08x", duration);
+
+ if (cb && cb->cbs && cb->cbs->track_duration)
+ cb->cbs->track_duration(mcp, duration);
+}
+
+static void mcp_mp_set_title_position(struct bt_mcp *mcp, int32_t position)
+{
+ struct event_callback *cb = mcp->cb;
+
+ DBG(mcp, "Track Position 0x%08x", position);
+
+ if (cb && cb->cbs && cb->cbs->track_position)
+ cb->cbs->track_position(mcp, position);
+}
+
+static void mcp_mp_set_media_state(struct bt_mcp *mcp, uint8_t state)
+{
+ struct event_callback *cb = mcp->cb;
+
+ DBG(mcp, "Media State 0x%02x", state);
+
+ if (cb && cb->cbs && cb->cbs->media_state)
+ cb->cbs->media_state(mcp, state);
+}
+
+static void read_media_player_name(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (!success) {
+ DBG(mcp, "Unable to read media player name: error 0x%02x", att_ecode);
+ return;
+ }
+
+ if (!length)
+ return;
+
+ mcp_mp_set_player_name(mcp, value, length);
+}
+
+static void read_track_title(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ struct event_callback *cb = mcp->cb;
+
+ if (!success) {
+ DBG(mcp, "Unable to read track title: error 0x%02x", att_ecode);
+ return;
+ }
+
+ if (!length)
+ return;
+
+ mcp_mp_set_track_title(mcp, value, length);
+}
+
+static void read_track_duration(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ int32_t duration;
+
+ if (!success) {
+ DBG(mcp, "Unable to read track duration: error 0x%02x", att_ecode);
+ return;
+ }
+
+ if (length != sizeof(duration)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }
+
+ memcpy(&duration, value, length);
+ mcp_mp_set_title_duration(mcp, duration);
+}
+
+static void read_track_position(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ int32_t position;
+
+ if (!success) {
+ DBG(mcp, "Unable to read track position: error 0x%02x", att_ecode);
+ return;
+ }
+
+ if (length != sizeof(position)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }
+
+ memcpy(&position, value, length);
+ mcp_mp_set_title_position(mcp, position);
+}
+
+static void read_media_state(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (!success) {
+ DBG(mcp, "Unable to read media state: error 0x%02x", att_ecode);
+ return;
+ }
+
+ if (length != sizeof(uint8_t)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }
+
+ mcp_mp_set_media_state(mcp, *value);
+}
+
+static void read_media_cp_op_supported(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (!success) {
+ DBG(mcp, "Unable to read media CP opcodes supported: error 0x%02x",
+ att_ecode);
+ return;
+ }
+
+ if (length != sizeof(uint32_t)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }
+
+ memcpy(&mcp->session.cp_op_supported, value, sizeof(uint32_t));
+ DBG(mcp, "Media Control Point Opcodes Supported 0x%08x",
+ mcp->session.cp_op_supported);
+}
+
+static void read_content_control_id(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (!success) {
+ DBG(mcp, "Unable to read content control id: error 0x%02x", att_ecode);
+ return;
+ }
+
+ if (length != sizeof(uint8_t)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }
+
+ DBG(mcp, "Content Control ID 0x%02x", *value);
+}
+
+static void mcp_pending_destroy(void *data)
+{
+ struct bt_mcp_pending *pending = data;
+ struct bt_mcp *mcp = pending->mcp;
+
+ queue_remove_if(mcp->pending, NULL, pending);
+}
+
+static void mcp_pending_complete(bool success, uint8_t att_ecode,
+ const uint8_t *value, uint16_t length,
+ void *user_data)
+{
+ struct bt_mcp_pending *pending = user_data;
+
+ if (pending->func)
+ pending->func(success, att_ecode, value, length,
+ pending->user_data);
+}
+
+static void mcp_read_value(struct bt_mcp *mcp, uint16_t value_handle,
+ bt_gatt_client_read_callback_t func,
+ void *user_data)
+{
+ struct bt_mcp_pending *pending;
+
+ pending = new0(struct bt_mcp_pending, 1);
+ pending->mcp = mcp;
+ pending->func = func;
+ pending->user_data = user_data;
+
+ pending->id = bt_gatt_client_read_value(mcp->client, value_handle,
+ mcp_pending_complete, pending,
+ mcp_pending_destroy);
+ if (!pending->id) {
+ DBG(mcp, "Unable to send Read request");
+ free(pending);
+ return;
+ }
+
+ queue_push_tail(mcp->pending, pending);
+}
+
+static void mcp_mp_name_register(uint16_t att_ecode, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Player Name notification failed: 0x%04x", att_ecode);
+}
+
+static void mcp_mp_name_notify(uint16_t value_handle, const uint8_t *value,
+ uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (!length)
+ return;
+
+ mcp_mp_set_player_name(mcp, value, length);
+}
+
+static void mcp_track_changed_register(uint16_t att_ecode, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Track Changed notification failed: 0x%04x", att_ecode);
+}
+
+static void mcp_track_changed_notify(uint16_t value_handle,
+ const uint8_t *value, uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ struct event_callback *cb = mcp->cb;
+
+ DBG(mcp, "Track Changed");
+
+ if (cb && cb->cbs && cb->cbs->track_changed)
+ cb->cbs->track_changed(mcp);
+}
+
+static void mcp_track_title_register(uint16_t att_ecode, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Track Title notification failed: 0x%04x", att_ecode);
+}
+
+static void mcp_track_title_notify(uint16_t value_handle, const uint8_t *value,
+ uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ mcp_mp_set_track_title(mcp, value, length);
+}
+
+static void mcp_track_duration_register(uint16_t att_ecode, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Track Duration notification failed: 0x%04x", att_ecode);
+}
+
+static void mcp_track_duration_notify(uint16_t value_handle,
+ const uint8_t *value, uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ int32_t duration;
+
+ memcpy(&duration, value, sizeof(int32_t));
+ mcp_mp_set_title_duration(mcp, duration);
+}
+
+static void mcp_track_position_register(uint16_t att_ecode, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Track Position notification failed: 0x%04x", att_ecode);
+}
+
+static void mcp_track_position_notify(uint16_t value_handle,
+ const uint8_t *value, uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ int32_t position;
+
+ memcpy(&position, value, sizeof(int32_t));
+ mcp_mp_set_title_position(mcp, position);
+}
+
+static void mcp_media_state_register(uint16_t att_ecode, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Media State notification failed: 0x%04x", att_ecode);
+}
+
+static void mcp_media_state_notify(uint16_t value_handle, const uint8_t *value,
+ uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ mcp_mp_set_media_state(mcp, *value);
+}
+
+static void mcp_media_cp_register(uint16_t att_ecode, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Media CP notification failed: 0x%04x", att_ecode);
+}
+
+static void mcp_media_cp_notify(uint16_t value_handle, const uint8_t *value,
+ uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ DBG(mcp, "Media CP Notification");
+}
+
+static void mcp_media_cp_op_supported_register(uint16_t att_ecode,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ if (att_ecode)
+ DBG(mcp, "Media Media CP OP Supported notification failed: 0x%04x",
+ att_ecode);
+}
+
+static void mcp_media_cp_op_supported_notify(uint16_t value_handle,
+ const uint8_t *value, uint16_t length, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+
+ memcpy(&mcp->session.cp_op_supported, value, sizeof(uint32_t));
+ DBG(mcp, "Media CP Opcodes Supported Notification 0x%08x",
+ mcp->session.cp_op_supported);
+}
+
+void bt_mcp_mp_name_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->mp_name, NULL, &value_handle,
+ NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Media Player handle 0x%04x", value_handle);
+
+ mcp_read_value(mcp, value_handle, read_media_player_name, mcp);
+
+ mcp->mp_name_id = bt_gatt_client_register_notify(mcp->client,
+ value_handle, mcp_mp_name_register, mcp_mp_name_notify,
+ mcp, NULL);
+}
+
+void bt_mcp_track_changed_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->track_changed, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Track Changed handle 0x%04x", value_handle);
+
+ mcp->track_changed_id = bt_gatt_client_register_notify(mcp->client,
+ value_handle, mcp_track_changed_register,
+ mcp_track_changed_notify, mcp, NULL);
+}
+
+void bt_mcp_track_title_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->track_title, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Track Title handle 0x%04x", value_handle);
+
+ mcp_read_value(mcp, value_handle, read_track_title, mcp);
+
+ mcp->track_title_id = bt_gatt_client_register_notify(mcp->client,
+ value_handle, mcp_track_title_register,
+ mcp_track_title_notify, mcp, NULL);
+}
+
+void bt_mcp_track_duration_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->track_duration, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Track Duration handle 0x%04x", value_handle);
+
+ mcp_read_value(mcp, value_handle, read_track_duration, mcp);
+
+ mcp->track_duration_id = bt_gatt_client_register_notify(mcp->client,
+ value_handle, mcp_track_duration_register,
+ mcp_track_duration_notify, mcp, NULL);
+}
+
+void bt_mcp_track_position_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->track_position, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Track Position handle 0x%04x", value_handle);
+
+ mcp_read_value(mcp, value_handle, read_track_position, mcp);
+
+ mcp->track_position_id = bt_gatt_client_register_notify(mcp->client,
+ value_handle, mcp_track_position_register,
+ mcp_track_position_notify, mcp, NULL);
+}
+
+void bt_mcp_media_state_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->media_state, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Media State handle 0x%04x", value_handle);
+
+ mcp_read_value(mcp, value_handle, read_media_state, mcp);
+
+ mcp->media_state_id = bt_gatt_client_register_notify(mcp->client,
+ value_handle, mcp_media_state_register,
+ mcp_media_state_notify, mcp, NULL);
+}
+
+void bt_mcp_media_cp_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->media_cp, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Media Control Point handle 0x%04x", value_handle);
+
+ mcp->media_cp_id = bt_gatt_client_register_notify(mcp->client,
+ value_handle, mcp_media_cp_register,
+ mcp_media_cp_notify, mcp, NULL);
+}
+
+void bt_mcp_media_cp_op_supported_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->media_cp_op_supportd, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Media Control Point Opcodes Supported handle 0x%04x",
+ value_handle);
+
+ mcp_read_value(mcp, value_handle, read_media_cp_op_supported, mcp);
+
+ mcp->media_cp_op_supported_id = bt_gatt_client_register_notify(
+ mcp->client, value_handle, mcp_media_cp_op_supported_register,
+ mcp_media_cp_op_supported_notify, mcp, NULL);
+}
+
+void bt_mcp_content_control_id_supported_attach(struct bt_mcp *mcp)
+{
+ uint16_t value_handle;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ if (!gatt_db_attribute_get_char_data(mcs->content_control_id, NULL,
+ &value_handle, NULL, NULL, NULL))
+ return;
+
+ DBG(mcp, "Media Content Control id Supported handle 0x%04x", value_handle);
+ mcp_read_value(mcp, value_handle, read_content_control_id, mcp);
+}
+
+static void foreach_mcs_char(struct gatt_db_attribute *attr, void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ uint16_t value_handle;
+ bt_uuid_t uuid, uuid_mp_name, uuid_track_changed, uuid_track_title,
+ uuid_track_duration, uuid_track_position, uuid_media_state,
+ uuid_media_cp, uuid_media_cp_op_supported,
+ uuid_content_control_id;
+ struct bt_mcs *mcs;
+
+ if (!gatt_db_attribute_get_char_data(attr, NULL, &value_handle,
+ NULL, NULL, &uuid))
+ return;
+
+ bt_uuid16_create(&uuid_mp_name, MEDIA_PLAYER_NAME_CHRC_UUID);
+ bt_uuid16_create(&uuid_track_changed, MEDIA_TRACK_CHNGD_CHRC_UUID);
+ bt_uuid16_create(&uuid_track_title, MEDIA_TRACK_TITLE_CHRC_UUID);
+ bt_uuid16_create(&uuid_track_duration, MEDIA_TRACK_DURATION_CHRC_UUID);
+ bt_uuid16_create(&uuid_track_position, MEDIA_TRACK_POSTION_CHRC_UUID);
+ bt_uuid16_create(&uuid_media_state, MEDIA_STATE_CHRC_UUID);
+ bt_uuid16_create(&uuid_media_cp, MEDIA_CP_CHRC_UUID);
+ bt_uuid16_create(&uuid_media_cp_op_supported,
+ MEDIA_CP_OP_SUPPORTED_CHRC_UUID);
+ bt_uuid16_create(&uuid_content_control_id,
+ MEDIA_CONTENT_CONTROL_ID_CHRC_UUID);
+
+ if (!bt_uuid_cmp(&uuid, &uuid_mp_name)) {
+ DBG(mcp, "Media Player Name found: handle 0x%04x", value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->mp_name)
+ return;
+
+ mcs->mp_name = attr;
+ bt_mcp_mp_name_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_track_changed)) {
+ DBG(mcp, "Track Changed found: handle 0x%04x", value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->track_changed)
+ return;
+
+ mcs->track_changed = attr;
+ bt_mcp_track_changed_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_track_title)) {
+ DBG(mcp, "Track Title found: handle 0x%04x", value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->track_title)
+ return;
+
+ mcs->track_title = attr;
+ bt_mcp_track_title_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_track_duration)) {
+ DBG(mcp, "Track Duration found: handle 0x%04x", value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->track_duration)
+ return;
+
+ mcs->track_duration = attr;
+ bt_mcp_track_duration_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_track_position)) {
+ DBG(mcp, "Track Position found: handle 0x%04x", value_handle);
+
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->track_position)
+ return;
+
+ mcs->track_position = attr;
+ bt_mcp_track_position_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_media_state)) {
+ DBG(mcp, "Media State found: handle 0x%04x", value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->media_state)
+ return;
+
+ mcs->media_state = attr;
+ bt_mcp_media_state_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_media_cp)) {
+ DBG(mcp, "Media Control Point found: handle 0x%04x", value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->media_cp)
+ return;
+
+ mcs->media_cp = attr;
+ bt_mcp_media_cp_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_media_cp_op_supported)) {
+ DBG(mcp, "Media Control Point Opecodes Supported found: handle 0x%04x",
+ value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->media_cp_op_supportd)
+ return;
+
+ mcs->media_cp_op_supportd = attr;
+ bt_mcp_media_cp_op_supported_attach(mcp);
+ }
+
+ if (!bt_uuid_cmp(&uuid, &uuid_content_control_id)) {
+ DBG(mcp, "Content Control ID found: handle 0x%04x", value_handle);
+
+ mcs = mcp_get_mcs(mcp);
+ if (!mcs || mcs->content_control_id)
+ return;
+
+ mcs->content_control_id = attr;
+ bt_mcp_content_control_id_supported_attach(mcp);
+ }
+}
+
+void bt_mcp_set_event_callbacks(struct bt_mcp *mcp,
+ const struct bt_mcp_event_callback *cbs,
+ void *user_data)
+{
+ struct event_callback *cb;
+
+ if (mcp->cb)
+ free(mcp->cb);
+
+ cb = new0(struct event_callback, 1);
+ cb->cbs = cbs;
+ cb->user_data = user_data;
+
+ mcp->cb = cb;
+}
+
+static void foreach_mcs_service(struct gatt_db_attribute *attr,
+ void *user_data)
+{
+ struct bt_mcp *mcp = user_data;
+ struct bt_mcs *mcs = mcp_get_mcs(mcp);
+
+ DBG(mcp, "");
+
+ mcs->service = attr;
+
+ gatt_db_service_foreach_char(attr, foreach_mcs_char, mcp);
+}
+
+static struct bt_mcp_db *mcp_db_new(struct gatt_db *db)
+{
+ struct bt_mcp_db *mdb;
+
+ if (!db)
+ return NULL;
+
+ mdb = new0(struct bt_mcp_db, 1);
+ mdb->db = gatt_db_ref(db);
+
+ if (!mcp_db)
+ mcp_db = queue_new();
+
+ queue_push_tail(mcp_db, mdb);
+
+ mdb->mcs = mcs_new(db);
+ return mdb;
+}
+
+static struct bt_mcp_db *mcp_get_db(struct gatt_db *db)
+{
+ struct bt_mcp_db *mdb;
+
+ mdb = queue_find(mcp_db, mcp_db_match, db);
+ if (mdb)
+ return mdb;
+
+ return mcp_db_new(db);
+}
+
+struct bt_mcp *bt_mcp_new(struct gatt_db *ldb, struct gatt_db *rdb)
+{
+ struct bt_mcp *mcp;
+ struct bt_mcp_db *mdb;
+
+ if (!ldb)
+ return NULL;
+
+ mdb = mcp_get_db(ldb);
+ if (!mdb)
+ return NULL;
+
+ mcp = new0(struct bt_mcp, 1);
+ mcp->ldb = mdb;
+ mcp->pending = queue_new();
+
+ if (!rdb)
+ goto done;
+
+ mdb = new0(struct bt_mcp_db, 1);
+ mdb->db = gatt_db_ref(rdb);
+
+ mcp->rdb = mdb;
+
+done:
+ bt_mcp_ref(mcp);
+
+ return mcp;
+}
+
+void bt_mcp_register(struct gatt_db *db)
+{
+ mcp_db_new(db);
+}
+
+bool bt_mcp_attach(struct bt_mcp *mcp, struct bt_gatt_client *client)
+{
+ bt_uuid_t uuid;
+
+ DBG(mcp, "mcp %p", mcp);
+
+ mcp->client = bt_gatt_client_clone(client);
+ if (!mcp->client)
+ return false;
+
+ if (mcp->rdb->mcs) {
+ uint16_t value_handle;
+
+ bt_mcp_mp_name_attach(mcp);
+ bt_mcp_track_changed_attach(mcp);
+ bt_mcp_track_title_attach(mcp);
+ bt_mcp_track_duration_attach(mcp);
+ bt_mcp_track_position_attach(mcp);
+ bt_mcp_media_state_attach(mcp);
+ bt_mcp_media_cp_attach(mcp);
+ bt_mcp_media_cp_op_supported_attach(mcp);
+ bt_mcp_content_control_id_supported_attach(mcp);
+
+ return true;
+ }
+
+ bt_uuid16_create(&uuid, GMCS_UUID);
+ gatt_db_foreach_service(mcp->rdb->db, &uuid, foreach_mcs_service, mcp);
+
+ return true;
+}
+
+void bt_mcp_detach(struct bt_mcp *mcp)
+{
+ DBG(mcp, "%p", mcp);
+
+ bt_gatt_client_unref(mcp->client);
+ mcp->client = NULL;
+}
diff --git a/src/shared/mcp.h b/src/shared/mcp.h
new file mode 100644
index 000000000..0a85631cf
--- /dev/null
+++ b/src/shared/mcp.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ */
+
+#include <stdbool.h>
+#include <inttypes.h>
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+struct bt_mcp;
+struct bt_mcp_db;
+struct bt_mcp_session_info;
+
+typedef void (*bt_mcp_debug_func_t)(const char *str, void *user_data);
+typedef void (*bt_mcp_destroy_func_t)(void *user_data);
+
+struct bt_mcp_event_callback {
+ void (*player_name)(struct bt_mcp *mcp, const uint8_t *value,
+ uint16_t length);
+ void (*track_changed)(struct bt_mcp *mcp);
+ void (*track_title)(struct bt_mcp *mcp, const uint8_t *value,
+ uint16_t length);
+ void (*track_duration)(struct bt_mcp *mcp, int32_t duration);
+ void (*track_position)(struct bt_mcp *mcp, int32_t position);
+ void (*playback_speed)(struct bt_mcp *mcp, int8_t speed);
+ void (*seeking_speed)(struct bt_mcp *mcp, int8_t speed);
+ void (*play_order)(struct bt_mcp *mcp, uint8_t order);
+ void (*play_order_supported)(struct bt_mcp *mcp, uint16_t order_supported);
+ void (*media_state)(struct bt_mcp *mcp, uint8_t state);
+ void (*content_control_id)(struct bt_mcp *mcp, uint8_t cc_id);
+};
+
+void bt_mcp_set_event_callbacks(struct bt_mcp *mcp,
+ const struct bt_mcp_event_callback *cbs,
+ void *user_data);
+
+bool bt_mcp_set_debug(struct bt_mcp *mcp, bt_mcp_debug_func_t cb,
+ void *user_data, bt_mcp_destroy_func_t destroy);
+
+void bt_mcp_register(struct gatt_db *db);
+bool bt_mcp_attach(struct bt_mcp *mcp, struct bt_gatt_client *client);
+void bt_mcp_detach(struct bt_mcp *mcp);
+
+struct bt_mcp *bt_mcp_new(struct gatt_db *ldb, struct gatt_db *rdb);
+struct bt_mcp *bt_mcp_ref(struct bt_mcp *mcp);
+void bt_mcp_unref(struct bt_mcp *mcp);
+
+bool bt_mcp_set_user_data(struct bt_mcp *mcp, void *user_data);
+void *bt_mcp_get_user_data(struct bt_mcp *mcp);
+
+unsigned int bt_mcp_play(struct bt_mcp *mcp);
+unsigned int bt_mcp_pause(struct bt_mcp *mcp);
+unsigned int bt_mcp_stop(struct bt_mcp *mcp);
diff --git a/src/shared/mcs.h b/src/shared/mcs.h
new file mode 100644
index 000000000..51c24d89c
--- /dev/null
+++ b/src/shared/mcs.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ */
+
+/* MCP Media State */
+#define BT_MCS_STATUS_INACTIVE 0x00
+#define BT_MCS_STATUS_PLAYING 0x01
+#define BT_MCS_STATUS_PAUSED 0x02
+#define BT_MCS_STATUS_SEEKING 0x03
+
+/* MCP Control Point Opcodes */
+#define BT_MCS_CMD_PLAY 0x01
+#define BT_MCS_CMD_PAUSE 0x02
+#define BT_MCS_CMD_FAST_REWIND 0x03
+#define BT_MCS_CMD_FAST_FORWARD 0x04
+#define BT_MCS_CMD_STOP 0x05
+
+#define BT_MCS_CMD_MOVE_RELATIVE 0x10
+
+#define BT_MCS_CMD_PREV_SEGMENT 0x20
+#define BT_MCS_CMD_NEXT_SEGMENT 0x21
+#define BT_MCS_CMD_FIRST_SEGMENT 0x22
+#define BT_MCS_CMD_LAST_SEGMENT 0x23
+#define BT_MCS_CMD_GOTO_SEGMENT 0x24
+
+#define BT_MCS_CMD_PREV_TRACK 0x30
+#define BT_MCS_CMD_NEXT_TRACK 0x31
+#define BT_MCS_CMD_FIRST_TRACK 0x32
+#define BT_MCS_CMD_LAST_TRACK 0x33
+#define BT_MCS_CMD_GOTO_TRACK 0x34
+
+#define BT_MCS_CMD_PREV_GROUP 0x40
+#define BT_MCS_CMD_NEXT_GROUP 0x41
+#define BT_MCS_CMD_FIRST_GROUP 0x42
+#define BT_MCS_CMD_LAST_GROUP 0x43
+#define BT_MCS_CMD_GOTO_GROUP 0x44
+
+
+/* MCP Control Point Opcodes Supported */
+#define BT_MCS_CMD_PLAY_SUPPORTED 0x00000001
+#define BT_MCS_CMD_PAUSE_SUPPORTED 0x00000002
+#define BT_MCS_CMD_FAST_REWIND_SUPPORTED 0x00000004
+#define BT_MCS_CMD_FAST_FORWARD_SUPPORTED 0x00000008
+#define BT_MCS_CMD_STOP_SUPPORTED 0x00000010
+#define BT_MCS_CMD_MOVE_RELATIVE_SUPPORTED 0x00000020
+#define BT_MCS_CMD_PREV_SEGMENT_SUPPORTED 0x00000040
+#define BT_MCS_CMD_NEXT_SEGMENT_SUPPORTED 0x00000080
+#define BT_MCS_CMD_FIRST_SEGMENT_SUPPORTED 0x00000100
+#define BT_MCS_CMD_LAST_SEGMENT_SUPPORTED 0x00000200
+#define BT_MCS_CMD_GOTO_SEGMENT_SUPPORTED 0x00000400
+#define BT_MCS_CMD_PREV_TRACK_SUPPORTED 0x00000800
+#define BT_MCS_CMD_NEXT_TRACK_SUPPORTED 0x00001000
+#define BT_MCS_CMD_FIRST_TRACK_SUPPORTED 0x00002000
+#define BT_MCS_CMD_LAST_TRACK_SUPPORTED 0x00004000
+#define BT_MCS_CMD_GOTO_TRACK_SUPPORTED 0x00008000
+#define BT_MCS_CMD_PREV_GROUP_SUPPORTED 0x00010000
+#define BT_MCS_CMD_NEXT_GROUP_SUPPORTED 0x00020000
+#define BT_MCS_CMD_FIRST_GROUP_SUPPORTED 0x00040000
+#define BT_MCS_CMD_LAST_GROUP_SUPPORTED 0x00080000
+#define BT_MCS_CMD_GOTO_GROUP_SUPPORTED 0x00100000
--
2.25.1

2022-10-06 15:07:37

by bluez.test.bot

[permalink] [raw]
Subject: RE: Media Control Profile Client

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=683505

---Test result---

Test Summary:
CheckPatch FAIL 5.09 seconds
GitLint PASS 1.96 seconds
Prep - Setup ELL PASS 31.81 seconds
Build - Prep PASS 0.67 seconds
Build - Configure PASS 10.15 seconds
Build - Make FAIL 12.78 seconds
Make Check FAIL 33.53 seconds
Make Check w/Valgrind FAIL 19.54 seconds
Make Distcheck FAIL 13.15 seconds
Build w/ext ELL - Configure PASS 10.24 seconds
Build w/ext ELL - Make FAIL 4.95 seconds
Incremental Build w/ patches FAIL 136.59 seconds
Scan Build FAIL 636.05 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script with rule in .checkpatch.conf
Output:
[BlueZ,2/4] shared/mcp: Add initial code for handling MCP
ERROR:FSF_MAILING_ADDRESS: Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.
#113: FILE: src/shared/mcp.c:19:
+ * License along with this library; if not, write to the Free Software$

ERROR:FSF_MAILING_ADDRESS: Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.
#114: FILE: src/shared/mcp.c:20:
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#179: FILE: src/shared/mcp.c:85:
+ struct bt_mcp_session_info session;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#184: FILE: src/shared/mcp.c:90:
+ bt_mcp_debug_func_t debug_func;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#185: FILE: src/shared/mcp.c:91:
+ bt_mcp_destroy_func_t debug_destroy;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#186: FILE: src/shared/mcp.c:92:
+ void *debug_data;$

ERROR:CODE_INDENT: code indent should use tabs where possible
#545: FILE: src/shared/mcp.c:451:
+ &uuid,$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#545: FILE: src/shared/mcp.c:451:
+ &uuid,$

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#555: FILE: src/shared/mcp.c:461:
+ mcs->track_title = gatt_db_service_add_characteristic(mcs->service, &uuid,

WARNING:LONG_LINE: line length of 90 exceeds 80 columns
#573: FILE: src/shared/mcp.c:479:
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_WRITE |

WARNING:LONG_LINE: line length of 90 exceeds 80 columns
#575: FILE: src/shared/mcp.c:481:
+ mcs_track_position_read, mcs_track_position_write,

WARNING:LONG_LINE: line length of 90 exceeds 80 columns
#582: FILE: src/shared/mcp.c:488:
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_WRITE |

WARNING:LONG_LINE: line length of 90 exceeds 80 columns
#584: FILE: src/shared/mcp.c:490:
+ mcs_playback_speed_read, mcs_playback_speed_write,

ERROR:CODE_INDENT: code indent should use tabs where possible
#589: FILE: src/shared/mcp.c:495:
+ &uuid,$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#589: FILE: src/shared/mcp.c:495:
+ &uuid,$

ERROR:CODE_INDENT: code indent should use tabs where possible
#590: FILE: src/shared/mcp.c:496:
+ BT_ATT_PERM_READ,$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#590: FILE: src/shared/mcp.c:496:
+ BT_ATT_PERM_READ,$

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#596: FILE: src/shared/mcp.c:502:
+ mcs->play_order = gatt_db_service_add_characteristic(mcs->service, &uuid,

WARNING:LONG_LINE: line length of 90 exceeds 80 columns
#598: FILE: src/shared/mcp.c:504:
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_WRITE |

WARNING:LONG_LINE: line length of 88 exceeds 80 columns
#600: FILE: src/shared/mcp.c:506:
+ mcs_playing_order_read, mcs_playing_order_write,

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#604: FILE: src/shared/mcp.c:510:
+ mcs->play_order_supported = gatt_db_service_add_characteristic(mcs->service,

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#612: FILE: src/shared/mcp.c:518:
+ mcs->media_state = gatt_db_service_add_characteristic(mcs->service, &uuid,

WARNING:LONG_LINE: line length of 90 exceeds 80 columns
#614: FILE: src/shared/mcp.c:520:
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_NOTIFY,

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#624: FILE: src/shared/mcp.c:530:
+ BT_GATT_CHRC_PROP_WRITE | BT_GATT_CHRC_PROP_NOTIFY |

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#633: FILE: src/shared/mcp.c:539:
+ mcs->media_cp_op_supportd = gatt_db_service_add_characteristic(mcs->service,

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#641: FILE: src/shared/mcp.c:547:
+ mcs->content_control_id = gatt_db_service_add_characteristic(mcs->service,

WARNING:LONG_LINE: line length of 90 exceeds 80 columns
#644: FILE: src/shared/mcp.c:550:
+ BT_GATT_CHRC_PROP_READ | BT_GATT_CHRC_PROP_NOTIFY,

WARNING:LONG_LINE: line length of 86 exceeds 80 columns
#778: FILE: src/shared/mcp.c:684:
+ DBG(mcp, "Unable to read media player name: error 0x%02x", att_ecode);

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#814: FILE: src/shared/mcp.c:720:
+ DBG(mcp, "Unable to read track duration: error 0x%02x", att_ecode);

WARNING:BRACES: braces {} are not necessary for single statement blocks
#818: FILE: src/shared/mcp.c:724:
+ if (length != sizeof(duration)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#834: FILE: src/shared/mcp.c:740:
+ DBG(mcp, "Unable to read track position: error 0x%02x", att_ecode);

WARNING:BRACES: braces {} are not necessary for single statement blocks
#838: FILE: src/shared/mcp.c:744:
+ if (length != sizeof(position)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }

WARNING:BRACES: braces {} are not necessary for single statement blocks
#857: FILE: src/shared/mcp.c:763:
+ if (length != sizeof(uint8_t)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }

WARNING:LONG_LINE_STRING: line length of 83 exceeds 80 columns
#871: FILE: src/shared/mcp.c:777:
+ DBG(mcp, "Unable to read media CP opcodes supported: error 0x%02x",

WARNING:BRACES: braces {} are not necessary for single statement blocks
#876: FILE: src/shared/mcp.c:782:
+ if (length != sizeof(uint32_t)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }

WARNING:LONG_LINE: line length of 87 exceeds 80 columns
#892: FILE: src/shared/mcp.c:798:
+ DBG(mcp, "Unable to read content control id: error 0x%02x", att_ecode);

WARNING:BRACES: braces {} are not necessary for single statement blocks
#896: FILE: src/shared/mcp.c:802:
+ if (length != sizeof(uint8_t)) {
+ DBG(mcp, "Wrong length received Length : %u", length);
+ }

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#947: FILE: src/shared/mcp.c:853:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#950: FILE: src/shared/mcp.c:856:
+ DBG(mcp, "Media Player Name notification failed: 0x%04x", att_ecode);

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#966: FILE: src/shared/mcp.c:872:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 87 exceeds 80 columns
#969: FILE: src/shared/mcp.c:875:
+ DBG(mcp, "Media Track Changed notification failed: 0x%04x", att_ecode);

ERROR:CODE_INDENT: code indent should use tabs where possible
#973: FILE: src/shared/mcp.c:879:
+ const uint8_t *value, uint16_t length, void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#973: FILE: src/shared/mcp.c:879:
+ const uint8_t *value, uint16_t length, void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#986: FILE: src/shared/mcp.c:892:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#989: FILE: src/shared/mcp.c:895:
+ DBG(mcp, "Media Track Title notification failed: 0x%04x", att_ecode);

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1002: FILE: src/shared/mcp.c:908:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 88 exceeds 80 columns
#1005: FILE: src/shared/mcp.c:911:
+ DBG(mcp, "Media Track Duration notification failed: 0x%04x", att_ecode);

ERROR:CODE_INDENT: code indent should use tabs where possible
#1009: FILE: src/shared/mcp.c:915:
+ const uint8_t *value, uint16_t length, void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1009: FILE: src/shared/mcp.c:915:
+ const uint8_t *value, uint16_t length, void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1020: FILE: src/shared/mcp.c:926:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 88 exceeds 80 columns
#1023: FILE: src/shared/mcp.c:929:
+ DBG(mcp, "Media Track Position notification failed: 0x%04x", att_ecode);

ERROR:CODE_INDENT: code indent should use tabs where possible
#1027: FILE: src/shared/mcp.c:933:
+ const uint8_t *value, uint16_t length, void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1027: FILE: src/shared/mcp.c:933:
+ const uint8_t *value, uint16_t length, void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1038: FILE: src/shared/mcp.c:944:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#1041: FILE: src/shared/mcp.c:947:
+ DBG(mcp, "Media Media State notification failed: 0x%04x", att_ecode);

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1054: FILE: src/shared/mcp.c:960:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1057: FILE: src/shared/mcp.c:963:
+ DBG(mcp, "Media Media CP notification failed: 0x%04x", att_ecode);

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1063: FILE: src/shared/mcp.c:969:
+ struct bt_mcp *mcp = user_data;$

ERROR:CODE_INDENT: code indent should use tabs where possible
#1069: FILE: src/shared/mcp.c:975:
+ void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1069: FILE: src/shared/mcp.c:975:
+ void *user_data)$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1071: FILE: src/shared/mcp.c:977:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE_STRING: line length of 83 exceeds 80 columns
#1074: FILE: src/shared/mcp.c:980:
+ DBG(mcp, "Media Media CP OP Supported notification failed: 0x%04x",

WARNING:LONG_LINE: line length of 95 exceeds 80 columns
#1079: FILE: src/shared/mcp.c:985:
+ const uint8_t *value, uint16_t length, void *user_data)

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1081: FILE: src/shared/mcp.c:987:
+ struct bt_mcp *mcp = user_data;$

WARNING:LONG_LINE: line length of 95 exceeds 80 columns
#1102: FILE: src/shared/mcp.c:1008:
+ value_handle, mcp_mp_name_register, mcp_mp_name_notify,

WARNING:LONG_LINE: line length of 89 exceeds 80 columns
#1118: FILE: src/shared/mcp.c:1024:
+ value_handle, mcp_track_changed_register,

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#1119: FILE: src/shared/mcp.c:1025:
+ mcp_track_changed_notify, mcp, NULL);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1154: FILE: src/shared/mcp.c:1060:
+ value_handle, mcp_track_duration_register,

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1172: FILE: src/shared/mcp.c:1078:
+ value_handle, mcp_track_position_register,

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#1206: FILE: src/shared/mcp.c:1112:
+ value_handle, mcp_media_cp_register,

ERROR:CODE_INDENT: code indent should use tabs where possible
#1220: FILE: src/shared/mcp.c:1126:
+ value_handle);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#1220: FILE: src/shared/mcp.c:1126:
+ value_handle);$

WARNING:LONG_LINE: line length of 94 exceeds 80 columns
#1225: FILE: src/shared/mcp.c:1131:
+ mcp->client, value_handle, mcp_media_cp_op_supported_register,

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#1238: FILE: src/shared/mcp.c:1144:
+ DBG(mcp, "Media Content Control id Supported handle 0x%04x", value_handle);

WARNING:LONG_LINE: line length of 91 exceeds 80 columns
#1247: FILE: src/shared/mcp.c:1153:
+ uuid_track_duration, uuid_track_position, uuid_media_state,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1264: FILE: src/shared/mcp.c:1170:
+ MEDIA_CP_OP_SUPPORTED_CHRC_UUID);

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#1266: FILE: src/shared/mcp.c:1172:
+ MEDIA_CONTENT_CONTROL_ID_CHRC_UUID);

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1269: FILE: src/shared/mcp.c:1175:
+ DBG(mcp, "Media Player Name found: handle 0x%04x", value_handle);

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#1336: FILE: src/shared/mcp.c:1242:
+ DBG(mcp, "Media Control Point found: handle 0x%04x", value_handle);

WARNING:LONG_LINE_STRING: line length of 87 exceeds 80 columns
#1347: FILE: src/shared/mcp.c:1253:
+ DBG(mcp, "Media Control Point Opecodes Supported found: handle 0x%04x",

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1359: FILE: src/shared/mcp.c:1265:
+ DBG(mcp, "Content Control ID found: handle 0x%04x", value_handle);

WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __packed over __attribute__((packed))
#1522: FILE: src/shared/mcp.h:14:
+#define __packed __attribute__((packed))

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#1543: FILE: src/shared/mcp.h:35:
+ void (*play_order_supported)(struct bt_mcp *mcp, uint16_t order_supported);

/github/workspace/src/13000447.patch total: 10 errors, 73 warnings, 1540 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

NOTE: Whitespace errors detected.
You may wish to use scripts/cleanpatch or scripts/cleanfile

/github/workspace/src/13000447.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.

[BlueZ,3/4] profiles: Add initial code for mcp plugin
WARNING:LEADING_SPACE: please, no spaces at the start of a line
#381: FILE: profiles/audio/mcp.c:270:
+ bt_mcp_set_debug(data->mcp, mcp_debug, NULL, NULL);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#396: FILE: profiles/audio/mcp.c:285:
+ if (data->mp) {$

ERROR:CODE_INDENT: code indent should use tabs where possible
#397: FILE: profiles/audio/mcp.c:286:
+ media_player_destroy(data->mp);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#397: FILE: profiles/audio/mcp.c:286:
+ media_player_destroy(data->mp);$

ERROR:CODE_INDENT: code indent should use tabs where possible
#398: FILE: profiles/audio/mcp.c:287:
+ data->mp = NULL;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#398: FILE: profiles/audio/mcp.c:287:
+ data->mp = NULL;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#399: FILE: profiles/audio/mcp.c:288:
+ }$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#477: FILE: profiles/audio/mcp.c:366:
+ if (data->mp) {$

ERROR:CODE_INDENT: code indent should use tabs where possible
#478: FILE: profiles/audio/mcp.c:367:
+ media_player_destroy(data->mp);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#478: FILE: profiles/audio/mcp.c:367:
+ media_player_destroy(data->mp);$

ERROR:CODE_INDENT: code indent should use tabs where possible
#479: FILE: profiles/audio/mcp.c:368:
+ data->mp = NULL;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#479: FILE: profiles/audio/mcp.c:368:
+ data->mp = NULL;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#480: FILE: profiles/audio/mcp.c:369:
+ }$

WARNING:LINE_SPACING: Missing a blank line after declarations
#493: FILE: profiles/audio/mcp.c:382:
+ struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+ bt_mcp_register(btd_gatt_database_get_db(database));

WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (8, 8)
#521: FILE: profiles/audio/mcp.c:410:
+ if (!(g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL)) {
+ warn("D-Bus experimental not enabled");

ERROR:CODE_INDENT: code indent should use tabs where possible
#522: FILE: profiles/audio/mcp.c:411:
+ warn("D-Bus experimental not enabled");$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#522: FILE: profiles/audio/mcp.c:411:
+ warn("D-Bus experimental not enabled");$

ERROR:CODE_INDENT: code indent should use tabs where possible
#523: FILE: profiles/audio/mcp.c:412:
+ return -ENOTSUP;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#523: FILE: profiles/audio/mcp.c:412:
+ return -ENOTSUP;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#526: FILE: profiles/audio/mcp.c:415:
+ btd_profile_register(&mcp_profile);$

WARNING:BRACES: braces {} are not necessary for single statement blocks
#534: FILE: profiles/audio/mcp.c:423:
+ if (g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL) {
+ btd_profile_unregister(&mcp_profile);
+ }

/github/workspace/src/13000445.patch total: 6 errors, 15 warnings, 450 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

NOTE: Whitespace errors detected.
You may wish to use scripts/cleanpatch or scripts/cleanfile

/github/workspace/src/13000445.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.

[BlueZ,4/4] monitor/att: Add decoding support for GMCS
WARNING:LEADING_SPACE: please, no spaces at the start of a line
#113: FILE: monitor/att.c:1754:
+ char utf8_name[HCI_MAX_NAME_LENGTH + 2];$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#114: FILE: monitor/att.c:1755:
+ int i;$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#116: FILE: monitor/att.c:1757:
+ if (g_utf8_validate((const char *) name, len, NULL))$

ERROR:CODE_INDENT: code indent should use tabs where possible
#117: FILE: monitor/att.c:1758:
+ return g_strndup((char *) name, len);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#117: FILE: monitor/att.c:1758:
+ return g_strndup((char *) name, len);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#119: FILE: monitor/att.c:1760:
+ len = MIN(len, sizeof(utf8_name) - 1);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#121: FILE: monitor/att.c:1762:
+ memset(utf8_name, 0, sizeof(utf8_name));$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#122: FILE: monitor/att.c:1763:
+ strncpy(utf8_name, (char *) name, len);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#125: FILE: monitor/att.c:1766:
+ for (i = 0; utf8_name[i] != '\0'; i++) {$

ERROR:CODE_INDENT: code indent should use tabs where possible
#126: FILE: monitor/att.c:1767:
+ if (!isascii(utf8_name[i]))$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#126: FILE: monitor/att.c:1767:
+ if (!isascii(utf8_name[i]))$

WARNING:SUSPECT_CODE_INDENT: suspect code indent for conditional statements (8, 12)
#126: FILE: monitor/att.c:1767:
+ if (!isascii(utf8_name[i]))
+ utf8_name[i] = ' ';

ERROR:CODE_INDENT: code indent should use tabs where possible
#127: FILE: monitor/att.c:1768:
+ utf8_name[i] = ' ';$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#127: FILE: monitor/att.c:1768:
+ utf8_name[i] = ' ';$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#128: FILE: monitor/att.c:1769:
+ }$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#131: FILE: monitor/att.c:1772:
+ g_strstrip(utf8_name);$

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#133: FILE: monitor/att.c:1774:
+ return g_strdup(utf8_name);$

WARNING:LONG_LINE_STRING: line length of 86 exceeds 80 columns
#383: FILE: monitor/att.c:2024:
+ print_text(COLOR_ERROR, " Supported Playing Orders: invalid size");

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#387: FILE: monitor/att.c:2028:
+ print_field(" Supported Playing Orders: 0x%4.4x", supported_orders);

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#451: FILE: monitor/att.c:2092:
+ {0x02 , "Pause"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#452: FILE: monitor/att.c:2093:
+ {0x03 , "Fast Rewind"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#453: FILE: monitor/att.c:2094:
+ {0x04 , "Fast Forward"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#454: FILE: monitor/att.c:2095:
+ {0x05 , "Stop"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#455: FILE: monitor/att.c:2096:
+ {0x10 , "Move Relative"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#456: FILE: monitor/att.c:2097:
+ {0x20 , "Previous Segment"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#457: FILE: monitor/att.c:2098:
+ {0x21 , "Next Segment"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#458: FILE: monitor/att.c:2099:
+ {0x22 , "First Segment"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#459: FILE: monitor/att.c:2100:
+ {0x23 , "Last Segment"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#460: FILE: monitor/att.c:2101:
+ {0x24 , "Goto Segment"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#461: FILE: monitor/att.c:2102:
+ {0x30 , "Previous Track"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#462: FILE: monitor/att.c:2103:
+ {0x31 , "Next Track"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#463: FILE: monitor/att.c:2104:
+ {0x32 , "First Track"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#464: FILE: monitor/att.c:2105:
+ {0x33 , "Last Track"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#465: FILE: monitor/att.c:2106:
+ {0x34 , "Goto Track"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#466: FILE: monitor/att.c:2107:
+ {0x40 , "Previous Group"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#467: FILE: monitor/att.c:2108:
+ {0x41 , "Next Group"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#468: FILE: monitor/att.c:2109:
+ {0x42 , "First Group"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#469: FILE: monitor/att.c:2110:
+ {0x43 , "Last Group"},
^

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#470: FILE: monitor/att.c:2111:
+ {0x44 , "Goto Group"},
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#514: FILE: monitor/att.c:2155:
+ {0^I, "Play (0x00000001)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#514: FILE: monitor/att.c:2155:
+ {0 , "Play (0x00000001)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#515: FILE: monitor/att.c:2156:
+ {1^I, "Pause (0x00000002)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#515: FILE: monitor/att.c:2156:
+ {1 , "Pause (0x00000002)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#516: FILE: monitor/att.c:2157:
+ {2^I, "Fast Rewind^I(0x00000004)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#516: FILE: monitor/att.c:2157:
+ {2 , "Fast Rewind (0x00000004)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#517: FILE: monitor/att.c:2158:
+ {3^I, "Fast Forward (0x00000008)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#517: FILE: monitor/att.c:2158:
+ {3 , "Fast Forward (0x00000008)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#518: FILE: monitor/att.c:2159:
+ {4^I, "Stop (0x00000010)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#518: FILE: monitor/att.c:2159:
+ {4 , "Stop (0x00000010)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#519: FILE: monitor/att.c:2160:
+ {5^I, "Move Relative (0x00000020)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#519: FILE: monitor/att.c:2160:
+ {5 , "Move Relative (0x00000020)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#520: FILE: monitor/att.c:2161:
+ {6^I, "Previous Segment (0x00000040)"^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#520: FILE: monitor/att.c:2161:
+ {6 , "Previous Segment (0x00000040)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#521: FILE: monitor/att.c:2162:
+ {7^I, "Next Segment (0x00000080)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#521: FILE: monitor/att.c:2162:
+ {7 , "Next Segment (0x00000080)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#522: FILE: monitor/att.c:2163:
+ {8^I, "First Segment (0x00000100)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#522: FILE: monitor/att.c:2163:
+ {8 , "First Segment (0x00000100)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#523: FILE: monitor/att.c:2164:
+ {9^I, "Last Segment (0x00000200)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#523: FILE: monitor/att.c:2164:
+ {9 , "Last Segment (0x00000200)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#524: FILE: monitor/att.c:2165:
+ {10^I, "Goto Segment (0x00000400)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#524: FILE: monitor/att.c:2165:
+ {10 , "Goto Segment (0x00000400)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#525: FILE: monitor/att.c:2166:
+ {11^I, "Previous Track (0x00000800)" },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#525: FILE: monitor/att.c:2166:
+ {11 , "Previous Track (0x00000800)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#526: FILE: monitor/att.c:2167:
+ {12^I, "Next Track (0x00001000)"^I^I },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#526: FILE: monitor/att.c:2167:
+ {12 , "Next Track (0x00001000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#527: FILE: monitor/att.c:2168:
+ {13^I, "First Track (0x00002000)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#527: FILE: monitor/att.c:2168:
+ {13 , "First Track (0x00002000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#528: FILE: monitor/att.c:2169:
+ {14^I, "Last Track (0x00004000)"^I^I },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#528: FILE: monitor/att.c:2169:
+ {14 , "Last Track (0x00004000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#529: FILE: monitor/att.c:2170:
+ {15^I, "Goto Track (0x00008000)"^I^I },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#529: FILE: monitor/att.c:2170:
+ {15 , "Goto Track (0x00008000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#530: FILE: monitor/att.c:2171:
+ {16^I, "Previous Group (0x00010000)"^I },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#530: FILE: monitor/att.c:2171:
+ {16 , "Previous Group (0x00010000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#531: FILE: monitor/att.c:2172:
+ {17^I, "Next Group (0x00020000)"^I^I },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#531: FILE: monitor/att.c:2172:
+ {17 , "Next Group (0x00020000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#532: FILE: monitor/att.c:2173:
+ {18^I, "First Group (0x00040000)"^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#532: FILE: monitor/att.c:2173:
+ {18 , "First Group (0x00040000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#533: FILE: monitor/att.c:2174:
+ {19^I, "Last Group (0x00080000)"^I^I },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#533: FILE: monitor/att.c:2174:
+ {19 , "Last Group (0x00080000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#534: FILE: monitor/att.c:2175:
+ {20 , "Goto Group (0x00100000)"^I^I },$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#534: FILE: monitor/att.c:2175:
+ {20 , "Goto Group (0x00100000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#535: FILE: monitor/att.c:2176:
+ {21^I, "RFU (0x00200000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#535: FILE: monitor/att.c:2176:
+ {21 , "RFU (0x00200000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#536: FILE: monitor/att.c:2177:
+ {22^I, "RFU (0x00400000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#536: FILE: monitor/att.c:2177:
+ {22 , "RFU (0x00400000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#537: FILE: monitor/att.c:2178:
+ {23^I, "RFU (0x00800000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#537: FILE: monitor/att.c:2178:
+ {23 , "RFU (0x00800000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#538: FILE: monitor/att.c:2179:
+ {24^I, "RFU (0x01000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#538: FILE: monitor/att.c:2179:
+ {24 , "RFU (0x01000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#539: FILE: monitor/att.c:2180:
+ {25^I, "RFU (0x02000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#539: FILE: monitor/att.c:2180:
+ {25 , "RFU (0x02000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#540: FILE: monitor/att.c:2181:
+ {26^I, "RFU (0x04000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#540: FILE: monitor/att.c:2181:
+ {26 , "RFU (0x04000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#541: FILE: monitor/att.c:2182:
+ {27^I, "RFU (0x08000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#541: FILE: monitor/att.c:2182:
+ {27 , "RFU (0x08000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#542: FILE: monitor/att.c:2183:
+ {28^I, "RFU (0x10000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#542: FILE: monitor/att.c:2183:
+ {28 , "RFU (0x10000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#543: FILE: monitor/att.c:2184:
+ {29^I, "RFU (0x20000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#543: FILE: monitor/att.c:2184:
+ {29 , "RFU (0x20000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#544: FILE: monitor/att.c:2185:
+ {30^I, "RFU (0x40000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#544: FILE: monitor/att.c:2185:
+ {30 , "RFU (0x40000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#545: FILE: monitor/att.c:2186:
+ {31^I, "RFU (0x80000000)"^I^I^I^I},$

ERROR:SPACING: space prohibited before that ',' (ctx:WxW)
#545: FILE: monitor/att.c:2186:
+ {31 , "RFU (0x80000000)" },
^

WARNING:LEADING_SPACE: please, no spaces at the start of a line
#546: FILE: monitor/att.c:2187:
+ { }$

/github/workspace/src/13000446.patch total: 55 errors, 49 warnings, 535 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

NOTE: Whitespace errors detected.
You may wish to use scripts/cleanpatch or scripts/cleanfile

/github/workspace/src/13000446.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: Build - Make - FAIL
Desc: Build the BlueZ source tree
Output:
src/shared/mcp.c: In function ‘read_track_title’:
src/shared/mcp.c:699:25: error: unused variable ‘cb’ [-Werror=unused-variable]
699 | struct event_callback *cb = mcp->cb;
| ^~
src/shared/mcp.c: At top level:
src/shared/mcp.c:994:6: error: no previous declaration for ‘bt_mcp_mp_name_attach’ [-Werror=missing-declarations]
994 | void bt_mcp_mp_name_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1012:6: error: no previous declaration for ‘bt_mcp_track_changed_attach’ [-Werror=missing-declarations]
1012 | void bt_mcp_track_changed_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1028:6: error: no previous declaration for ‘bt_mcp_track_title_attach’ [-Werror=missing-declarations]
1028 | void bt_mcp_track_title_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1046:6: error: no previous declaration for ‘bt_mcp_track_duration_attach’ [-Werror=missing-declarations]
1046 | void bt_mcp_track_duration_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1064:6: error: no previous declaration for ‘bt_mcp_track_position_attach’ [-Werror=missing-declarations]
1064 | void bt_mcp_track_position_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1082:6: error: no previous declaration for ‘bt_mcp_media_state_attach’ [-Werror=missing-declarations]
1082 | void bt_mcp_media_state_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1100:6: error: no previous declaration for ‘bt_mcp_media_cp_attach’ [-Werror=missing-declarations]
1100 | void bt_mcp_media_cp_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1116:6: error: no previous declaration for ‘bt_mcp_media_cp_op_supported_attach’ [-Werror=missing-declarations]
1116 | void bt_mcp_media_cp_op_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1135:6: error: no previous declaration for ‘bt_mcp_content_control_id_supported_attach’ [-Werror=missing-declarations]
1135 | void bt_mcp_content_control_id_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c: In function ‘bt_mcp_attach’:
src/shared/mcp.c:1381:12: error: unused variable ‘value_handle’ [-Werror=unused-variable]
1381 | uint16_t value_handle;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:8235: src/shared/libshared_mainloop_la-mcp.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4465: all] Error 2


##############################
Test: Make Check - FAIL
Desc: Run 'make check'
Output:
src/shared/mcp.c: In function ‘read_track_title’:
src/shared/mcp.c:699:25: error: unused variable ‘cb’ [-Werror=unused-variable]
699 | struct event_callback *cb = mcp->cb;
| ^~
src/shared/mcp.c: At top level:
src/shared/mcp.c:994:6: error: no previous declaration for ‘bt_mcp_mp_name_attach’ [-Werror=missing-declarations]
994 | void bt_mcp_mp_name_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1012:6: error: no previous declaration for ‘bt_mcp_track_changed_attach’ [-Werror=missing-declarations]
1012 | void bt_mcp_track_changed_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1028:6: error: no previous declaration for ‘bt_mcp_track_title_attach’ [-Werror=missing-declarations]
1028 | void bt_mcp_track_title_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1046:6: error: no previous declaration for ‘bt_mcp_track_duration_attach’ [-Werror=missing-declarations]
1046 | void bt_mcp_track_duration_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1064:6: error: no previous declaration for ‘bt_mcp_track_position_attach’ [-Werror=missing-declarations]
1064 | void bt_mcp_track_position_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1082:6: error: no previous declaration for ‘bt_mcp_media_state_attach’ [-Werror=missing-declarations]
1082 | void bt_mcp_media_state_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1100:6: error: no previous declaration for ‘bt_mcp_media_cp_attach’ [-Werror=missing-declarations]
1100 | void bt_mcp_media_cp_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1116:6: error: no previous declaration for ‘bt_mcp_media_cp_op_supported_attach’ [-Werror=missing-declarations]
1116 | void bt_mcp_media_cp_op_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1135:6: error: no previous declaration for ‘bt_mcp_content_control_id_supported_attach’ [-Werror=missing-declarations]
1135 | void bt_mcp_content_control_id_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c: In function ‘bt_mcp_attach’:
src/shared/mcp.c:1381:12: error: unused variable ‘value_handle’ [-Werror=unused-variable]
1381 | uint16_t value_handle;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:8032: src/shared/libshared_glib_la-mcp.lo] Error 1
make: *** [Makefile:11650: check] Error 2


##############################
Test: Make Check w/Valgrind - FAIL
Desc: Run 'make check' with Valgrind
Output:
src/shared/mcp.c: In function ‘read_track_title’:
src/shared/mcp.c:699:25: error: unused variable ‘cb’ [-Werror=unused-variable]
699 | struct event_callback *cb = mcp->cb;
| ^~
src/shared/mcp.c: At top level:
src/shared/mcp.c:994:6: error: no previous declaration for ‘bt_mcp_mp_name_attach’ [-Werror=missing-declarations]
994 | void bt_mcp_mp_name_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1012:6: error: no previous declaration for ‘bt_mcp_track_changed_attach’ [-Werror=missing-declarations]
1012 | void bt_mcp_track_changed_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1028:6: error: no previous declaration for ‘bt_mcp_track_title_attach’ [-Werror=missing-declarations]
1028 | void bt_mcp_track_title_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1046:6: error: no previous declaration for ‘bt_mcp_track_duration_attach’ [-Werror=missing-declarations]
1046 | void bt_mcp_track_duration_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1064:6: error: no previous declaration for ‘bt_mcp_track_position_attach’ [-Werror=missing-declarations]
1064 | void bt_mcp_track_position_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1082:6: error: no previous declaration for ‘bt_mcp_media_state_attach’ [-Werror=missing-declarations]
1082 | void bt_mcp_media_state_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1100:6: error: no previous declaration for ‘bt_mcp_media_cp_attach’ [-Werror=missing-declarations]
1100 | void bt_mcp_media_cp_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1116:6: error: no previous declaration for ‘bt_mcp_media_cp_op_supported_attach’ [-Werror=missing-declarations]
1116 | void bt_mcp_media_cp_op_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1135:6: error: no previous declaration for ‘bt_mcp_content_control_id_supported_attach’ [-Werror=missing-declarations]
1135 | void bt_mcp_content_control_id_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c: In function ‘bt_mcp_attach’:
src/shared/mcp.c:1381:12: error: unused variable ‘value_handle’ [-Werror=unused-variable]
1381 | uint16_t value_handle;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:8235: src/shared/libshared_mainloop_la-mcp.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4465: all] Error 2


##############################
Test: Make Distcheck - FAIL
Desc: Run distcheck to check the distribution
Output:
make[2]: *** No rule to make target 'shared/mcs.h', needed by 'distdir-am'. Stop.
make[1]: *** [Makefile:11483: distdir] Error 2
make: *** [Makefile:11559: dist] Error 2


##############################
Test: Build w/ext ELL - Make - FAIL
Desc: Build BlueZ source with '--enable-external-ell' configuration
Output:
src/shared/mcp.c: In function ‘read_track_title’:
src/shared/mcp.c:699:25: error: unused variable ‘cb’ [-Werror=unused-variable]
699 | struct event_callback *cb = mcp->cb;
| ^~
src/shared/mcp.c: At top level:
src/shared/mcp.c:994:6: error: no previous declaration for ‘bt_mcp_mp_name_attach’ [-Werror=missing-declarations]
994 | void bt_mcp_mp_name_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1012:6: error: no previous declaration for ‘bt_mcp_track_changed_attach’ [-Werror=missing-declarations]
1012 | void bt_mcp_track_changed_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1028:6: error: no previous declaration for ‘bt_mcp_track_title_attach’ [-Werror=missing-declarations]
1028 | void bt_mcp_track_title_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1046:6: error: no previous declaration for ‘bt_mcp_track_duration_attach’ [-Werror=missing-declarations]
1046 | void bt_mcp_track_duration_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1064:6: error: no previous declaration for ‘bt_mcp_track_position_attach’ [-Werror=missing-declarations]
1064 | void bt_mcp_track_position_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1082:6: error: no previous declaration for ‘bt_mcp_media_state_attach’ [-Werror=missing-declarations]
1082 | void bt_mcp_media_state_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1100:6: error: no previous declaration for ‘bt_mcp_media_cp_attach’ [-Werror=missing-declarations]
1100 | void bt_mcp_media_cp_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1116:6: error: no previous declaration for ‘bt_mcp_media_cp_op_supported_attach’ [-Werror=missing-declarations]
1116 | void bt_mcp_media_cp_op_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1135:6: error: no previous declaration for ‘bt_mcp_content_control_id_supported_attach’ [-Werror=missing-declarations]
1135 | void bt_mcp_content_control_id_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c: In function ‘bt_mcp_attach’:
src/shared/mcp.c:1381:12: error: unused variable ‘value_handle’ [-Werror=unused-variable]
1381 | uint16_t value_handle;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:8235: src/shared/libshared_mainloop_la-mcp.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4465: all] Error 2


##############################
Test: Incremental Build w/ patches - FAIL
Desc: Incremental build per patch in the series
Output:
src/shared/mcp.c: In function ‘read_track_title’:
src/shared/mcp.c:699:25: error: unused variable ‘cb’ [-Werror=unused-variable]
699 | struct event_callback *cb = mcp->cb;
| ^~
src/shared/mcp.c: At top level:
src/shared/mcp.c:994:6: error: no previous declaration for ‘bt_mcp_mp_name_attach’ [-Werror=missing-declarations]
994 | void bt_mcp_mp_name_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1012:6: error: no previous declaration for ‘bt_mcp_track_changed_attach’ [-Werror=missing-declarations]
1012 | void bt_mcp_track_changed_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1028:6: error: no previous declaration for ‘bt_mcp_track_title_attach’ [-Werror=missing-declarations]
1028 | void bt_mcp_track_title_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1046:6: error: no previous declaration for ‘bt_mcp_track_duration_attach’ [-Werror=missing-declarations]
1046 | void bt_mcp_track_duration_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1064:6: error: no previous declaration for ‘bt_mcp_track_position_attach’ [-Werror=missing-declarations]
1064 | void bt_mcp_track_position_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1082:6: error: no previous declaration for ‘bt_mcp_media_state_attach’ [-Werror=missing-declarations]
1082 | void bt_mcp_media_state_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1100:6: error: no previous declaration for ‘bt_mcp_media_cp_attach’ [-Werror=missing-declarations]
1100 | void bt_mcp_media_cp_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1116:6: error: no previous declaration for ‘bt_mcp_media_cp_op_supported_attach’ [-Werror=missing-declarations]
1116 | void bt_mcp_media_cp_op_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1135:6: error: no previous declaration for ‘bt_mcp_content_control_id_supported_attach’ [-Werror=missing-declarations]
1135 | void bt_mcp_content_control_id_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c: In function ‘bt_mcp_attach’:
src/shared/mcp.c:1381:12: error: unused variable ‘value_handle’ [-Werror=unused-variable]
1381 | uint16_t value_handle;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:8226: src/shared/libshared_mainloop_la-mcp.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4460: all] Error 2


##############################
Test: Scan Build - FAIL
Desc: Run Scan Build with patches
Output:
client/player.c:1756:25: warning: Dereference of null pointer
iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
^~~~~~~~~~~~~~~~~~~~~
1 warning generated.
src/shared/ad.c:369:19: warning: Use of zero-allocated memory
buf[(*pos)++] = ad_type;
^
1 warning generated.
src/shared/gatt-client.c:387:21: warning: Use of memory after it is freed
gatt_db_unregister(op->client->db, op->db_id);
^~~~~~~~~~
src/shared/gatt-client.c:600:2: warning: Use of memory after it is freed
discovery_op_complete(op, false, att_ecode);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:900:2: warning: Use of memory after it is freed
discovery_op_complete(op, success, att_ecode);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1009:2: warning: Use of memory after it is freed
discovery_op_complete(op, success, att_ecode);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1185:2: warning: Use of memory after it is freed
discovery_op_complete(op, success, att_ecode);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1250:2: warning: Use of memory after it is freed
discovery_op_complete(op, success, att_ecode);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1521:6: warning: Use of memory after it is freed
if (read_db_hash(op)) {
^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:1526:2: warning: Use of memory after it is freed
discover_all(op);
^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2028:6: warning: Use of memory after it is freed
if (read_db_hash(op)) {
^~~~~~~~~~~~~~~~
src/shared/gatt-client.c:2036:8: warning: Use of memory after it is freed
discovery_op_ref(op),
^~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3119:2: warning: Use of memory after it is freed
complete_write_long_op(req, success, 0, false);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/gatt-client.c:3141:2: warning: Use of memory after it is freed
request_unref(req);
^~~~~~~~~~~~~~~~~~
12 warnings generated.
src/shared/mcp.c: In function ‘read_track_title’:
src/shared/mcp.c:699:25: error: unused variable ‘cb’ [-Werror=unused-variable]
699 | struct event_callback *cb = mcp->cb;
| ^~
src/shared/mcp.c: At top level:
src/shared/mcp.c:994:6: error: no previous declaration for ‘bt_mcp_mp_name_attach’ [-Werror=missing-declarations]
994 | void bt_mcp_mp_name_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1012:6: error: no previous declaration for ‘bt_mcp_track_changed_attach’ [-Werror=missing-declarations]
1012 | void bt_mcp_track_changed_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1028:6: error: no previous declaration for ‘bt_mcp_track_title_attach’ [-Werror=missing-declarations]
1028 | void bt_mcp_track_title_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1046:6: error: no previous declaration for ‘bt_mcp_track_duration_attach’ [-Werror=missing-declarations]
1046 | void bt_mcp_track_duration_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1064:6: error: no previous declaration for ‘bt_mcp_track_position_attach’ [-Werror=missing-declarations]
1064 | void bt_mcp_track_position_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1082:6: error: no previous declaration for ‘bt_mcp_media_state_attach’ [-Werror=missing-declarations]
1082 | void bt_mcp_media_state_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1100:6: error: no previous declaration for ‘bt_mcp_media_cp_attach’ [-Werror=missing-declarations]
1100 | void bt_mcp_media_cp_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1116:6: error: no previous declaration for ‘bt_mcp_media_cp_op_supported_attach’ [-Werror=missing-declarations]
1116 | void bt_mcp_media_cp_op_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c:1135:6: error: no previous declaration for ‘bt_mcp_content_control_id_supported_attach’ [-Werror=missing-declarations]
1135 | void bt_mcp_content_control_id_supported_attach(struct bt_mcp *mcp)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/shared/mcp.c: In function ‘bt_mcp_attach’:
src/shared/mcp.c:1381:12: error: unused variable ‘value_handle’ [-Werror=unused-variable]
1381 | uint16_t value_handle;
| ^~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [Makefile:8032: src/shared/libshared_glib_la-mcp.lo] Error 1
make: *** [Makefile:4465: all] Error 2




---
Regards,
Linux Bluetooth

2022-10-06 20:43:43

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [PATCH BlueZ 0/4] Media Control Profile Client

Hi Abhay,

On Thu, Oct 6, 2022 at 7:39 AM Abhay Maheta
<[email protected]> wrote:
>
> This series of patches adds support for Media Control Profile for LE Audio.
> These patches primarily foces on Media Control Client Role.
>
> Abhay Maheta (4):
> lib/uuid: Add GMCS UUIDs
> shared/mcp: Add initial code for handling MCP
> profiles: Add initial code for mcp plugin
> monitor/att: Add decoding support for GMCS
>
> Makefile.am | 1 +
> Makefile.plugins | 5 +
> configure.ac | 4 +
> lib/uuid.h | 15 +
> monitor/att.c | 511 +++++++++++++++
> profiles/audio/mcp.c | 429 +++++++++++++
> src/shared/mcp.c | 1408 ++++++++++++++++++++++++++++++++++++++++++
> src/shared/mcp.h | 60 ++
> src/shared/mcs.h | 65 ++
> 9 files changed, 2498 insertions(+)
> create mode 100644 profiles/audio/mcp.c
> create mode 100644 src/shared/mcp.c
> create mode 100644 src/shared/mcp.h
> create mode 100644 src/shared/mcs.h
>
> --
> 2.25.1

Please fix the code style, there are quite a few problems with that,
it would also be great to give some information on how the plugin
works for instance does it work with bluetoothctl player menu?

--
Luiz Augusto von Dentz