Skip to content

Commit 0412244

Browse files
lylezhu2012kartben
authored andcommitted
Bluetooth: HFP_HF: Optimize SLC init procedure
In current implementation, it is difficult to insert new AT commands in the SLC initialization sequence. Add a SLC initialization sequence. Send AT command one by one. It will be easy to insert new AT commands in the appropriate position. Signed-off-by: Lyle Zhu <[email protected]>
1 parent 32e6c21 commit 0412244

File tree

1 file changed

+112
-122
lines changed

1 file changed

+112
-122
lines changed

subsys/bluetooth/host/classic/hfp_hf.c

Lines changed: 112 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,51 +1789,6 @@ static int at_vgs_finish(struct at_client *hf_at, enum at_result result,
17891789
}
17901790
#endif /* CONFIG_BT_HFP_HF_VOLUME */
17911791

1792-
#if defined(CONFIG_BT_HFP_HF_CODEC_NEG)
1793-
static void get_codec_ids(struct bt_hfp_hf *hf, char *buffer, size_t buffer_len)
1794-
{
1795-
size_t len = 0;
1796-
uint8_t ids = hf->hf_codec_ids;
1797-
int index = 0;
1798-
1799-
while (ids && (len < (buffer_len-2))) {
1800-
if (ids & 0x01) {
1801-
buffer[len++] = index + '0';
1802-
buffer[len++] = ',';
1803-
}
1804-
index ++;
1805-
ids = ids >> 1;
1806-
}
1807-
1808-
if (len > 0) {
1809-
len --;
1810-
}
1811-
1812-
buffer[len] = '\0';
1813-
}
1814-
1815-
static int send_at_bac(struct bt_hfp_hf *hf, at_finish_cb_t cb)
1816-
{
1817-
if (hf->ag_features & BT_HFP_AG_FEATURE_CODEC_NEG) {
1818-
char ids[sizeof(hf->hf_codec_ids)*2*8 + 1];
1819-
get_codec_ids(hf, &ids[0], ARRAY_SIZE(ids));
1820-
return hfp_hf_send_cmd(hf, NULL, cb, "AT+BAC=%s", ids);
1821-
}
1822-
1823-
return -ENOTSUP;
1824-
}
1825-
1826-
static int at_bac_finish(struct at_client *hf_at, enum at_result result,
1827-
enum at_cme cme_err)
1828-
{
1829-
struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
1830-
1831-
LOG_DBG("BAC set (result %d) on %p", result, hf);
1832-
1833-
return 0;
1834-
}
1835-
#endif /* CONFIG_BT_HFP_HF_CODEC_NEG */
1836-
18371792
#if defined(CONFIG_BT_HFP_HF_3WAY_CALL)
18381793
static int send_at_ccwa(struct bt_hfp_hf *hf, at_finish_cb_t cb)
18391794
{
@@ -1876,9 +1831,6 @@ static struct at_cmd_init
18761831
#if defined(CONFIG_BT_HFP_HF_CLI)
18771832
{send_at_clip, at_clip_finish, false},
18781833
#endif /* CONFIG_BT_HFP_HF_CLI */
1879-
#if defined(CONFIG_BT_HFP_HF_CODEC_NEG)
1880-
{send_at_bac, at_bac_finish, false},
1881-
#endif /* CONFIG_BT_HFP_HF_CODEC_NEG */
18821834
#if defined(CONFIG_BT_HFP_HF_3WAY_CALL)
18831835
{send_at_ccwa, at_ccwa_finish, false},
18841836
#endif /* CONFIG_BT_HFP_HF_3WAY_CALL */
@@ -1962,114 +1914,152 @@ static void slc_completed(struct at_client *hf_at)
19621914
}
19631915

19641916
#if defined(CONFIG_BT_HFP_HF_3WAY_CALL)
1965-
int chld_finish(struct at_client *hf_at, enum at_result result,
1966-
enum at_cme cme_err)
1917+
static int send_at_chld_supported(struct bt_hfp_hf *hf, at_finish_cb_t cb)
19671918
{
1968-
if (result != AT_RESULT_OK) {
1969-
LOG_ERR("SLC Connection ERROR in response");
1970-
hf_slc_error(hf_at);
1971-
return -EINVAL;
1972-
}
1919+
return hfp_hf_send_cmd(hf, NULL, cb, "AT+CHLD=?");
1920+
}
1921+
#endif /* CONFIG_BT_HFP_HF_3WAY_CALL */
19731922

1974-
slc_completed(hf_at);
1923+
static int send_at_cmer(struct bt_hfp_hf *hf, at_finish_cb_t cb)
1924+
{
1925+
at_register_unsolicited(&hf->at, unsolicited_cb);
1926+
return hfp_hf_send_cmd(hf, NULL, cb, "AT+CMER=3,0,0,1");
1927+
}
19751928

1976-
return 0;
1929+
static int send_at_cind_status(struct bt_hfp_hf *hf, at_finish_cb_t cb)
1930+
{
1931+
return hfp_hf_send_cmd(hf, cind_status_resp, cb, "AT+CIND?");
19771932
}
1978-
#endif /* CONFIG_BT_HFP_HF_3WAY_CALL */
19791933

1980-
int cmer_finish(struct at_client *hf_at, enum at_result result,
1981-
enum at_cme cme_err)
1934+
static int send_at_cind_supported(struct bt_hfp_hf *hf, at_finish_cb_t cb)
19821935
{
1983-
#if defined(CONFIG_BT_HFP_HF_3WAY_CALL)
1984-
struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
1985-
int err;
1986-
#endif /* CONFIG_BT_HFP_HF_3WAY_CALL */
1936+
return hfp_hf_send_cmd(hf, cind_resp, cb, "AT+CIND=?");
1937+
}
19871938

1988-
if (result != AT_RESULT_OK) {
1989-
LOG_ERR("SLC Connection ERROR in response");
1990-
hf_slc_error(hf_at);
1991-
return -EINVAL;
1992-
}
1939+
#if defined(CONFIG_BT_HFP_HF_CODEC_NEG)
1940+
static void get_codec_ids(struct bt_hfp_hf *hf, char *buffer, size_t buffer_len)
1941+
{
1942+
size_t len = 0;
1943+
uint8_t ids = hf->hf_codec_ids;
1944+
int index = 0;
19931945

1994-
#if defined(CONFIG_BT_HFP_HF_3WAY_CALL)
1995-
if ((hf->ag_features & BT_HFP_AG_FEATURE_3WAY_CALL) &&
1996-
(hf->hf_features & BT_HFP_HF_FEATURE_3WAY_CALL)) {
1997-
err = hfp_hf_send_cmd(hf, NULL, chld_finish, "AT+CHLD=?");
1998-
if (err < 0) {
1999-
hf_slc_error(hf_at);
1946+
while (ids && (len < (buffer_len-2))) {
1947+
if (ids & 0x01) {
1948+
buffer[len++] = index + '0';
1949+
buffer[len++] = ',';
20001950
}
2001-
return err;
1951+
index++;
1952+
ids = ids >> 1;
20021953
}
2003-
#endif /* CONFIG_BT_HFP_HF_3WAY_CALL */
20041954

2005-
slc_completed(hf_at);
1955+
if (len > 0) {
1956+
len--;
1957+
}
20061958

2007-
return 0;
1959+
buffer[len] = '\0';
20081960
}
20091961

2010-
int cind_status_finish(struct at_client *hf_at, enum at_result result,
2011-
enum at_cme cme_err)
1962+
static int send_at_bac(struct bt_hfp_hf *hf, at_finish_cb_t cb)
20121963
{
2013-
struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
2014-
int err;
2015-
2016-
if (result != AT_RESULT_OK) {
2017-
LOG_ERR("SLC Connection ERROR in response");
2018-
hf_slc_error(hf_at);
2019-
return -EINVAL;
2020-
}
1964+
char ids[sizeof(hf->hf_codec_ids)*2*8 + 1];
20211965

2022-
at_register_unsolicited(hf_at, unsolicited_cb);
2023-
err = hfp_hf_send_cmd(hf, NULL, cmer_finish, "AT+CMER=3,0,0,1");
2024-
if (err < 0) {
2025-
hf_slc_error(hf_at);
2026-
return err;
2027-
}
1966+
get_codec_ids(hf, &ids[0], ARRAY_SIZE(ids));
1967+
return hfp_hf_send_cmd(hf, NULL, cb, "AT+BAC=%s", ids);
1968+
}
1969+
#endif /* CONFIG_BT_HFP_HF_CODEC_NEG */
20281970

2029-
return 0;
1971+
static int send_at_brsf(struct bt_hfp_hf *hf, at_finish_cb_t cb)
1972+
{
1973+
return hfp_hf_send_cmd(hf, brsf_resp, cb, "AT+BRSF=%u", hf->hf_features);
20301974
}
20311975

2032-
int cind_finish(struct at_client *hf_at, enum at_result result,
2033-
enum at_cme cme_err)
1976+
static struct slc_init
1977+
{
1978+
at_send_t send;
1979+
bool disconnect; /* Disconnect if command failed. */
1980+
uint32_t ag_feature_mask; /* AG feature mask */
1981+
} slc_init_list[] = {
1982+
{send_at_brsf, true, 0},
1983+
#if defined(CONFIG_BT_HFP_HF_CODEC_NEG)
1984+
{send_at_bac, true, BT_HFP_AG_FEATURE_CODEC_NEG},
1985+
#endif /* CONFIG_BT_HFP_HF_CODEC_NEG */
1986+
{send_at_cind_supported, true, 0},
1987+
{send_at_cind_status, true, 0},
1988+
{send_at_cmer, true, 0},
1989+
#if defined(CONFIG_BT_HFP_HF_3WAY_CALL)
1990+
{send_at_chld_supported, true, BT_HFP_AG_FEATURE_3WAY_CALL},
1991+
#endif /* CONFIG_BT_HFP_HF_3WAY_CALL */
1992+
};
1993+
1994+
static int slc_init_start(struct bt_hfp_hf *hf);
1995+
1996+
static int slc_init_finish(struct at_client *hf_at, enum at_result result,
1997+
enum at_cme cme_err)
20341998
{
20351999
struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
2036-
int err;
20372000

20382001
if (result != AT_RESULT_OK) {
2039-
LOG_ERR("SLC Connection ERROR in response");
2040-
hf_slc_error(hf_at);
2041-
return -EINVAL;
2002+
LOG_WRN("It is ERROR response of AT command %d.", hf->cmd_init_seq);
2003+
if (slc_init_list[hf->cmd_init_seq].disconnect) {
2004+
hf_slc_error(&hf->at);
2005+
return 0;
2006+
}
20422007
}
20432008

2044-
err = hfp_hf_send_cmd(hf, cind_status_resp, cind_status_finish,
2045-
"AT+CIND?");
2046-
if (err < 0) {
2047-
hf_slc_error(hf_at);
2048-
return err;
2009+
if (ARRAY_SIZE(slc_init_list) <= hf->cmd_init_seq) {
2010+
LOG_ERR("Invalid indicator (%d>=%d)", hf->cmd_init_seq,
2011+
ARRAY_SIZE(slc_init_list));
20492012
}
20502013

2014+
/* Goto next AT command */
2015+
hf->cmd_init_seq++;
2016+
(void)slc_init_start(hf);
20512017
return 0;
20522018
}
20532019

2054-
int brsf_finish(struct at_client *hf_at, enum at_result result,
2055-
enum at_cme cme_err)
2020+
static int slc_init_start(struct bt_hfp_hf *hf)
20562021
{
2057-
struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
2058-
int err;
2022+
at_send_t send;
2023+
uint32_t feture_mask;
2024+
int err = -EINVAL;
20592025

2060-
if (result != AT_RESULT_OK) {
2061-
LOG_ERR("SLC Connection ERROR in response");
2062-
hf_slc_error(hf_at);
2063-
return -EINVAL;
2026+
while (ARRAY_SIZE(slc_init_list) > hf->cmd_init_seq) {
2027+
LOG_DBG("Fetch AT command (%d)", hf->cmd_init_seq);
2028+
feture_mask = slc_init_list[hf->cmd_init_seq].ag_feature_mask;
2029+
if (feture_mask && (!(feture_mask & hf->ag_features))) {
2030+
/* The feature is not supported by AG. Skip the step. */
2031+
LOG_INF("Skip SLC init step %d", hf->cmd_init_seq);
2032+
hf->cmd_init_seq++;
2033+
continue;
2034+
}
2035+
2036+
send = slc_init_list[hf->cmd_init_seq].send;
2037+
if (send) {
2038+
LOG_DBG("Send AT command");
2039+
err = send(hf, slc_init_finish);
2040+
} else {
2041+
LOG_WRN("Invalid send func of AT command");
2042+
}
2043+
2044+
if (!err) {
2045+
break;
2046+
}
2047+
2048+
LOG_WRN("AT command sending failed");
2049+
if (slc_init_list[hf->cmd_init_seq].disconnect) {
2050+
hfp_hf_send_failed(hf);
2051+
break;
2052+
}
2053+
/* Goto next AT command */
2054+
LOG_WRN("Send next AT command");
2055+
hf->cmd_init_seq++;
20642056
}
20652057

2066-
err = hfp_hf_send_cmd(hf, cind_resp, cind_finish, "AT+CIND=?");
2067-
if (err < 0) {
2068-
hf_slc_error(hf_at);
2069-
return err;
2058+
if (ARRAY_SIZE(slc_init_list) <= hf->cmd_init_seq) {
2059+
slc_completed(&hf->at);
20702060
}
20712061

2072-
return 0;
2062+
return err;
20732063
}
20742064

20752065
int hf_slc_establish(struct bt_hfp_hf *hf)
@@ -2078,8 +2068,8 @@ int hf_slc_establish(struct bt_hfp_hf *hf)
20782068

20792069
LOG_DBG("");
20802070

2081-
err = hfp_hf_send_cmd(hf, brsf_resp, brsf_finish, "AT+BRSF=%u",
2082-
hf->hf_features);
2071+
hf->cmd_init_seq = 0;
2072+
err = slc_init_start(hf);
20832073
if (err < 0) {
20842074
hf_slc_error(&hf->at);
20852075
return err;

0 commit comments

Comments
 (0)