mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-01-26 06:07:53 +00:00
Compare commits
13 Commits
56cb8076db
...
1840f7c177
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1840f7c177 | ||
|
|
bc53b6b343 | ||
|
|
332e35039d | ||
|
|
254620676f | ||
|
|
78f16bc04b | ||
|
|
2b5d21da5b | ||
|
|
2d6a7d2186 | ||
|
|
db7c74a042 | ||
|
|
9fa0de16e9 | ||
|
|
f030e1dc03 | ||
|
|
88f8eda1e9 | ||
|
|
9ad6219db3 | ||
|
|
e29d851d2c |
@ -1171,6 +1171,15 @@ in a platform-specific way. See `tests/examples/bt-pinephone.lua` in WirePlumber
|
||||
Do not enable this setting if you don't know what all this means, as it won't work.
|
||||
\endparblock
|
||||
|
||||
@PAR@ monitor-prop bluez5.hw-offload-datapath # integer
|
||||
\parblock
|
||||
HFP/HSP hardware offload data path ID (default: 0).
|
||||
|
||||
This feature configures the SCO hardware‑offload data path for HFP/HSP using the Bluetooth
|
||||
SIG–specified procedure. It is intended for advanced setups and vendor integrations. Do not
|
||||
edit this unless required; incorrect values can disable SCO offload.
|
||||
\endparblock
|
||||
|
||||
@PAR@ monitor-prop bluez5.a2dp.opus.pro.channels = 3 # integer
|
||||
PipeWire Opus Pro audio profile channel count.
|
||||
|
||||
|
||||
@ -1692,6 +1692,59 @@ static int device_disable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_devic
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Synchronize IEC958 digital output/input switch states.
|
||||
*
|
||||
* IEC958 switches default to muted in ALSA drivers. Cards with multiple
|
||||
* HDMI/DP outputs have indexed switches (IEC958,0 IEC958,1 etc). We enable
|
||||
* all switches since we cannot reliably map device numbers to indices.
|
||||
*/
|
||||
static void sync_iec958_controls(pa_alsa_device *d)
|
||||
{
|
||||
snd_mixer_t *mixer_handle;
|
||||
snd_mixer_elem_t *elem;
|
||||
pa_card *impl;
|
||||
int r;
|
||||
|
||||
mixer_handle = d->mixer_handle;
|
||||
|
||||
/* Pro-audio profiles don't have per-device mixers, use card mixer */
|
||||
if (!mixer_handle) {
|
||||
impl = d->card;
|
||||
if (!impl || impl->card.index == ACP_INVALID_INDEX)
|
||||
return;
|
||||
|
||||
mixer_handle = pa_alsa_open_mixer(impl->ucm.mixers, impl->card.index, true);
|
||||
if (!mixer_handle)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable all IEC958 switches */
|
||||
for (elem = snd_mixer_first_elem(mixer_handle); elem;
|
||||
elem = snd_mixer_elem_next(elem)) {
|
||||
|
||||
if (snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE)
|
||||
continue;
|
||||
|
||||
const char *name = snd_mixer_selem_get_name(elem);
|
||||
if (!name || !pa_startswith(name, "IEC958"))
|
||||
continue;
|
||||
|
||||
if (snd_mixer_selem_has_playback_switch(elem)) {
|
||||
r = snd_mixer_selem_set_playback_switch_all(elem, 1);
|
||||
if (r < 0)
|
||||
pa_log_warn("Failed to enable IEC958 playback switch: %s",
|
||||
pa_alsa_strerror(r));
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_has_capture_switch(elem)) {
|
||||
r = snd_mixer_selem_set_capture_switch_all(elem, 1);
|
||||
if (r < 0)
|
||||
pa_log_warn("Failed to enable IEC958 capture switch: %s",
|
||||
pa_alsa_strerror(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int device_enable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_device *dev)
|
||||
{
|
||||
const char *mod_name;
|
||||
@ -1783,6 +1836,9 @@ static int device_enable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_device
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable IEC958 switches for digital outputs */
|
||||
sync_iec958_controls(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2283,6 +2339,7 @@ int acp_device_set_port(struct acp_device *dev, uint32_t port_index, uint32_t fl
|
||||
pa_sink_suspend(s, false, PA_SUSPEND_UNAVAILABLE);
|
||||
#endif
|
||||
}
|
||||
sync_iec958_controls(d);
|
||||
if (impl->events && impl->events->port_changed)
|
||||
impl->events->port_changed(impl->user_data,
|
||||
old ? old->port.index : 0, p->port.index);
|
||||
|
||||
@ -63,6 +63,9 @@ SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.bluez5.native");
|
||||
|
||||
#define RFCOMM_MESSAGE_MAX_LENGTH 256
|
||||
|
||||
#define BT_CODEC_CVSD 0x02
|
||||
#define BT_CODEC_MSBC 0x05
|
||||
|
||||
enum {
|
||||
HFP_AG_INITIAL_CODEC_SETUP_NONE = 0,
|
||||
HFP_AG_INITIAL_CODEC_SETUP_SEND,
|
||||
@ -112,6 +115,7 @@ struct impl {
|
||||
int hfp_default_speaker_volume;
|
||||
|
||||
struct spa_source sco;
|
||||
unsigned int hfphsp_sco_datapath;
|
||||
|
||||
const struct spa_bt_quirks *quirks;
|
||||
|
||||
@ -297,6 +301,33 @@ static const struct media_codec *codec_list_best(struct impl *backend, struct sp
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sco_offload_btcodec(struct impl *backend, int sock, bool msbc)
|
||||
{
|
||||
int err;
|
||||
char buffer[255];
|
||||
struct bt_codecs *codecs;
|
||||
|
||||
if (backend->hfphsp_sco_datapath == HFP_SCO_DEFAULT_DATAPATH)
|
||||
return;
|
||||
|
||||
spa_log_info(backend->log, "sock(%d) msbc(%d)", sock, msbc);
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
codecs = (void *)buffer;
|
||||
if (msbc)
|
||||
codecs->codecs[0].id = BT_CODEC_MSBC;
|
||||
else
|
||||
codecs->codecs[0].id = BT_CODEC_CVSD;
|
||||
codecs->num_codecs = 1;
|
||||
codecs->codecs[0].data_path_id = backend->hfphsp_sco_datapath;
|
||||
|
||||
err = setsockopt(sock, SOL_BLUETOOTH, BT_CODEC, codecs, sizeof(buffer));
|
||||
if (err < 0)
|
||||
spa_log_error(backend->log, "ERROR: %s (%d)", strerror(errno), errno);
|
||||
else
|
||||
spa_log_info(backend->log, "set offload codec succeeded");
|
||||
}
|
||||
|
||||
static DBusHandlerResult profile_release(DBusConnection *conn, DBusMessage *m, void *userdata)
|
||||
{
|
||||
if (!reply_with_error(conn, m, BLUEZ_PROFILE_INTERFACE ".Error.NotImplemented", "Method not implemented"))
|
||||
@ -2595,6 +2626,8 @@ static int sco_create_socket(struct impl *backend, struct spa_bt_adapter *adapte
|
||||
}
|
||||
}
|
||||
|
||||
sco_offload_btcodec(backend, sock, transparent);
|
||||
|
||||
return spa_steal_fd(sock);
|
||||
}
|
||||
|
||||
@ -4101,6 +4134,14 @@ static void parse_hfp_default_volumes(struct impl *backend, const struct spa_dic
|
||||
backend->hfp_default_speaker_volume = SPA_BT_VOLUME_HS_MAX;
|
||||
}
|
||||
|
||||
static void parse_sco_datapath(struct impl *backend, const struct spa_dict *info)
|
||||
{
|
||||
backend->hfphsp_sco_datapath = HFP_SCO_DEFAULT_DATAPATH;
|
||||
|
||||
spa_atou32(spa_dict_lookup(info, "bluez5.hw-offload-datapath"),
|
||||
&backend->hfphsp_sco_datapath, 10);
|
||||
}
|
||||
|
||||
static const struct spa_bt_backend_implementation backend_impl = {
|
||||
SPA_VERSION_BT_BACKEND_IMPLEMENTATION,
|
||||
.free = backend_native_free,
|
||||
@ -4163,6 +4204,7 @@ struct spa_bt_backend *backend_native_new(struct spa_bt_monitor *monitor,
|
||||
parse_hfp_disable_nrec(backend, info);
|
||||
parse_hfp_default_volumes(backend, info);
|
||||
parse_hfp_pts(backend, info);
|
||||
parse_sco_datapath(backend, info);
|
||||
|
||||
#ifdef HAVE_BLUEZ_5_BACKEND_HSP_NATIVE
|
||||
if (!dbus_connection_register_object_path(backend->conn,
|
||||
|
||||
@ -135,7 +135,8 @@ extern "C" {
|
||||
#define PROFILE_HFP_AG "/Profile/HFPAG"
|
||||
#define PROFILE_HFP_HF "/Profile/HFPHF"
|
||||
|
||||
#define HSP_HS_DEFAULT_CHANNEL 3
|
||||
#define HSP_HS_DEFAULT_CHANNEL 3
|
||||
#define HFP_SCO_DEFAULT_DATAPATH 0
|
||||
|
||||
#define SOURCE_ID_BLUETOOTH 0x1 /* Bluetooth SIG */
|
||||
#define SOURCE_ID_USB 0x2 /* USB Implementer's Forum */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user