mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
bluez5: implement basic CIND/CIEV support in backend-native
Set HFP call indicator based on whether transport is acquired or not.
This commit is contained in:
parent
113ab31613
commit
f92b0eee56
1 changed files with 42 additions and 2 deletions
|
|
@ -137,6 +137,8 @@ struct rfcomm {
|
||||||
unsigned int msbc_supported_by_hfp:1;
|
unsigned int msbc_supported_by_hfp:1;
|
||||||
unsigned int hfp_ag_switching_codec:1;
|
unsigned int hfp_ag_switching_codec:1;
|
||||||
unsigned int hfp_ag_initial_codec_setup:2;
|
unsigned int hfp_ag_initial_codec_setup:2;
|
||||||
|
unsigned int cind_call_active:1;
|
||||||
|
unsigned int cind_call_notify:1;
|
||||||
enum hfp_hf_state hf_state;
|
enum hfp_hf_state hf_state;
|
||||||
enum hsp_hs_state hs_state;
|
enum hsp_hs_state hs_state;
|
||||||
unsigned int codec;
|
unsigned int codec;
|
||||||
|
|
@ -676,6 +678,22 @@ static void process_hfp_hf_indicator(struct rfcomm *rfcomm, unsigned int indicat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rfcomm_hfp_ag_set_cind(struct rfcomm *rfcomm, bool call_active)
|
||||||
|
{
|
||||||
|
if (rfcomm->profile != SPA_BT_PROFILE_HFP_HF)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (call_active == rfcomm->cind_call_active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rfcomm->cind_call_active = call_active;
|
||||||
|
|
||||||
|
if (!rfcomm->cind_call_notify)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rfcomm_send_reply(rfcomm, "+CIEV: 2,%d", rfcomm->cind_call_active);
|
||||||
|
}
|
||||||
|
|
||||||
static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf)
|
static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf)
|
||||||
{
|
{
|
||||||
struct impl *backend = rfcomm->backend;
|
struct impl *backend = rfcomm->backend;
|
||||||
|
|
@ -762,12 +780,20 @@ static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf)
|
||||||
rfcomm_send_reply(rfcomm, "+CIND:(\"service\",(0-1)),(\"call\",(0-1)),(\"callsetup\",(0-3)),(\"callheld\",(0-2))");
|
rfcomm_send_reply(rfcomm, "+CIND:(\"service\",(0-1)),(\"call\",(0-1)),(\"callsetup\",(0-3)),(\"callheld\",(0-2))");
|
||||||
rfcomm_send_reply(rfcomm, "OK");
|
rfcomm_send_reply(rfcomm, "OK");
|
||||||
} else if (spa_strstartswith(buf, "AT+CIND?")) {
|
} else if (spa_strstartswith(buf, "AT+CIND?")) {
|
||||||
rfcomm_send_reply(rfcomm, "+CIND: 0,0,0,0");
|
rfcomm_send_reply(rfcomm, "+CIND: 0,%d,0,0", rfcomm->cind_call_active);
|
||||||
rfcomm_send_reply(rfcomm, "OK");
|
rfcomm_send_reply(rfcomm, "OK");
|
||||||
} else if (spa_strstartswith(buf, "AT+CMER")) {
|
} else if (spa_strstartswith(buf, "AT+CMER")) {
|
||||||
|
int mode, keyp, disp, ind;
|
||||||
|
|
||||||
rfcomm->slc_configured = true;
|
rfcomm->slc_configured = true;
|
||||||
rfcomm_send_reply(rfcomm, "OK");
|
rfcomm_send_reply(rfcomm, "OK");
|
||||||
|
|
||||||
|
rfcomm->cind_call_active = false;
|
||||||
|
if (sscanf(buf, "AT+CMER= %d , %d , %d , %d", &mode, &keyp, &disp, &ind) == 4)
|
||||||
|
rfcomm->cind_call_notify = ind ? true : false;
|
||||||
|
else
|
||||||
|
rfcomm->cind_call_notify = false;
|
||||||
|
|
||||||
/* switch codec to mSBC by sending unsolicited +BCS message */
|
/* switch codec to mSBC by sending unsolicited +BCS message */
|
||||||
if (rfcomm->codec_negotiation_supported && rfcomm->msbc_supported_by_hfp) {
|
if (rfcomm->codec_negotiation_supported && rfcomm->msbc_supported_by_hfp) {
|
||||||
spa_log_debug(backend->log, "RFCOMM initial codec setup");
|
spa_log_debug(backend->log, "RFCOMM initial codec setup");
|
||||||
|
|
@ -785,7 +811,6 @@ static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf)
|
||||||
rfcomm_emit_volume_changed(rfcomm, -1, SPA_BT_VOLUME_INVALID);
|
rfcomm_emit_volume_changed(rfcomm, -1, SPA_BT_VOLUME_INVALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!rfcomm->slc_configured) {
|
} else if (!rfcomm->slc_configured) {
|
||||||
spa_log_warn(backend->log, "RFCOMM receive command before SLC completed: %s", buf);
|
spa_log_warn(backend->log, "RFCOMM receive command before SLC completed: %s", buf);
|
||||||
rfcomm_send_reply(rfcomm, "ERROR");
|
rfcomm_send_reply(rfcomm, "ERROR");
|
||||||
|
|
@ -829,6 +854,11 @@ static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf)
|
||||||
rfcomm_send_reply(rfcomm, "OK");
|
rfcomm_send_reply(rfcomm, "OK");
|
||||||
if (was_switching_codec)
|
if (was_switching_codec)
|
||||||
spa_bt_device_emit_codec_switched(rfcomm->device, 0);
|
spa_bt_device_emit_codec_switched(rfcomm->device, 0);
|
||||||
|
} else if (spa_strstartswith(buf, "AT+BIA=")) {
|
||||||
|
/* We only support 'call' indicator, which HFP 4.35.1 defines as
|
||||||
|
always active (assuming CMER enabled it), so we don't need to
|
||||||
|
parse anything here. */
|
||||||
|
rfcomm_send_reply(rfcomm, "OK");
|
||||||
} else if (sscanf(buf, "AT+VGM=%u", &gain) == 1) {
|
} else if (sscanf(buf, "AT+VGM=%u", &gain) == 1) {
|
||||||
if (gain <= SPA_BT_VOLUME_HS_MAX) {
|
if (gain <= SPA_BT_VOLUME_HS_MAX) {
|
||||||
if (!rfcomm->broken_mic_hw_volume)
|
if (!rfcomm->broken_mic_hw_volume)
|
||||||
|
|
@ -1172,12 +1202,17 @@ fail_close:
|
||||||
static int sco_acquire_cb(void *data, bool optional)
|
static int sco_acquire_cb(void *data, bool optional)
|
||||||
{
|
{
|
||||||
struct spa_bt_transport *t = data;
|
struct spa_bt_transport *t = data;
|
||||||
|
struct transport_data *td = t->user_data;
|
||||||
struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this);
|
struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this);
|
||||||
int sock;
|
int sock;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
|
|
||||||
spa_log_debug(backend->log, "transport %p: enter sco_acquire_cb", t);
|
spa_log_debug(backend->log, "transport %p: enter sco_acquire_cb", t);
|
||||||
|
|
||||||
|
#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
|
||||||
|
rfcomm_hfp_ag_set_cind(td->rfcomm, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (optional || t->fd > 0)
|
if (optional || t->fd > 0)
|
||||||
sock = t->fd;
|
sock = t->fd;
|
||||||
else
|
else
|
||||||
|
|
@ -1217,10 +1252,15 @@ fail:
|
||||||
static int sco_release_cb(void *data)
|
static int sco_release_cb(void *data)
|
||||||
{
|
{
|
||||||
struct spa_bt_transport *t = data;
|
struct spa_bt_transport *t = data;
|
||||||
|
struct transport_data *td = t->user_data;
|
||||||
struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this);
|
struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this);
|
||||||
|
|
||||||
spa_log_info(backend->log, "Transport %s released", t->path);
|
spa_log_info(backend->log, "Transport %s released", t->path);
|
||||||
|
|
||||||
|
#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
|
||||||
|
rfcomm_hfp_ag_set_cind(td->rfcomm, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (t->sco_io) {
|
if (t->sco_io) {
|
||||||
spa_bt_sco_io_destroy(t->sco_io);
|
spa_bt_sco_io_destroy(t->sco_io);
|
||||||
t->sco_io = NULL;
|
t->sco_io = NULL;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue