Skip to content

Commit

Permalink
Fix RFCOMM thread bug introduced in 0afd202
Browse files Browse the repository at this point in the history
  • Loading branch information
arkq committed Mar 4, 2019
1 parent b3078b2 commit 4fbe6ee
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 84 deletions.
1 change: 1 addition & 0 deletions src/ba-adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

#include "bluealsa.h"

Expand Down
118 changes: 52 additions & 66 deletions src/ba-transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,63 +40,54 @@ static int io_thread_create(struct ba_transport *t) {
void *(*routine)(void *) = NULL;
int ret;

switch (t->type.profile) {
case BA_TRANSPORT_PROFILE_A2DP_SOURCE:
switch (t->type.codec) {
case A2DP_CODEC_SBC:
routine = io_thread_a2dp_source_sbc;
break;
if (t->type.profile & BA_TRANSPORT_PROFILE_RFCOMM)
routine = rfcomm_thread;
else if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO)
routine = io_thread_sco;
else if (t->type.profile & BA_TRANSPORT_PROFILE_A2DP_SOURCE)
switch (t->type.codec) {
case A2DP_CODEC_SBC:
routine = io_thread_a2dp_source_sbc;
break;
#if ENABLE_MPEG
case A2DP_CODEC_MPEG12:
break;
case A2DP_CODEC_MPEG12:
break;
#endif
#if ENABLE_AAC
case A2DP_CODEC_MPEG24:
routine = io_thread_a2dp_source_aac;
break;
case A2DP_CODEC_MPEG24:
routine = io_thread_a2dp_source_aac;
break;
#endif
#if ENABLE_APTX
case A2DP_CODEC_VENDOR_APTX:
routine = io_thread_a2dp_source_aptx;
break;
case A2DP_CODEC_VENDOR_APTX:
routine = io_thread_a2dp_source_aptx;
break;
#endif
#if ENABLE_LDAC
case A2DP_CODEC_VENDOR_LDAC:
routine = io_thread_a2dp_source_ldac;
break;
case A2DP_CODEC_VENDOR_LDAC:
routine = io_thread_a2dp_source_ldac;
break;
#endif
default:
warn("Codec not supported: %u", t->type.codec);
}
break;
case BA_TRANSPORT_PROFILE_A2DP_SINK:
switch (t->type.codec) {
case A2DP_CODEC_SBC:
routine = io_thread_a2dp_sink_sbc;
break;
default:
warn("Codec not supported: %u", t->type.codec);
}
else if (t->type.profile & BA_TRANSPORT_PROFILE_A2DP_SINK)
switch (t->type.codec) {
case A2DP_CODEC_SBC:
routine = io_thread_a2dp_sink_sbc;
break;
#if ENABLE_MPEG
case A2DP_CODEC_MPEG12:
break;
case A2DP_CODEC_MPEG12:
break;
#endif
#if ENABLE_AAC
case A2DP_CODEC_MPEG24:
routine = io_thread_a2dp_sink_aac;
break;
case A2DP_CODEC_MPEG24:
routine = io_thread_a2dp_sink_aac;
break;
#endif
default:
warn("Codec not supported: %u", t->type.codec);
}
break;
case BA_TRANSPORT_PROFILE_HFP_HF:
case BA_TRANSPORT_PROFILE_HFP_AG:
case BA_TRANSPORT_PROFILE_HSP_HS:
case BA_TRANSPORT_PROFILE_HSP_AG:
routine = io_thread_sco;
break;
case BA_TRANSPORT_PROFILE_RFCOMM:
routine = rfcomm_thread;
break;
}
default:
warn("Codec not supported: %u", t->type.codec);
}

if (routine == NULL)
return -1;
Expand Down Expand Up @@ -222,7 +213,8 @@ struct ba_transport *transport_new_rfcomm(
gchar *dbus_path_sco = NULL;
struct ba_transport *t, *t_sco;

struct ba_transport_type ttype = { .profile = BA_TRANSPORT_PROFILE_RFCOMM };
struct ba_transport_type ttype = {
.profile = type.profile | BA_TRANSPORT_PROFILE_RFCOMM };
if ((t = transport_new(device, ttype, dbus_owner, dbus_path)) == NULL)
goto fail;

Expand Down Expand Up @@ -319,34 +311,28 @@ void ba_transport_free(struct ba_transport *t) {

unsigned int pcm_type = BA_PCM_TYPE_NULL;

/* free type-specific resources */
switch (t->type.profile) {
case BA_TRANSPORT_PROFILE_A2DP_SOURCE:
case BA_TRANSPORT_PROFILE_A2DP_SINK:
pcm_type = BA_PCM_TYPE_A2DP | (t->type.profile == BA_TRANSPORT_PROFILE_A2DP_SOURCE ?
BA_PCM_STREAM_PLAYBACK : BA_PCM_STREAM_CAPTURE);
transport_release_pcm(&t->a2dp.pcm);
pthread_mutex_destroy(&t->a2dp.drained_mtx);
pthread_cond_destroy(&t->a2dp.drained);
free(t->a2dp.cconfig);
break;
case BA_TRANSPORT_PROFILE_RFCOMM:
/* free profile-specific resources */
if (t->type.profile & BA_TRANSPORT_PROFILE_RFCOMM) {
memset(&t->d->battery, 0, sizeof(t->d->battery));
memset(&t->d->xapl, 0, sizeof(t->d->xapl));
ba_transport_free(t->rfcomm.sco);
break;
case BA_TRANSPORT_PROFILE_HFP_HF:
case BA_TRANSPORT_PROFILE_HFP_AG:
case BA_TRANSPORT_PROFILE_HSP_HS:
case BA_TRANSPORT_PROFILE_HSP_AG:
}
else if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO) {
pcm_type = BA_PCM_TYPE_SCO | BA_PCM_STREAM_PLAYBACK | BA_PCM_STREAM_CAPTURE;
pthread_mutex_destroy(&t->sco.spk_drained_mtx);
pthread_cond_destroy(&t->sco.spk_drained);
transport_release_pcm(&t->sco.spk_pcm);
transport_release_pcm(&t->sco.mic_pcm);
if (t->sco.rfcomm != NULL)
t->sco.rfcomm->rfcomm.sco = NULL;
break;
}
else if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_A2DP) {
pcm_type = BA_PCM_TYPE_A2DP | (t->type.profile == BA_TRANSPORT_PROFILE_A2DP_SOURCE ?
BA_PCM_STREAM_PLAYBACK : BA_PCM_STREAM_CAPTURE);
transport_release_pcm(&t->a2dp.pcm);
pthread_mutex_destroy(&t->a2dp.drained_mtx);
pthread_cond_destroy(&t->a2dp.drained);
free(t->a2dp.cconfig);
}

/* detach transport from the device */
Expand Down Expand Up @@ -433,7 +419,7 @@ unsigned int transport_get_channels(const struct ba_transport *t) {
#endif
}

if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO)
if (IS_BA_TRANSPORT_PROFILE_SCO(t->type.profile))
return 1;

/* the number of channels is unspecified */
Expand Down Expand Up @@ -538,7 +524,7 @@ unsigned int transport_get_sampling(const struct ba_transport *t) {
#endif
}

if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO)
if (IS_BA_TRANSPORT_PROFILE_SCO(t->type.profile))
switch (t->type.codec) {
case HFP_CODEC_UNDEFINED:
break;
Expand Down
18 changes: 10 additions & 8 deletions src/ba-transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@
#define BA_TRANSPORT_PROFILE_HSP_AG (2 << 4)
#define BA_TRANSPORT_PROFILE_RFCOMM (1 << 6)

#define BA_TRANSPORT_PROFILE_MASK_A2DP (\
BA_TRANSPORT_PROFILE_A2DP_SOURCE | BA_TRANSPORT_PROFILE_A2DP_SINK)
#define BA_TRANSPORT_PROFILE_MASK_HFP (\
BA_TRANSPORT_PROFILE_HFP_HF | BA_TRANSPORT_PROFILE_HFP_AG)
#define BA_TRANSPORT_PROFILE_MASK_HSP (\
BA_TRANSPORT_PROFILE_HSP_HS | BA_TRANSPORT_PROFILE_HSP_AG)
#define BA_TRANSPORT_PROFILE_MASK_SCO (\
BA_TRANSPORT_PROFILE_MASK_HFP | BA_TRANSPORT_PROFILE_MASK_HSP)
#define BA_TRANSPORT_PROFILE_MASK_A2DP \
(BA_TRANSPORT_PROFILE_A2DP_SOURCE | BA_TRANSPORT_PROFILE_A2DP_SINK)
#define BA_TRANSPORT_PROFILE_MASK_HFP \
(BA_TRANSPORT_PROFILE_HFP_HF | BA_TRANSPORT_PROFILE_HFP_AG)
#define BA_TRANSPORT_PROFILE_MASK_HSP \
(BA_TRANSPORT_PROFILE_HSP_HS | BA_TRANSPORT_PROFILE_HSP_AG)
#define BA_TRANSPORT_PROFILE_MASK_SCO \
(BA_TRANSPORT_PROFILE_MASK_HFP | BA_TRANSPORT_PROFILE_MASK_HSP)
#define IS_BA_TRANSPORT_PROFILE_SCO(p) \
(((p) & BA_TRANSPORT_PROFILE_MASK_SCO) == (p))

struct ba_transport_type {
/* Selected profile and audio codec. For A2DP vendor codecs the upper byte
Expand Down
12 changes: 6 additions & 6 deletions src/ctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ static int ctl_lookup_transport(struct ba_adapter *a, const bdaddr_t *addr,
return 0;
continue;
case BA_PCM_TYPE_SCO:
if ((*t)->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO)
if (IS_BA_TRANSPORT_PROFILE_SCO((*t)->type.profile))
return 0;
continue;
case BA_PCM_TYPE_RFCOMM:
if ((*t)->type.profile == BA_TRANSPORT_PROFILE_RFCOMM)
if ((*t)->type.profile & BA_TRANSPORT_PROFILE_RFCOMM)
return 0;
continue;
}
Expand All @@ -119,7 +119,7 @@ static struct ba_pcm *ctl_lookup_pcm(struct ba_transport *t, uint8_t type, int c
if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_A2DP)
if (t->a2dp.pcm.client == client)
return &t->a2dp.pcm;
if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO) {
if (IS_BA_TRANSPORT_PROFILE_SCO(t->type.profile)) {
if (type & BA_PCM_STREAM_PLAYBACK)
if (t->sco.spk_pcm.client == client)
return &t->sco.spk_pcm;
Expand Down Expand Up @@ -150,7 +150,7 @@ static struct ba_msg_transport *ctl_transport(const struct ba_transport *t,
transport->delay = t->a2dp.delay;
}

if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO) {
if (IS_BA_TRANSPORT_PROFILE_SCO(t->type.profile)) {
transport->type = BA_PCM_TYPE_SCO | BA_PCM_STREAM_PLAYBACK | BA_PCM_STREAM_CAPTURE;
transport->ch1_muted = t->sco.spk_muted;
transport->ch1_volume = t->sco.spk_gain;
Expand Down Expand Up @@ -336,7 +336,7 @@ static void ctl_thread_cmd_pcm_open(struct ba_ctl *ctl, struct ba_request *req,

pthread_mutex_lock(&t->mutex);

if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO &&
if (IS_BA_TRANSPORT_PROFILE_SCO(t->type.profile) &&
t->type.codec == HFP_CODEC_UNDEFINED) {
status.code = BA_STATUS_CODE_CODEC_NOT_SELECTED;
goto final;
Expand Down Expand Up @@ -552,7 +552,7 @@ static void *ctl_thread(void *arg) {
transport_send_signal(t, TRANSPORT_PCM_CLOSE);
}
}
if (t->type.profile & BA_TRANSPORT_PROFILE_MASK_SCO) {
if (IS_BA_TRANSPORT_PROFILE_SCO(t->type.profile)) {
if (t->sco.spk_pcm.client == fd) {
transport_release_pcm(&t->sco.spk_pcm);
transport_send_signal(t, TRANSPORT_PCM_CLOSE);
Expand Down
4 changes: 2 additions & 2 deletions src/rfcomm.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ void *rfcomm_thread(void *arg) {
goto ioerror;
}

if (t->type.profile == BA_TRANSPORT_PROFILE_HFP_HF)
if (t->type.profile & BA_TRANSPORT_PROFILE_HFP_HF)
switch (conn.state) {
case HFP_DISCONNECTED:
sprintf(tmp, "%u", config.hfp.features_rfcomm_hf);
Expand Down Expand Up @@ -661,7 +661,7 @@ void *rfcomm_thread(void *arg) {
BA_PCM_TYPE_SCO | BA_PCM_STREAM_PLAYBACK | BA_PCM_STREAM_CAPTURE);
}

if (t->type.profile == BA_TRANSPORT_PROFILE_HFP_AG)
if (t->type.profile & BA_TRANSPORT_PROFILE_HFP_AG)
switch (conn.state) {
case HFP_DISCONNECTED:
case HFP_SLC_BRSF_SET:
Expand Down
10 changes: 8 additions & 2 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,14 @@ const char *ba_transport_type_to_string(struct ba_transport_type type) {
return "HSP Headset";
case BA_TRANSPORT_PROFILE_HSP_AG:
return "HSP Audio Gateway";
case BA_TRANSPORT_PROFILE_RFCOMM:
return "RFCOMM";
case BA_TRANSPORT_PROFILE_RFCOMM | BA_TRANSPORT_PROFILE_HFP_HF:
return "RFCOMM: HFP Hands-Free";
case BA_TRANSPORT_PROFILE_RFCOMM | BA_TRANSPORT_PROFILE_HFP_AG:
return "RFCOMM: HFP Audio Gateway";
case BA_TRANSPORT_PROFILE_RFCOMM | BA_TRANSPORT_PROFILE_HSP_HS:
return "RFCOMM: HSP Headset";
case BA_TRANSPORT_PROFILE_RFCOMM | BA_TRANSPORT_PROFILE_HSP_AG:
return "RFCOMM: HSP Audio Gateway";
}
return "N/A";
}
Expand Down

0 comments on commit 4fbe6ee

Please sign in to comment.