* [BlueZ PATCH 0/3] Add MCS fast seek and track position write
@ 2026-08-31 6:11 raghu447
2026-08-31 6:11 ` [BlueZ PATCH 1/3] profiles/audio: Support MCS fast seeking raghu447
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: raghu447 @ 2026-08-31 6:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: raghu447
These patches are needed to make MCS PTS tests pass.
raghavendra (3):
profiles/audio: Support MCS fast seeking
profiles/audio: Support MCS track position writes
shared/mcp: Notify unsupported RFU opcodes
profiles/audio/mcp.c | 63 ++++++++++++++++++++++++++++++++++++++++--
profiles/audio/media.c | 27 ++++++++++++++++++
profiles/audio/media.h | 1 +
src/shared/mcp.c | 4 ++-
unit/test-mcp.c | 14 ++++++++++
5 files changed, 106 insertions(+), 3 deletions(-)
^ permalink raw reply [flat|nested] 15+ messages in thread* [BlueZ PATCH 1/3] profiles/audio: Support MCS fast seeking 2026-08-31 6:11 [BlueZ PATCH 0/3] Add MCS fast seek and track position write raghu447 @ 2026-08-31 6:11 ` raghu447 2026-09-02 15:31 ` Luiz Augusto von Dentz 2026-08-31 6:11 ` [BlueZ PATCH 2/3] profiles/audio: Support MCS track position writes raghu447 2026-08-31 6:11 ` [BlueZ PATCH 3/3] shared/mcp: Notify unsupported RFU opcodes raghu447 2 siblings, 1 reply; 15+ messages in thread From: raghu447 @ 2026-08-31 6:11 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghavendra From: raghavendra <raghavendra.rao@collabora.com> --- profiles/audio/mcp.c | 43 ++++++++++++++++++++++++++++++++++++++++++ profiles/audio/media.c | 27 ++++++++++++++++++++++++++ profiles/audio/media.h | 1 + 3 files changed, 71 insertions(+) diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c index 8adf814e8..4df388a22 100644 --- a/profiles/audio/mcp.c +++ b/profiles/audio/mcp.c @@ -60,6 +60,7 @@ #define MCS_UUID_STR "00001848-0000-1000-8000-00805f9b34fb" #define GMCS_UUID_STR "00001849-0000-1000-8000-00805f9b34fb" +#define MCS_SEEK_OFFSET (10 * 1000 * 1000) /* @@ -440,6 +441,7 @@ struct mcs_instance { struct bt_mcs *mcs; struct queue *player_links; bool at_start; + int8_t seeking_speed; /* GMCS-specific */ struct bt_uinput *uinput; @@ -494,6 +496,11 @@ static void mcs_update_media_state(struct mcs_instance *mcs) state = BT_MCS_STATE_INACTIVE; } + if (state != BT_MCS_STATE_SEEKING && mcs->seeking_speed) { + mcs->seeking_speed = 0; + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); + } + bt_mcs_set_media_state(mcs->mcs, state); bt_mcs_changed(mcs->mcs, MCS_TRACK_POSITION_CHRC_UUID); } @@ -656,6 +663,32 @@ static bool mcs_pause(void *data) return mcs_command(mcs, BT_MCS_CMD_PAUSE); } +static bool mcs_fast_rewind(void *data) +{ + struct mcs_instance *mcs = data; + struct player_link *p = mcs_get_active(mcs); + + if (!p || !local_player_seek(p->lp, -MCS_SEEK_OFFSET)) + return false; + + mcs->seeking_speed = -1; + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); + return true; +} + +static bool mcs_fast_forward(void *data) +{ + struct mcs_instance *mcs = data; + struct player_link *p = mcs_get_active(mcs); + + if (!p || !local_player_seek(p->lp, MCS_SEEK_OFFSET)) + return false; + + mcs->seeking_speed = 1; + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); + return true; +} + static bool mcs_stop(void *data) { struct mcs_instance *mcs = data; @@ -752,6 +785,13 @@ static int32_t mcs_track_position(void *data) return local_player_get_position(p->lp) / 10; } +static int8_t mcs_seeking_speed(void *data) +{ + struct mcs_instance *mcs = data; + + return mcs->seeking_speed; +} + static uint8_t mcs_playing_order(void *data) { struct mcs_instance *mcs = data; @@ -858,12 +898,15 @@ static const struct bt_mcs_callback gmcs_cb = { .track_title = mcs_track_title, .track_duration = mcs_track_duration, .track_position = mcs_track_position, + .seeking_speed = mcs_seeking_speed, .playing_order = mcs_playing_order, .playing_order_supported = mcs_playing_order_supported, .set_track_position = mcs_set_track_position, .set_playing_order = mcs_set_playing_order, .play = mcs_play, .pause = mcs_pause, + .fast_rewind = mcs_fast_rewind, + .fast_forward = mcs_fast_forward, .stop = mcs_stop, .next_track = mcs_next_track, .previous_track = mcs_previous_track, diff --git a/profiles/audio/media.c b/profiles/audio/media.c index 95f9580b0..aeb6226da 100644 --- a/profiles/audio/media.c +++ b/profiles/audio/media.c @@ -157,6 +157,7 @@ struct local_player { GTimer *timer; bool play; bool pause; + bool seek; bool next; bool previous; bool control; @@ -2296,6 +2297,29 @@ bool local_player_pause(struct local_player *mp) return local_player_send(mp, "Pause"); } +bool local_player_seek(struct local_player *mp, int64_t offset) +{ + DBusMessage *msg; + + DBG(""); + + if (!mp->seek || !mp->control) + return false; + + msg = dbus_message_new_method_call(mp->sender, mp->path, + MEDIA_PLAYER_INTERFACE, "Seek"); + if (msg == NULL) { + error("Couldn't allocate D-Bus message"); + return false; + } + + dbus_message_append_args(msg, DBUS_TYPE_INT64, &offset, + DBUS_TYPE_INVALID); + g_dbus_send_message(btd_get_dbus_connection(), msg); + + return true; +} + bool local_player_next(struct local_player *mp) { DBG(""); @@ -2673,6 +2697,9 @@ static gboolean set_player_property(struct local_player *mp, const char *key, if (strcasecmp(key, "CanPause") == 0) return set_flag(mp, &var, &mp->pause); + if (strcasecmp(key, "CanSeek") == 0) + return set_flag(mp, &var, &mp->seek); + if (strcasecmp(key, "CanGoNext") == 0) return set_flag(mp, &var, &mp->next); diff --git a/profiles/audio/media.h b/profiles/audio/media.h index 1c43075ba..a89466657 100644 --- a/profiles/audio/media.h +++ b/profiles/audio/media.h @@ -73,6 +73,7 @@ bool local_player_have_track(struct local_player *lp); bool local_player_play(struct local_player *lp); bool local_player_stop(struct local_player *lp); bool local_player_pause(struct local_player *lp); +bool local_player_seek(struct local_player *lp, int64_t offset); bool local_player_next(struct local_player *lp); bool local_player_previous(struct local_player *lp); ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [BlueZ PATCH 1/3] profiles/audio: Support MCS fast seeking 2026-08-31 6:11 ` [BlueZ PATCH 1/3] profiles/audio: Support MCS fast seeking raghu447 @ 2026-09-02 15:31 ` Luiz Augusto von Dentz 0 siblings, 0 replies; 15+ messages in thread From: Luiz Augusto von Dentz @ 2026-09-02 15:31 UTC (permalink / raw) To: raghu447; +Cc: linux-bluetooth Hi Raghu, On Mon, Aug 31, 2026 at 2:12 AM raghu447 <raghavendra.rao@collabora.com> wrote: > > From: raghavendra <raghavendra.rao@collabora.com> > > --- > profiles/audio/mcp.c | 43 ++++++++++++++++++++++++++++++++++++++++++ > profiles/audio/media.c | 27 ++++++++++++++++++++++++++ > profiles/audio/media.h | 1 + > 3 files changed, 71 insertions(+) > > diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c > index 8adf814e8..4df388a22 100644 > --- a/profiles/audio/mcp.c > +++ b/profiles/audio/mcp.c > @@ -60,6 +60,7 @@ > > #define MCS_UUID_STR "00001848-0000-1000-8000-00805f9b34fb" > #define GMCS_UUID_STR "00001849-0000-1000-8000-00805f9b34fb" > +#define MCS_SEEK_OFFSET (10 * 1000 * 1000) Okay, what is this for? Why it is not the final number and where it comes from? > > > /* > @@ -440,6 +441,7 @@ struct mcs_instance { > struct bt_mcs *mcs; > struct queue *player_links; > bool at_start; > + int8_t seeking_speed; > > /* GMCS-specific */ > struct bt_uinput *uinput; > @@ -494,6 +496,11 @@ static void mcs_update_media_state(struct mcs_instance *mcs) > state = BT_MCS_STATE_INACTIVE; > } > > + if (state != BT_MCS_STATE_SEEKING && mcs->seeking_speed) { > + mcs->seeking_speed = 0; > + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); > + } > + > bt_mcs_set_media_state(mcs->mcs, state); > bt_mcs_changed(mcs->mcs, MCS_TRACK_POSITION_CHRC_UUID); > } > @@ -656,6 +663,32 @@ static bool mcs_pause(void *data) > return mcs_command(mcs, BT_MCS_CMD_PAUSE); > } > > +static bool mcs_fast_rewind(void *data) > +{ > + struct mcs_instance *mcs = data; > + struct player_link *p = mcs_get_active(mcs); > + > + if (!p || !local_player_seek(p->lp, -MCS_SEEK_OFFSET)) > + return false; Should we seek back to 0? I don't get why you need to seek negatively like this. > + > + mcs->seeking_speed = -1; > + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); > + return true; > +} > + > +static bool mcs_fast_forward(void *data) > +{ > + struct mcs_instance *mcs = data; > + struct player_link *p = mcs_get_active(mcs); > + > + if (!p || !local_player_seek(p->lp, MCS_SEEK_OFFSET)) > + return false; > + > + mcs->seeking_speed = 1; > + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); > + return true; > +} > + > static bool mcs_stop(void *data) > { > struct mcs_instance *mcs = data; > @@ -752,6 +785,13 @@ static int32_t mcs_track_position(void *data) > return local_player_get_position(p->lp) / 10; > } > > +static int8_t mcs_seeking_speed(void *data) > +{ > + struct mcs_instance *mcs = data; > + > + return mcs->seeking_speed; > +} > + > static uint8_t mcs_playing_order(void *data) > { > struct mcs_instance *mcs = data; > @@ -858,12 +898,15 @@ static const struct bt_mcs_callback gmcs_cb = { > .track_title = mcs_track_title, > .track_duration = mcs_track_duration, > .track_position = mcs_track_position, > + .seeking_speed = mcs_seeking_speed, > .playing_order = mcs_playing_order, > .playing_order_supported = mcs_playing_order_supported, > .set_track_position = mcs_set_track_position, > .set_playing_order = mcs_set_playing_order, > .play = mcs_play, > .pause = mcs_pause, > + .fast_rewind = mcs_fast_rewind, > + .fast_forward = mcs_fast_forward, > .stop = mcs_stop, > .next_track = mcs_next_track, > .previous_track = mcs_previous_track, > diff --git a/profiles/audio/media.c b/profiles/audio/media.c > index 95f9580b0..aeb6226da 100644 > --- a/profiles/audio/media.c > +++ b/profiles/audio/media.c > @@ -157,6 +157,7 @@ struct local_player { > GTimer *timer; > bool play; > bool pause; > + bool seek; > bool next; > bool previous; > bool control; > @@ -2296,6 +2297,29 @@ bool local_player_pause(struct local_player *mp) > return local_player_send(mp, "Pause"); > } > > +bool local_player_seek(struct local_player *mp, int64_t offset) > +{ > + DBusMessage *msg; > + > + DBG(""); > + > + if (!mp->seek || !mp->control) > + return false; > + > + msg = dbus_message_new_method_call(mp->sender, mp->path, > + MEDIA_PLAYER_INTERFACE, "Seek"); > + if (msg == NULL) { > + error("Couldn't allocate D-Bus message"); > + return false; > + } > + > + dbus_message_append_args(msg, DBUS_TYPE_INT64, &offset, > + DBUS_TYPE_INVALID); > + g_dbus_send_message(btd_get_dbus_connection(), msg); > + > + return true; > +} > + > bool local_player_next(struct local_player *mp) > { > DBG(""); > @@ -2673,6 +2697,9 @@ static gboolean set_player_property(struct local_player *mp, const char *key, > if (strcasecmp(key, "CanPause") == 0) > return set_flag(mp, &var, &mp->pause); > > + if (strcasecmp(key, "CanSeek") == 0) > + return set_flag(mp, &var, &mp->seek); > + > if (strcasecmp(key, "CanGoNext") == 0) > return set_flag(mp, &var, &mp->next); > > diff --git a/profiles/audio/media.h b/profiles/audio/media.h > index 1c43075ba..a89466657 100644 > --- a/profiles/audio/media.h > +++ b/profiles/audio/media.h > @@ -73,6 +73,7 @@ bool local_player_have_track(struct local_player *lp); > bool local_player_play(struct local_player *lp); > bool local_player_stop(struct local_player *lp); > bool local_player_pause(struct local_player *lp); > +bool local_player_seek(struct local_player *lp, int64_t offset); > bool local_player_next(struct local_player *lp); > bool local_player_previous(struct local_player *lp); > > -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 15+ messages in thread
* [BlueZ PATCH 2/3] profiles/audio: Support MCS track position writes 2026-08-31 6:11 [BlueZ PATCH 0/3] Add MCS fast seek and track position write raghu447 2026-08-31 6:11 ` [BlueZ PATCH 1/3] profiles/audio: Support MCS fast seeking raghu447 @ 2026-08-31 6:11 ` raghu447 2026-09-02 15:35 ` Luiz Augusto von Dentz 2026-08-31 6:11 ` [BlueZ PATCH 3/3] shared/mcp: Notify unsupported RFU opcodes raghu447 2 siblings, 1 reply; 15+ messages in thread From: raghu447 @ 2026-08-31 6:11 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghavendra From: raghavendra <raghavendra.rao@collabora.com> This is needed to Pass PTS GMCS/SR/SP/BV-02-C test. --- profiles/audio/mcp.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c index 4df388a22..fc9d2dc73 100644 --- a/profiles/audio/mcp.c +++ b/profiles/audio/mcp.c @@ -835,8 +835,24 @@ static uint16_t mcs_playing_order_supported(void *data) static bool mcs_set_track_position(void *data, int32_t value) { - /* TODO: add support to setting position in org.bluez.MediaPlayer */ - return false; + struct mcs_instance *mcs = data; + struct player_link *p = mcs_get_active(mcs); + int64_t position = value; + + if (!p) + return false; + + if (value < 0) { + int32_t duration = mcs_track_duration(mcs); + + if (duration == BT_MCS_DURATION_UNAVAILABLE) + return false; + + position += duration; + } + + return local_player_seek(p->lp, (position * 10 - + local_player_get_position(p->lp)) * 1000); } static bool mcs_set_playing_order(void *data, uint8_t value) ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [BlueZ PATCH 2/3] profiles/audio: Support MCS track position writes 2026-08-31 6:11 ` [BlueZ PATCH 2/3] profiles/audio: Support MCS track position writes raghu447 @ 2026-09-02 15:35 ` Luiz Augusto von Dentz 2026-09-03 8:19 ` Bastien Nocera 0 siblings, 1 reply; 15+ messages in thread From: Luiz Augusto von Dentz @ 2026-09-02 15:35 UTC (permalink / raw) To: raghu447; +Cc: linux-bluetooth Hi Raghu, On Mon, Aug 31, 2026 at 2:13 AM raghu447 <raghavendra.rao@collabora.com> wrote: > > From: raghavendra <raghavendra.rao@collabora.com> > > This is needed to Pass PTS GMCS/SR/SP/BV-02-C test. > --- > profiles/audio/mcp.c | 20 ++++++++++++++++++-- > 1 file changed, 18 insertions(+), 2 deletions(-) > > diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c > index 4df388a22..fc9d2dc73 100644 > --- a/profiles/audio/mcp.c > +++ b/profiles/audio/mcp.c > @@ -835,8 +835,24 @@ static uint16_t mcs_playing_order_supported(void *data) > > static bool mcs_set_track_position(void *data, int32_t value) > { > - /* TODO: add support to setting position in org.bluez.MediaPlayer */ > - return false; > + struct mcs_instance *mcs = data; > + struct player_link *p = mcs_get_active(mcs); > + int64_t position = value; > + > + if (!p) > + return false; > + > + if (value < 0) { > + int32_t duration = mcs_track_duration(mcs); > + > + if (duration == BT_MCS_DURATION_UNAVAILABLE) > + return false; > + > + position += duration; > + } Are the seek and position values in different units? We should probably document why we are having to multiply it bellow. > + return local_player_seek(p->lp, (position * 10 - > + local_player_get_position(p->lp)) * 1000); > } > > static bool mcs_set_playing_order(void *data, uint8_t value) > -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [BlueZ PATCH 2/3] profiles/audio: Support MCS track position writes 2026-09-02 15:35 ` Luiz Augusto von Dentz @ 2026-09-03 8:19 ` Bastien Nocera 2026-09-04 16:53 ` [PATCH 0/4] Add MCS fast seek and track position write support raghu447 0 siblings, 1 reply; 15+ messages in thread From: Bastien Nocera @ 2026-09-03 8:19 UTC (permalink / raw) To: Luiz Augusto von Dentz, raghu447; +Cc: linux-bluetooth On Wed, 2026-09-02 at 11:35 -0400, Luiz Augusto von Dentz wrote: > Hi Raghu, > > On Mon, Aug 31, 2026 at 2:13 AM raghu447 > <raghavendra.rao@collabora.com> wrote: > > > > From: raghavendra <raghavendra.rao@collabora.com> > > > > This is needed to Pass PTS GMCS/SR/SP/BV-02-C test. > > --- > > profiles/audio/mcp.c | 20 ++++++++++++++++++-- > > 1 file changed, 18 insertions(+), 2 deletions(-) > > > > diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c > > index 4df388a22..fc9d2dc73 100644 > > --- a/profiles/audio/mcp.c > > +++ b/profiles/audio/mcp.c > > @@ -835,8 +835,24 @@ static uint16_t > > mcs_playing_order_supported(void *data) > > > > static bool mcs_set_track_position(void *data, int32_t value) > > { > > - /* TODO: add support to setting position in > > org.bluez.MediaPlayer */ > > - return false; > > + struct mcs_instance *mcs = data; > > + struct player_link *p = mcs_get_active(mcs); > > + int64_t position = value; > > + > > + if (!p) > > + return false; > > + > > + if (value < 0) { > > + int32_t duration = mcs_track_duration(mcs); > > + > > + if (duration == BT_MCS_DURATION_UNAVAILABLE) > > + return false; > > + > > + position += duration; > > + } > > Are the seek and position values in different units? We should > probably document why we are having to multiply it bellow. I'd recommend using variable names like "position_msec/position_usec/etc." and declaring constants for things like converting between what the hardware uses and the code uses, like glib's G_USEC_PER_SEC. Cheers > > > + return local_player_seek(p->lp, (position * 10 - > > + local_player_get_position(p->lp)) * > > 1000); > > } > > > > static bool mcs_set_playing_order(void *data, uint8_t value) > > > ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 0/4] Add MCS fast seek and track position write support 2026-09-03 8:19 ` Bastien Nocera @ 2026-09-04 16:53 ` raghu447 2026-09-04 16:53 ` [PATCH 1/4] profiles/audio: Support MCS track position writes raghu447 ` (4 more replies) 0 siblings, 5 replies; 15+ messages in thread From: raghu447 @ 2026-09-04 16:53 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghu447 These patches are needed to make MCS PTS tests pass. raghavendra (4): profiles/audio: Support MCS track position writes profiles/audio: Support MCS fast seeking shared/mcp: Notify unsupported RFU opcodes unit/test-mcp: Test unsupported RFU opcode profiles/audio/mcp.c | 71 ++++++++++++++++++++++++++++++++++++++++-- profiles/audio/media.c | 32 +++++++++++++++++++ profiles/audio/media.h | 1 + src/shared/mcp.c | 2 +- unit/test-mcp.c | 14 +++++++++ 5 files changed, 117 insertions(+), 3 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/4] profiles/audio: Support MCS track position writes 2026-09-04 16:53 ` [PATCH 0/4] Add MCS fast seek and track position write support raghu447 @ 2026-09-04 16:53 ` raghu447 2026-09-04 17:51 ` Add MCS fast seek and track position write support bluez.test.bot 2026-09-04 16:53 ` [PATCH 2/4] profiles/audio: Support MCS fast seeking raghu447 ` (3 subsequent siblings) 4 siblings, 1 reply; 15+ messages in thread From: raghu447 @ 2026-09-04 16:53 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghavendra From: raghavendra <raghavendra.rao@collabora.com> Use MPRIS Seek to handle MCS Track Position writes. This is required by PTS GMCS/SR/SP/BV-02-C test. --- profiles/audio/mcp.c | 22 ++++++++++++++++++++-- profiles/audio/media.c | 32 ++++++++++++++++++++++++++++++++ profiles/audio/media.h | 1 + 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c index 8adf814e8..2d239ac4b 100644 --- a/profiles/audio/mcp.c +++ b/profiles/audio/mcp.c @@ -795,8 +795,26 @@ static uint16_t mcs_playing_order_supported(void *data) static bool mcs_set_track_position(void *data, int32_t value) { - /* TODO: add support to setting position in org.bluez.MediaPlayer */ - return false; + struct mcs_instance *mcs = data; + struct player_link *p = mcs_get_active(mcs); + int64_t position_centisec = value; + + if (!p) + return false; + + if (value < 0) { + int32_t duration_centisec = mcs_track_duration(mcs); + + if (duration_centisec == BT_MCS_DURATION_UNAVAILABLE) + return false; + + position_centisec += duration_centisec; + } + + /* Convert MCS centiseconds to a relative MPRIS microsecond offset. */ + return local_player_seek(p->lp, (position_centisec * 10 - + local_player_get_position(p->lp)) * + G_TIME_SPAN_MILLISECOND); } static bool mcs_set_playing_order(void *data, uint8_t value) diff --git a/profiles/audio/media.c b/profiles/audio/media.c index 95f9580b0..82117a2ed 100644 --- a/profiles/audio/media.c +++ b/profiles/audio/media.c @@ -157,6 +157,7 @@ struct local_player { GTimer *timer; bool play; bool pause; + bool seek; bool next; bool previous; bool control; @@ -2296,6 +2297,29 @@ bool local_player_pause(struct local_player *mp) return local_player_send(mp, "Pause"); } +bool local_player_seek(struct local_player *mp, int64_t offset_usec) +{ + DBusMessage *msg; + + DBG(""); + + if (!mp->seek || !mp->control) + return false; + + msg = dbus_message_new_method_call(mp->sender, mp->path, + MEDIA_PLAYER_INTERFACE, "Seek"); + if (msg == NULL) { + error("Couldn't allocate D-Bus message"); + return false; + } + + dbus_message_append_args(msg, DBUS_TYPE_INT64, &offset_usec, + DBUS_TYPE_INVALID); + g_dbus_send_message(btd_get_dbus_connection(), msg); + + return true; +} + bool local_player_next(struct local_player *mp) { DBG(""); @@ -2673,6 +2697,9 @@ static gboolean set_player_property(struct local_player *mp, const char *key, if (strcasecmp(key, "CanPause") == 0) return set_flag(mp, &var, &mp->pause); + if (strcasecmp(key, "CanSeek") == 0) + return set_flag(mp, &var, &mp->seek); + if (strcasecmp(key, "CanGoNext") == 0) return set_flag(mp, &var, &mp->next); @@ -3247,6 +3274,11 @@ static void app_register_player(void *data, void *user_data) goto fail; } + if (g_dbus_proxy_get_property(proxy, "CanSeek", &iter)) { + if (!set_flag(player, &iter, &player->seek)) + goto fail; + } + if (g_dbus_proxy_get_property(proxy, "CanGoNext", &iter)) { if (!set_flag(player, &iter, &player->next)) goto fail; diff --git a/profiles/audio/media.h b/profiles/audio/media.h index 1c43075ba..43a85b1d6 100644 --- a/profiles/audio/media.h +++ b/profiles/audio/media.h @@ -73,6 +73,7 @@ bool local_player_have_track(struct local_player *lp); bool local_player_play(struct local_player *lp); bool local_player_stop(struct local_player *lp); bool local_player_pause(struct local_player *lp); +bool local_player_seek(struct local_player *lp, int64_t offset_usec); bool local_player_next(struct local_player *lp); bool local_player_previous(struct local_player *lp); -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* RE: Add MCS fast seek and track position write support 2026-09-04 16:53 ` [PATCH 1/4] profiles/audio: Support MCS track position writes raghu447 @ 2026-09-04 17:51 ` bluez.test.bot 0 siblings, 0 replies; 15+ messages in thread From: bluez.test.bot @ 2026-09-04 17:51 UTC (permalink / raw) To: linux-bluetooth, raghavendra.rao [-- Attachment #1: Type: text/plain, Size: 988 bytes --] 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=1158246 ---Test result--- Test Summary: CheckPatch PASS 1.58 seconds GitLint PASS 1.05 seconds BuildEll PASS 16.66 seconds BluezMake PASS 500.28 seconds MakeCheck PASS 17.84 seconds MakeDistcheck PASS 136.29 seconds CheckValgrind PASS 193.43 seconds CheckSmatch PASS 230.36 seconds bluezmakeextell PASS 86.95 seconds IncrementalBuild PASS 613.86 seconds ScanBuild PASS 759.13 seconds https://github.com/bluez/bluez/pull/2492 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/4] profiles/audio: Support MCS fast seeking 2026-09-04 16:53 ` [PATCH 0/4] Add MCS fast seek and track position write support raghu447 2026-09-04 16:53 ` [PATCH 1/4] profiles/audio: Support MCS track position writes raghu447 @ 2026-09-04 16:53 ` raghu447 2026-09-04 16:53 ` [PATCH 3/4] shared/mcp: Notify unsupported RFU opcodes raghu447 ` (2 subsequent siblings) 4 siblings, 0 replies; 15+ messages in thread From: raghu447 @ 2026-09-04 16:53 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghavendra From: raghavendra <raghavendra.rao@collabora.com> Map Fast Rewind and Fast Forward to relative MPRIS Seek calls. Report direction through Seeking Speed until Seeked restores player state. This is required by PTS tests GMCS/SR/MCP/BV-05-C to BV-08-C. --- profiles/audio/mcp.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/profiles/audio/mcp.c b/profiles/audio/mcp.c index 2d239ac4b..314bce243 100644 --- a/profiles/audio/mcp.c +++ b/profiles/audio/mcp.c @@ -60,6 +60,7 @@ #define MCS_UUID_STR "00001848-0000-1000-8000-00805f9b34fb" #define GMCS_UUID_STR "00001849-0000-1000-8000-00805f9b34fb" +#define MCS_SEEK_OFFSET_USEC (10 * G_USEC_PER_SEC) /* @@ -440,6 +441,7 @@ struct mcs_instance { struct bt_mcs *mcs; struct queue *player_links; bool at_start; + int8_t seeking_speed; /* GMCS-specific */ struct bt_uinput *uinput; @@ -494,6 +496,11 @@ static void mcs_update_media_state(struct mcs_instance *mcs) state = BT_MCS_STATE_INACTIVE; } + if (state != BT_MCS_STATE_SEEKING && mcs->seeking_speed) { + mcs->seeking_speed = 0; + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); + } + bt_mcs_set_media_state(mcs->mcs, state); bt_mcs_changed(mcs->mcs, MCS_TRACK_POSITION_CHRC_UUID); } @@ -557,6 +564,11 @@ static void lp_track_position(uint32_t old_ms, uint32_t new_ms, void *user_data) if (!player_link_is_active(p)) return; + if (mcs->seeking_speed) { + mcs_update_media_state(mcs); + return; + } + bt_mcs_changed(mcs->mcs, MCS_TRACK_POSITION_CHRC_UUID); } @@ -656,6 +668,33 @@ static bool mcs_pause(void *data) return mcs_command(mcs, BT_MCS_CMD_PAUSE); } +/* MPRIS Seek uses signed offsets: negative rewinds, positive advances. */ +static bool mcs_fast_rewind(void *data) +{ + struct mcs_instance *mcs = data; + struct player_link *p = mcs_get_active(mcs); + + if (!p || !local_player_seek(p->lp, -MCS_SEEK_OFFSET_USEC)) + return false; + + mcs->seeking_speed = -1; + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); + return true; +} + +static bool mcs_fast_forward(void *data) +{ + struct mcs_instance *mcs = data; + struct player_link *p = mcs_get_active(mcs); + + if (!p || !local_player_seek(p->lp, MCS_SEEK_OFFSET_USEC)) + return false; + + mcs->seeking_speed = 1; + bt_mcs_changed(mcs->mcs, MCS_SEEKING_SPEED_CHRC_UUID); + return true; +} + static bool mcs_stop(void *data) { struct mcs_instance *mcs = data; @@ -752,6 +791,13 @@ static int32_t mcs_track_position(void *data) return local_player_get_position(p->lp) / 10; } +static int8_t mcs_seeking_speed(void *data) +{ + struct mcs_instance *mcs = data; + + return mcs->seeking_speed; +} + static uint8_t mcs_playing_order(void *data) { struct mcs_instance *mcs = data; @@ -876,12 +922,15 @@ static const struct bt_mcs_callback gmcs_cb = { .track_title = mcs_track_title, .track_duration = mcs_track_duration, .track_position = mcs_track_position, + .seeking_speed = mcs_seeking_speed, .playing_order = mcs_playing_order, .playing_order_supported = mcs_playing_order_supported, .set_track_position = mcs_set_track_position, .set_playing_order = mcs_set_playing_order, .play = mcs_play, .pause = mcs_pause, + .fast_rewind = mcs_fast_rewind, + .fast_forward = mcs_fast_forward, .stop = mcs_stop, .next_track = mcs_next_track, .previous_track = mcs_previous_track, -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/4] shared/mcp: Notify unsupported RFU opcodes 2026-09-04 16:53 ` [PATCH 0/4] Add MCS fast seek and track position write support raghu447 2026-09-04 16:53 ` [PATCH 1/4] profiles/audio: Support MCS track position writes raghu447 2026-09-04 16:53 ` [PATCH 2/4] profiles/audio: Support MCS fast seeking raghu447 @ 2026-09-04 16:53 ` raghu447 2026-09-04 16:53 ` [PATCH 4/4] unit/test-mcp: Test unsupported RFU opcode raghu447 2026-09-04 20:20 ` [PATCH 0/4] Add MCS fast seek and track position write support patchwork-bot+bluetooth 4 siblings, 0 replies; 15+ messages in thread From: raghu447 @ 2026-09-04 16:53 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghavendra From: raghavendra <raghavendra.rao@collabora.com> Use the ATT result to suppress responses for malformed writes while allowing opcode 0x00 to report Operation Not Supported. This is required by GMCS/SR/SPE/BI-01-C. --- src/shared/mcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/mcp.c b/src/shared/mcp.c index a954869b0..4ee14d156 100644 --- a/src/shared/mcp.c +++ b/src/shared/mcp.c @@ -370,7 +370,7 @@ respond: ret, rsp.result); gatt_db_attribute_write_result(attrib, id, ret); - if (!rsp.op) + if (ret) return; /* Make state transition immediately if command was successful and has -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 4/4] unit/test-mcp: Test unsupported RFU opcode 2026-09-04 16:53 ` [PATCH 0/4] Add MCS fast seek and track position write support raghu447 ` (2 preceding siblings ...) 2026-09-04 16:53 ` [PATCH 3/4] shared/mcp: Notify unsupported RFU opcodes raghu447 @ 2026-09-04 16:53 ` raghu447 2026-09-04 20:20 ` [PATCH 0/4] Add MCS fast seek and track position write support patchwork-bot+bluetooth 4 siblings, 0 replies; 15+ messages in thread From: raghu447 @ 2026-09-04 16:53 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghavendra From: raghavendra <raghavendra.rao@collabora.com> Verify that GMCS/SR/SPE/BI-01-C opcode 0x00 produces an Operation Not Supported notification. --- unit/test-mcp.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/unit/test-mcp.c b/unit/test-mcp.c index 6331c6c99..21997915d 100644 --- a/unit/test-mcp.c +++ b/unit/test-mcp.c @@ -2057,6 +2057,19 @@ static void testgroup_sr_mcp(void) } +#define GMCS_SR_SPE_BI_01_C \ + WRITE_NORESP_CHRC(CP, 0x00), \ + NOTIFY_CHRC(CP, 0x00, 0x02 /* not supp */) + +static void testgroup_sr_spe(void) +{ + define_test("GMCS/SR/SPE/BI-01-C [Media Control Point - Opcode not " + "Supported]", + test_setup_server, test_server, + &cfg_sggit_gmcs, GMCS_SR_SPE_BI_01_C); +} + + static void sr_spn_value(struct test_data *data, struct iovec *buf, size_t size, uint16_t uuid) { @@ -2132,6 +2145,7 @@ int main(int argc, char *argv[]) testgroup_cl_extra(); testgroup_sr_sggit(); testgroup_sr_mcp(); + testgroup_sr_spe(); testgroup_sr_spn(); return tester_run(); -- 2.43.0 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 0/4] Add MCS fast seek and track position write support 2026-09-04 16:53 ` [PATCH 0/4] Add MCS fast seek and track position write support raghu447 ` (3 preceding siblings ...) 2026-09-04 16:53 ` [PATCH 4/4] unit/test-mcp: Test unsupported RFU opcode raghu447 @ 2026-09-04 20:20 ` patchwork-bot+bluetooth 4 siblings, 0 replies; 15+ messages in thread From: patchwork-bot+bluetooth @ 2026-09-04 20:20 UTC (permalink / raw) To: raghu447; +Cc: linux-bluetooth Hello: This series was applied to bluetooth/bluez.git (master) by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>: On Fri, 4 Sep 2026 22:23:28 +0530 you wrote: > These patches are needed to make MCS PTS tests pass. > > raghavendra (4): > profiles/audio: Support MCS track position writes > profiles/audio: Support MCS fast seeking > shared/mcp: Notify unsupported RFU opcodes > unit/test-mcp: Test unsupported RFU opcode > > [...] Here is the summary with links: - [1/4] profiles/audio: Support MCS track position writes https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=d13f18c9a930 - [2/4] profiles/audio: Support MCS fast seeking https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=f801cd34402b - [3/4] shared/mcp: Notify unsupported RFU opcodes https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=4e237b304e5b - [4/4] unit/test-mcp: Test unsupported RFU opcode https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=36cc1305a827 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 15+ messages in thread
* [BlueZ PATCH 3/3] shared/mcp: Notify unsupported RFU opcodes 2026-08-31 6:11 [BlueZ PATCH 0/3] Add MCS fast seek and track position write raghu447 2026-08-31 6:11 ` [BlueZ PATCH 1/3] profiles/audio: Support MCS fast seeking raghu447 2026-08-31 6:11 ` [BlueZ PATCH 2/3] profiles/audio: Support MCS track position writes raghu447 @ 2026-08-31 6:11 ` raghu447 2026-09-02 15:36 ` Luiz Augusto von Dentz 2 siblings, 1 reply; 15+ messages in thread From: raghu447 @ 2026-08-31 6:11 UTC (permalink / raw) To: linux-bluetooth; +Cc: raghavendra From: raghavendra <raghavendra.rao@collabora.com> This is needed to Pass PTS GMCS/SR/SPE/BI-01-C test. --- src/shared/mcp.c | 4 +++- unit/test-mcp.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/shared/mcp.c b/src/shared/mcp.c index a954869b0..583ae40dc 100644 --- a/src/shared/mcp.c +++ b/src/shared/mcp.c @@ -324,6 +324,7 @@ static void write_media_cp(struct gatt_db_attribute *attrib, int ret = 0; int32_t arg = 0; uint8_t op; + bool rfu_op = false; bool ok = false; if (offset) { @@ -337,6 +338,7 @@ static void write_media_cp(struct gatt_db_attribute *attrib, } rsp.op = op; + rfu_op = !op; cmd = mcs_get_command(op); if (!cmd || !(cmd->support & mcs_get_supported(mcs))) { @@ -370,7 +372,7 @@ respond: ret, rsp.result); gatt_db_attribute_write_result(attrib, id, ret); - if (!rsp.op) + if (!rsp.op && !rfu_op) return; /* Make state transition immediately if command was successful and has diff --git a/unit/test-mcp.c b/unit/test-mcp.c index 6331c6c99..21997915d 100644 --- a/unit/test-mcp.c +++ b/unit/test-mcp.c @@ -2057,6 +2057,19 @@ static void testgroup_sr_mcp(void) } +#define GMCS_SR_SPE_BI_01_C \ + WRITE_NORESP_CHRC(CP, 0x00), \ + NOTIFY_CHRC(CP, 0x00, 0x02 /* not supp */) + +static void testgroup_sr_spe(void) +{ + define_test("GMCS/SR/SPE/BI-01-C [Media Control Point - Opcode not " + "Supported]", + test_setup_server, test_server, + &cfg_sggit_gmcs, GMCS_SR_SPE_BI_01_C); +} + + static void sr_spn_value(struct test_data *data, struct iovec *buf, size_t size, uint16_t uuid) { @@ -2132,6 +2145,7 @@ int main(int argc, char *argv[]) testgroup_cl_extra(); testgroup_sr_sggit(); testgroup_sr_mcp(); + testgroup_sr_spe(); testgroup_sr_spn(); return tester_run(); ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [BlueZ PATCH 3/3] shared/mcp: Notify unsupported RFU opcodes 2026-08-31 6:11 ` [BlueZ PATCH 3/3] shared/mcp: Notify unsupported RFU opcodes raghu447 @ 2026-09-02 15:36 ` Luiz Augusto von Dentz 0 siblings, 0 replies; 15+ messages in thread From: Luiz Augusto von Dentz @ 2026-09-02 15:36 UTC (permalink / raw) To: raghu447; +Cc: linux-bluetooth Hi Raghu, On Mon, Aug 31, 2026 at 2:12 AM raghu447 <raghavendra.rao@collabora.com> wrote: > > From: raghavendra <raghavendra.rao@collabora.com> > > This is needed to Pass PTS GMCS/SR/SPE/BI-01-C test. > --- > src/shared/mcp.c | 4 +++- > unit/test-mcp.c | 14 ++++++++++++++ Split the changes for the unit and shared components. > 2 files changed, 17 insertions(+), 1 deletion(-) > > diff --git a/src/shared/mcp.c b/src/shared/mcp.c > index a954869b0..583ae40dc 100644 > --- a/src/shared/mcp.c > +++ b/src/shared/mcp.c > @@ -324,6 +324,7 @@ static void write_media_cp(struct gatt_db_attribute *attrib, > int ret = 0; > int32_t arg = 0; > uint8_t op; > + bool rfu_op = false; > bool ok = false; > > if (offset) { > @@ -337,6 +338,7 @@ static void write_media_cp(struct gatt_db_attribute *attrib, > } > > rsp.op = op; > + rfu_op = !op; > > cmd = mcs_get_command(op); > if (!cmd || !(cmd->support & mcs_get_supported(mcs))) { > @@ -370,7 +372,7 @@ respond: > ret, rsp.result); > > gatt_db_attribute_write_result(attrib, id, ret); > - if (!rsp.op) > + if (!rsp.op && !rfu_op) > return; > > /* Make state transition immediately if command was successful and has > diff --git a/unit/test-mcp.c b/unit/test-mcp.c > index 6331c6c99..21997915d 100644 > --- a/unit/test-mcp.c > +++ b/unit/test-mcp.c > @@ -2057,6 +2057,19 @@ static void testgroup_sr_mcp(void) > } > > > +#define GMCS_SR_SPE_BI_01_C \ > + WRITE_NORESP_CHRC(CP, 0x00), \ > + NOTIFY_CHRC(CP, 0x00, 0x02 /* not supp */) > + > +static void testgroup_sr_spe(void) > +{ > + define_test("GMCS/SR/SPE/BI-01-C [Media Control Point - Opcode not " > + "Supported]", > + test_setup_server, test_server, > + &cfg_sggit_gmcs, GMCS_SR_SPE_BI_01_C); > +} > + > + > static void sr_spn_value(struct test_data *data, struct iovec *buf, size_t size, > uint16_t uuid) > { > @@ -2132,6 +2145,7 @@ int main(int argc, char *argv[]) > testgroup_cl_extra(); > testgroup_sr_sggit(); > testgroup_sr_mcp(); > + testgroup_sr_spe(); > testgroup_sr_spn(); > > return tester_run(); > -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-09-04 20:21 UTC | newest] Thread overview: 15+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-31 6:11 [BlueZ PATCH 0/3] Add MCS fast seek and track position write raghu447 2026-08-31 6:11 ` [BlueZ PATCH 1/3] profiles/audio: Support MCS fast seeking raghu447 2026-09-02 15:31 ` Luiz Augusto von Dentz 2026-08-31 6:11 ` [BlueZ PATCH 2/3] profiles/audio: Support MCS track position writes raghu447 2026-09-02 15:35 ` Luiz Augusto von Dentz 2026-09-03 8:19 ` Bastien Nocera 2026-09-04 16:53 ` [PATCH 0/4] Add MCS fast seek and track position write support raghu447 2026-09-04 16:53 ` [PATCH 1/4] profiles/audio: Support MCS track position writes raghu447 2026-09-04 17:51 ` Add MCS fast seek and track position write support bluez.test.bot 2026-09-04 16:53 ` [PATCH 2/4] profiles/audio: Support MCS fast seeking raghu447 2026-09-04 16:53 ` [PATCH 3/4] shared/mcp: Notify unsupported RFU opcodes raghu447 2026-09-04 16:53 ` [PATCH 4/4] unit/test-mcp: Test unsupported RFU opcode raghu447 2026-09-04 20:20 ` [PATCH 0/4] Add MCS fast seek and track position write support patchwork-bot+bluetooth 2026-08-31 6:11 ` [BlueZ PATCH 3/3] shared/mcp: Notify unsupported RFU opcodes raghu447 2026-09-02 15:36 ` Luiz Augusto von Dentz
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).