Bluetooth: HFP_AG: Protect the consistency of AG state/value
Use hfp_ag_lock/hfp_ag_unlock to protect the consistency of AG state or value. Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
This commit is contained in:
parent
5da8916ad5
commit
fa6df6a51a
1 changed files with 188 additions and 33 deletions
|
@ -135,7 +135,9 @@ static void bt_hfp_ag_set_state(struct bt_hfp_ag *ag, bt_hfp_state_t state)
|
||||||
{
|
{
|
||||||
LOG_DBG("update state %p, old %d -> new %d", ag, ag->state, state);
|
LOG_DBG("update state %p, old %d -> new %d", ag, ag->state, state);
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
ag->state = state;
|
ag->state = state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case BT_HFP_DISCONNECTED:
|
case BT_HFP_DISCONNECTED:
|
||||||
|
@ -162,9 +164,14 @@ static void bt_hfp_ag_set_state(struct bt_hfp_ag *ag, bt_hfp_state_t state)
|
||||||
|
|
||||||
static void bt_hfp_ag_set_call_state(struct bt_hfp_ag *ag, bt_hfp_call_state_t call_state)
|
static void bt_hfp_ag_set_call_state(struct bt_hfp_ag *ag, bt_hfp_call_state_t call_state)
|
||||||
{
|
{
|
||||||
|
bt_hfp_state_t state;
|
||||||
|
|
||||||
LOG_DBG("update call state %p, old %d -> new %d", ag, ag->call_state, call_state);
|
LOG_DBG("update call state %p, old %d -> new %d", ag, ag->call_state, call_state);
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
ag->call_state = call_state;
|
ag->call_state = call_state;
|
||||||
|
state = ag->state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
switch (call_state) {
|
switch (call_state) {
|
||||||
case BT_HFP_CALL_TERMINATE:
|
case BT_HFP_CALL_TERMINATE:
|
||||||
|
@ -192,7 +199,7 @@ static void bt_hfp_ag_set_call_state(struct bt_hfp_ag *ag, bt_hfp_call_state_t c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->state == BT_HFP_DISCONNECTING) {
|
if (state == BT_HFP_DISCONNECTING) {
|
||||||
int err = bt_rfcomm_dlc_disconnect(&ag->rfcomm_dlc);
|
int err = bt_rfcomm_dlc_disconnect(&ag->rfcomm_dlc);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -387,7 +394,9 @@ static int bt_hfp_ag_brsf_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
ag->hf_features = hf_features;
|
ag->hf_features = hf_features;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
return hfp_ag_send_data(ag, NULL, NULL, "\r\n+BRSF:%d\r\n", ag->ag_features);
|
return hfp_ag_send_data(ag, NULL, NULL, "\r\n+BRSF:%d\r\n", ag->ag_features);
|
||||||
}
|
}
|
||||||
|
@ -402,10 +411,13 @@ static int bt_hfp_ag_bac_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (!(ag->hf_features & BT_HFP_HF_FEATURE_CODEC_NEG) ||
|
if (!(ag->hf_features & BT_HFP_HF_FEATURE_CODEC_NEG) ||
|
||||||
!(ag->ag_features & BT_HFP_AG_FEATURE_CODEC_NEG)) {
|
!(ag->ag_features & BT_HFP_AG_FEATURE_CODEC_NEG)) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
while (err == 0) {
|
while (err == 0) {
|
||||||
err = get_number(buf, &codec);
|
err = get_number(buf, &codec);
|
||||||
|
@ -424,7 +436,9 @@ static int bt_hfp_ag_bac_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
ag->hf_codec_ids = codec_ids;
|
ag->hf_codec_ids = codec_ids;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (bt_ag && bt_ag->codec) {
|
if (bt_ag && bt_ag->codec) {
|
||||||
bt_ag->codec(ag, ag->hf_codec_ids);
|
bt_ag->codec(ag, ag->hf_codec_ids);
|
||||||
|
@ -487,7 +501,13 @@ static int bt_hfp_ag_cind_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
|
|
||||||
static void bt_hfp_ag_set_in_band_ring(struct bt_hfp_ag *ag, void *user_data)
|
static void bt_hfp_ag_set_in_band_ring(struct bt_hfp_ag *ag, void *user_data)
|
||||||
{
|
{
|
||||||
if ((ag->ag_features & BT_HFP_AG_FEATURE_INBAND_RINGTONE) != 0) {
|
bool is_inband_ringtone;
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
|
is_inband_ringtone = (ag->ag_features & BT_HFP_AG_FEATURE_INBAND_RINGTONE) ? true : false;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
|
if (is_inband_ringtone) {
|
||||||
int err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BSIR:1\r\n");
|
int err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BSIR:1\r\n");
|
||||||
|
|
||||||
atomic_set_bit_to(ag->flags, BT_HFP_AG_INBAND_RING, err == 0);
|
atomic_set_bit_to(ag->flags, BT_HFP_AG_INBAND_RING, err == 0);
|
||||||
|
@ -555,17 +575,22 @@ static int bt_hfp_ag_bind_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
char *data;
|
char *data;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (!((ag->ag_features & BT_HFP_AG_FEATURE_HF_IND) &&
|
if (!((ag->ag_features & BT_HFP_AG_FEATURE_HF_IND) &&
|
||||||
(ag->hf_features & BT_HFP_HF_FEATURE_HF_IND))) {
|
(ag->hf_features & BT_HFP_HF_FEATURE_HF_IND))) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (is_char(buf, '?')) {
|
if (is_char(buf, '?')) {
|
||||||
if (!is_char(buf, '\r')) {
|
if (!is_char(buf, '\r')) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
hf_indicators = ag->hf_indicators_of_hf & ag->hf_indicators_of_ag;
|
hf_indicators = ag->hf_indicators_of_hf & ag->hf_indicators_of_ag;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX
|
len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX
|
||||||
: (sizeof(hf_indicators) * 8);
|
: (sizeof(hf_indicators) * 8);
|
||||||
for (int i = 1; i < len; i++) {
|
for (int i = 1; i < len; i++) {
|
||||||
|
@ -596,7 +621,9 @@ static int bt_hfp_ag_bind_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
data = &ag->buffer[0];
|
data = &ag->buffer[0];
|
||||||
*data = '(';
|
*data = '(';
|
||||||
data++;
|
data++;
|
||||||
|
hfp_ag_lock(ag);
|
||||||
hf_indicators = ag->hf_indicators_of_ag;
|
hf_indicators = ag->hf_indicators_of_ag;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX
|
len = (sizeof(hf_indicators) * 8) > HFP_HF_IND_MAX ? HFP_HF_IND_MAX
|
||||||
: (sizeof(hf_indicators) * 8);
|
: (sizeof(hf_indicators) * 8);
|
||||||
for (int i = 1; (i < len) && (hf_indicators != 0); i++) {
|
for (int i = 1; (i < len) && (hf_indicators != 0); i++) {
|
||||||
|
@ -640,7 +667,9 @@ static int bt_hfp_ag_bind_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
ag->hf_indicators_of_hf = hf_indicators;
|
ag->hf_indicators_of_hf = hf_indicators;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -705,11 +734,17 @@ static int hfp_ag_update_indicator(struct bt_hfp_ag *ag, enum bt_hfp_ag_indicato
|
||||||
|
|
||||||
static void hfp_ag_close_sco(struct bt_hfp_ag *ag)
|
static void hfp_ag_close_sco(struct bt_hfp_ag *ag)
|
||||||
{
|
{
|
||||||
|
struct bt_conn *sco;
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
if (NULL != ag->sco_chan.sco) {
|
|
||||||
LOG_DBG("Disconnect sco %p", ag->sco_chan.sco);
|
hfp_ag_lock(ag);
|
||||||
bt_conn_disconnect(ag->sco_chan.sco, BT_HCI_ERR_LOCALHOST_TERM_CONN);
|
sco = ag->sco_chan.sco;
|
||||||
ag->sco_chan.sco = NULL;
|
ag->sco_chan.sco = NULL;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
if (sco != NULL) {
|
||||||
|
LOG_DBG("Disconnect sco %p", sco);
|
||||||
|
bt_conn_disconnect(sco, BT_HCI_ERR_LOCALHOST_TERM_CONN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,17 +789,22 @@ static void bt_hfp_ag_unit_call_terminate(struct bt_hfp_ag *ag, void *user_data)
|
||||||
static int bt_hfp_ag_chup_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
static int bt_hfp_ag_chup_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
if (!is_char(buf, '\r')) {
|
if (!is_char(buf, '\r')) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->call_state == BT_HFP_CALL_ALERTING) {
|
hfp_ag_lock(ag);
|
||||||
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
|
if (call_state == BT_HFP_CALL_ALERTING) {
|
||||||
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
err = hfp_ag_next_step(ag, bt_hfp_ag_call_reject, NULL);
|
err = hfp_ag_next_step(ag, bt_hfp_ag_call_reject, NULL);
|
||||||
} else if ((ag->call_state == BT_HFP_CALL_ACTIVE) || (ag->call_state == BT_HFP_CALL_HOLD)) {
|
} else if ((call_state == BT_HFP_CALL_ACTIVE) || (call_state == BT_HFP_CALL_HOLD)) {
|
||||||
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL);
|
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL);
|
||||||
} else {
|
} else {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
@ -776,6 +816,7 @@ static uint8_t bt_hfp_get_call_state(struct bt_hfp_ag *ag)
|
||||||
{
|
{
|
||||||
uint8_t status = HFP_AG_CLCC_STATUS_INVALID;
|
uint8_t status = HFP_AG_CLCC_STATUS_INVALID;
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
switch (ag->call_state) {
|
switch (ag->call_state) {
|
||||||
case BT_HFP_CALL_TERMINATE:
|
case BT_HFP_CALL_TERMINATE:
|
||||||
break;
|
break;
|
||||||
|
@ -801,6 +842,7 @@ static uint8_t bt_hfp_get_call_state(struct bt_hfp_ag *ag)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -817,10 +859,13 @@ static int bt_hfp_ag_clcc_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->call_state == BT_HFP_CALL_TERMINATE) {
|
if (ag->call_state == BT_HFP_CALL_TERMINATE) {
|
||||||
/* AG shall always send OK response to HF */
|
/* AG shall always send OK response to HF */
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
dir = atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL) ? 1 : 0;
|
dir = atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL) ? 1 : 0;
|
||||||
status = bt_hfp_get_call_state(ag);
|
status = bt_hfp_get_call_state(ag);
|
||||||
|
@ -841,12 +886,16 @@ static int bt_hfp_ag_bia_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
uint32_t number;
|
uint32_t number;
|
||||||
int err;
|
int err;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
uint32_t indicator = ag->indicator;
|
uint32_t indicator;
|
||||||
|
|
||||||
if (!is_char(buf, '=')) {
|
if (!is_char(buf, '=')) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
|
indicator = ag->indicator;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
while (buf->len > 0) {
|
while (buf->len > 0) {
|
||||||
err = get_number(buf, &number);
|
err = get_number(buf, &number);
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
|
@ -873,7 +922,10 @@ static int bt_hfp_ag_bia_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
/* Force call, call setup and held call indicators are enabled. */
|
/* Force call, call setup and held call indicators are enabled. */
|
||||||
indicator = BIT(BT_HFP_AG_CALL_IND) | BIT(BT_HFP_AG_CALL_SETUP_IND) |
|
indicator = BIT(BT_HFP_AG_CALL_IND) | BIT(BT_HFP_AG_CALL_SETUP_IND) |
|
||||||
BIT(BT_HFP_AG_CALL_HELD_IND);
|
BIT(BT_HFP_AG_CALL_HELD_IND);
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
ag->indicator = indicator;
|
ag->indicator = indicator;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -897,8 +949,12 @@ static void bt_hfp_ag_call_ringing_cb(struct bt_hfp_ag *ag, bool in_bond)
|
||||||
static void hfp_ag_sco_connected(struct bt_sco_chan *chan)
|
static void hfp_ag_sco_connected(struct bt_sco_chan *chan)
|
||||||
{
|
{
|
||||||
struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan);
|
struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan);
|
||||||
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
if (ag->call_state == BT_HFP_CALL_INCOMING) {
|
hfp_ag_lock(ag);
|
||||||
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
if (call_state == BT_HFP_CALL_INCOMING) {
|
||||||
bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_ALERTING);
|
bt_hfp_ag_set_call_state(ag, BT_HFP_CALL_ALERTING);
|
||||||
bt_hfp_ag_call_ringing_cb(ag, true);
|
bt_hfp_ag_call_ringing_cb(ag, true);
|
||||||
}
|
}
|
||||||
|
@ -911,12 +967,16 @@ static void hfp_ag_sco_connected(struct bt_sco_chan *chan)
|
||||||
static void hfp_ag_sco_disconnected(struct bt_sco_chan *chan, uint8_t reason)
|
static void hfp_ag_sco_disconnected(struct bt_sco_chan *chan, uint8_t reason)
|
||||||
{
|
{
|
||||||
struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan);
|
struct bt_hfp_ag *ag = CONTAINER_OF(chan, struct bt_hfp_ag, sco_chan);
|
||||||
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
if ((bt_ag) && bt_ag->sco_disconnected) {
|
if ((bt_ag) && bt_ag->sco_disconnected) {
|
||||||
bt_ag->sco_disconnected(ag);
|
bt_ag->sco_disconnected(ag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ag->call_state == BT_HFP_CALL_INCOMING) || (ag->call_state == BT_HFP_CALL_OUTGOING)) {
|
hfp_ag_lock(ag);
|
||||||
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
if ((call_state == BT_HFP_CALL_INCOMING) || (call_state == BT_HFP_CALL_OUTGOING)) {
|
||||||
bt_hfp_ag_call_reject(ag, NULL);
|
bt_hfp_ag_call_reject(ag, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -950,16 +1010,19 @@ static struct bt_conn *bt_hfp_ag_create_sco(struct bt_hfp_ag *ag)
|
||||||
|
|
||||||
static int hfp_ag_open_sco(struct bt_hfp_ag *ag)
|
static int hfp_ag_open_sco(struct bt_hfp_ag *ag)
|
||||||
{
|
{
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->sco_chan.sco == NULL) {
|
if (ag->sco_chan.sco == NULL) {
|
||||||
struct bt_conn *sco_conn = bt_hfp_ag_create_sco(ag);
|
struct bt_conn *sco_conn = bt_hfp_ag_create_sco(ag);
|
||||||
|
|
||||||
if (sco_conn == NULL) {
|
if (sco_conn == NULL) {
|
||||||
LOG_ERR("Fail to create sco connection!");
|
LOG_ERR("Fail to create sco connection!");
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("SCO connection created (%p)", sco_conn);
|
LOG_DBG("SCO connection created (%p)", sco_conn);
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -970,15 +1033,19 @@ static int bt_hfp_ag_codec_select(struct bt_hfp_ag *ag)
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->selected_codec_id == 0) {
|
if (ag->selected_codec_id == 0) {
|
||||||
LOG_ERR("Codec is invalid");
|
LOG_ERR("Codec is invalid");
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) {
|
if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) {
|
||||||
LOG_ERR("Codec is unsupported (codec id %d)", ag->selected_codec_id);
|
LOG_ERR("Codec is unsupported (codec id %d)", ag->selected_codec_id);
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BCS:%d\r\n", ag->selected_codec_id);
|
err = hfp_ag_send_data(ag, NULL, NULL, "\r\n+BCS:%d\r\n", ag->selected_codec_id);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
@ -990,8 +1057,13 @@ static int bt_hfp_ag_codec_select(struct bt_hfp_ag *ag)
|
||||||
static int bt_hfp_ag_create_audio_connection(struct bt_hfp_ag *ag)
|
static int bt_hfp_ag_create_audio_connection(struct bt_hfp_ag *ag)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
uint32_t hf_codec_ids;
|
||||||
|
|
||||||
if ((ag->hf_codec_ids != 0) && atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED)) {
|
hfp_ag_lock(ag);
|
||||||
|
hf_codec_ids = ag->hf_codec_ids;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
|
if ((hf_codec_ids != 0) && atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED)) {
|
||||||
atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CONN);
|
atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CONN);
|
||||||
err = bt_hfp_ag_codec_select(ag);
|
err = bt_hfp_ag_codec_select(ag);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1035,9 +1107,12 @@ static int bt_hfp_ag_ata_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->call_state != BT_HFP_CALL_ALERTING) {
|
if (ag->call_state != BT_HFP_CALL_ALERTING) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
@ -1105,21 +1180,15 @@ static int bt_hfp_ag_bcc_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->selected_codec_id == 0) {
|
hfp_ag_lock(ag);
|
||||||
return -ENOTSUP;
|
if ((ag->selected_codec_id == 0) ||
|
||||||
}
|
(!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) ||
|
||||||
|
(ag->call_state == BT_HFP_CALL_TERMINATE) ||
|
||||||
if (!(ag->hf_codec_ids & BIT(ag->selected_codec_id))) {
|
(ag->sco_chan.sco != NULL)) {
|
||||||
return -ENOTSUP;
|
hfp_ag_unlock(ag);
|
||||||
}
|
|
||||||
|
|
||||||
if (ag->call_state == BT_HFP_CALL_TERMINATE) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ag->sco_chan.sco != NULL) {
|
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
err = hfp_ag_next_step(ag, bt_hfp_ag_audio_connection, NULL);
|
err = hfp_ag_next_step(ag, bt_hfp_ag_audio_connection, NULL);
|
||||||
|
|
||||||
|
@ -1157,6 +1226,7 @@ static int bt_hfp_ag_bcs_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->selected_codec_id != number) {
|
if (ag->selected_codec_id != number) {
|
||||||
LOG_ERR("Received codec id %d is not aligned with selected %d",
|
LOG_ERR("Received codec id %d is not aligned with selected %d",
|
||||||
number, ag->selected_codec_id);
|
number, ag->selected_codec_id);
|
||||||
|
@ -1166,6 +1236,7 @@ static int bt_hfp_ag_bcs_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
ag->selected_codec_id, ag->hf_codec_ids);
|
ag->selected_codec_id, ag->hf_codec_ids);
|
||||||
err = -ENOTSUP;
|
err = -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CONN);
|
atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CONN);
|
||||||
atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED);
|
atomic_clear_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED);
|
||||||
|
@ -1173,7 +1244,12 @@ static int bt_hfp_ag_bcs_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_codec_conn_setup, NULL);
|
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_codec_conn_setup, NULL);
|
||||||
} else {
|
} else {
|
||||||
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
if (call_state != BT_HFP_CALL_TERMINATE) {
|
||||||
(void)hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL);
|
(void)hfp_ag_next_step(ag, bt_hfp_ag_unit_call_terminate, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1233,12 +1309,15 @@ static int bt_hfp_ag_atd_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ENAMETOOLONG;
|
return -ENAMETOOLONG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy number to ag->number including null-character */
|
/* Copy number to ag->number including null-character */
|
||||||
memcpy(ag->number, number, len + 1);
|
memcpy(ag->number, number, len + 1);
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL);
|
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL);
|
||||||
|
|
||||||
|
@ -1253,13 +1332,17 @@ static int bt_hfp_ag_bldn_handler(struct bt_hfp_ag *ag, struct net_buf *buf)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (strlen(ag->number) == 0) {
|
if (strlen(ag->number) == 0) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOSR;
|
return -ENOSR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL);
|
err = hfp_ag_next_step(ag, bt_hfp_ag_unit_call_outgoing, NULL);
|
||||||
|
|
||||||
|
@ -1313,11 +1396,15 @@ static void hfp_ag_connected(struct bt_rfcomm_dlc *dlc)
|
||||||
static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
|
static void hfp_ag_disconnected(struct bt_rfcomm_dlc *dlc)
|
||||||
{
|
{
|
||||||
struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc);
|
struct bt_hfp_ag *ag = CONTAINER_OF(dlc, struct bt_hfp_ag, rfcomm_dlc);
|
||||||
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTED);
|
bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTED);
|
||||||
|
|
||||||
if ((ag->call_state == BT_HFP_CALL_ALERTING) || (ag->call_state == BT_HFP_CALL_ACTIVE) ||
|
hfp_ag_lock(ag);
|
||||||
(ag->call_state == BT_HFP_CALL_HOLD)) {
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
if ((call_state == BT_HFP_CALL_ALERTING) || (call_state == BT_HFP_CALL_ACTIVE) ||
|
||||||
|
(call_state == BT_HFP_CALL_HOLD)) {
|
||||||
bt_hfp_ag_terminate_cb(ag, NULL);
|
bt_hfp_ag_terminate_cb(ag, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1420,10 +1507,15 @@ static void hfp_ag_sent(struct bt_rfcomm_dlc *dlc, struct net_buf *buf, int err)
|
||||||
static void bt_ag_deferred_work_cb(struct bt_hfp_ag *ag, void *user_data)
|
static void bt_ag_deferred_work_cb(struct bt_hfp_ag *ag, void *user_data)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
|
|
||||||
switch (ag->call_state) {
|
hfp_ag_lock(ag);
|
||||||
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
|
switch (call_state) {
|
||||||
case BT_HFP_CALL_TERMINATE:
|
case BT_HFP_CALL_TERMINATE:
|
||||||
break;
|
break;
|
||||||
case BT_HFP_CALL_ACTIVE:
|
case BT_HFP_CALL_ACTIVE:
|
||||||
|
@ -1483,10 +1575,14 @@ static void bt_ag_deferred_work(struct k_work *work)
|
||||||
static void bt_ag_ringing_work_cb(struct bt_hfp_ag *ag, void *user_data)
|
static void bt_ag_ringing_work_cb(struct bt_hfp_ag *ag, void *user_data)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
|
|
||||||
if (ag->call_state == BT_HFP_CALL_ALERTING) {
|
hfp_ag_lock(ag);
|
||||||
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
if (call_state == BT_HFP_CALL_ALERTING) {
|
||||||
|
|
||||||
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
||||||
return;
|
return;
|
||||||
|
@ -1635,6 +1731,7 @@ int bt_hfp_ag_connect(struct bt_conn *conn, struct bt_hfp_ag **ag, uint8_t chann
|
||||||
int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag)
|
int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
bt_hfp_call_state_t call_state;
|
||||||
|
|
||||||
LOG_DBG("");
|
LOG_DBG("");
|
||||||
|
|
||||||
|
@ -1642,16 +1739,20 @@ int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
|
call_state = ag->call_state;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTING);
|
bt_hfp_ag_set_state(ag, BT_HFP_DISCONNECTING);
|
||||||
|
|
||||||
if ((ag->call_state == BT_HFP_CALL_ACTIVE) || (ag->call_state == BT_HFP_CALL_HOLD)) {
|
if ((call_state == BT_HFP_CALL_ACTIVE) || (call_state == BT_HFP_CALL_HOLD)) {
|
||||||
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb,
|
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb,
|
||||||
NULL);
|
NULL);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
LOG_ERR("HFP AG send response err :(%d)", err);
|
LOG_ERR("HFP AG send response err :(%d)", err);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
} else if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
} else if (call_state != BT_HFP_CALL_TERMINATE) {
|
||||||
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE,
|
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND, BT_HFP_CALL_SETUP_NONE,
|
||||||
bt_hfp_ag_reject_cb, NULL);
|
bt_hfp_ag_reject_cb, NULL);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
@ -1710,21 +1811,27 @@ int bt_hfp_ag_remote_incoming(struct bt_hfp_ag *ag, const char *number)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
len = strlen(number);
|
len = strlen(number);
|
||||||
if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) {
|
if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
/* Copy number to ag->number including null-character */
|
/* Copy number to ag->number including null-character */
|
||||||
memcpy(ag->number, number, len + 1);
|
memcpy(ag->number, number, len + 1);
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
atomic_set_bit(ag->flags, BT_HFP_AG_INCOMING_CALL);
|
atomic_set_bit(ag->flags, BT_HFP_AG_INCOMING_CALL);
|
||||||
|
|
||||||
|
@ -1747,13 +1854,17 @@ int bt_hfp_ag_reject(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_INCOMING)) {
|
if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_INCOMING)) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1775,13 +1886,17 @@ int bt_hfp_ag_accept(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->call_state != BT_HFP_CALL_ALERTING) {
|
if (ag->call_state != BT_HFP_CALL_ALERTING) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
if (!atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1811,13 +1926,17 @@ int bt_hfp_ag_terminate(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) {
|
if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL);
|
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL);
|
||||||
|
|
||||||
|
@ -1853,21 +1972,27 @@ int bt_hfp_ag_outgoing(struct bt_hfp_ag *ag, const char *number)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
if (ag->call_state != BT_HFP_CALL_TERMINATE) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
len = strlen(number);
|
len = strlen(number);
|
||||||
if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) {
|
if ((len == 0) || (len > CONFIG_BT_HFP_AG_PHONE_NUMBER_MAX_LEN)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
/* Copy number to ag->number including null-character */
|
/* Copy number to ag->number including null-character */
|
||||||
memcpy(ag->number, number, len + 1);
|
memcpy(ag->number, number, len + 1);
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
atomic_clear_bit(ag->flags, BT_HFP_AG_INCOMING_CALL);
|
atomic_clear_bit(ag->flags, BT_HFP_AG_INCOMING_CALL);
|
||||||
|
|
||||||
|
@ -1898,19 +2023,24 @@ int bt_hfp_ag_remote_ringing(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BT_HFP_CALL_OUTGOING != ag->call_state) {
|
if (ag->call_state != BT_HFP_CALL_OUTGOING) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_test_bit(ag->flags, BT_HFP_AG_INBAND_RING)) {
|
if (atomic_test_bit(ag->flags, BT_HFP_AG_INBAND_RING)) {
|
||||||
if (ag->sco_chan.sco == NULL) {
|
if (ag->sco_chan.sco == NULL) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND,
|
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_SETUP_IND,
|
||||||
BT_HFP_CALL_SETUP_REMOTE_ALERTING, bt_hfp_ag_ringing_cb,
|
BT_HFP_CALL_SETUP_REMOTE_ALERTING, bt_hfp_ag_ringing_cb,
|
||||||
|
@ -1929,13 +2059,17 @@ int bt_hfp_ag_remote_reject(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_OUTGOING)) {
|
if ((ag->call_state != BT_HFP_CALL_ALERTING) && (ag->call_state != BT_HFP_CALL_OUTGOING)) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1957,13 +2091,17 @@ int bt_hfp_ag_remote_accept(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ag->call_state != BT_HFP_CALL_ALERTING) {
|
if (ag->call_state != BT_HFP_CALL_ALERTING) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
if (atomic_test_bit(ag->flags, BT_HFP_AG_INCOMING_CALL)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1993,13 +2131,17 @@ int bt_hfp_ag_remote_terminate(struct bt_hfp_ag *ag)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) {
|
if ((ag->call_state != BT_HFP_CALL_ACTIVE) || (ag->call_state != BT_HFP_CALL_HOLD)) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL);
|
err = hfp_ag_update_indicator(ag, BT_HFP_AG_CALL_IND, 0, bt_hfp_ag_terminate_cb, NULL);
|
||||||
|
|
||||||
|
@ -2016,9 +2158,12 @@ int bt_hfp_ag_set_indicator(struct bt_hfp_ag *ag, enum bt_hfp_ag_indicator index
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case BT_HFP_AG_SERVICE_IND:
|
case BT_HFP_AG_SERVICE_IND:
|
||||||
|
@ -2057,7 +2202,9 @@ int bt_hfp_ag_set_operator(struct bt_hfp_ag *ag, char *name)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2065,6 +2212,7 @@ int bt_hfp_ag_set_operator(struct bt_hfp_ag *ag, char *name)
|
||||||
len = MIN(sizeof(ag->operator) - 1, len);
|
len = MIN(sizeof(ag->operator) - 1, len);
|
||||||
memcpy(ag->operator, name, len);
|
memcpy(ag->operator, name, len);
|
||||||
ag->operator[len] = '\0';
|
ag->operator[len] = '\0';
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2079,19 +2227,26 @@ int bt_hfp_ag_select_codec(struct bt_hfp_ag *ag, uint8_t id)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
if (ag->state != BT_HFP_CONNECTED) {
|
if (ag->state != BT_HFP_CONNECTED) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ag->hf_codec_ids && BIT(id))) {
|
if (!(ag->hf_codec_ids && BIT(id))) {
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
if (atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CONN)) {
|
if (atomic_test_bit(ag->flags, BT_HFP_AG_CODEC_CONN)) {
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hfp_ag_lock(ag);
|
||||||
ag->selected_codec_id = id;
|
ag->selected_codec_id = id;
|
||||||
|
hfp_ag_unlock(ag);
|
||||||
|
|
||||||
atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED);
|
atomic_set_bit(ag->flags, BT_HFP_AG_CODEC_CHANGED);
|
||||||
|
|
||||||
err = bt_hfp_ag_create_audio_connection(ag);
|
err = bt_hfp_ag_create_audio_connection(ag);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue