Bluetooth: HFP HF: SLC Connection send/parse CIND
Part of service level connection initilization. Sending AT+CIND=? and parsing its response. < ACL Data TX: Handle 256 flags 0x00 dlen 18 [hci0] 20.888273 Channel: 76 len 14 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x09 cr 0 dlci 0x02 Control: 0xef poll/final 0 Length: 10 FCS: 0x40 41 54 2b 43 49 4e 44 3d 3f 0d 40 AT+CIND=?.@ > HCI Event: Number of Completed Packets (0x13) plen 5 [hci0] 20.914998 Num handles: 1 Handle: 256 Count: 1 > HCI Event: Number of Completed Packets (0x13) plen 5 [hci0] 20.916863 Num handles: 1 Handle: 256 Count: 1 > ACL Data RX: Handle 256 flags 0x02 dlen 142 [hci0] 20.945835 Channel: 64 len 138 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x0b cr 1 dlci 0x02 Control: 0xff poll/final 1 Length: 1024 FCS: 0x86 Credits: 1 0d 0a 2b 43 49 4e 44 3a 20 28 22 63 61 6c 6c 22 ..+CIND: ("call" 2c 28 30 2c 31 29 29 2c 28 22 63 61 6c 6c 73 65 ,(0,1)),("callse 74 75 70 22 2c 28 30 2d 33 29 29 2c 28 22 73 65 tup",(0-3)),("se 72 76 69 63 65 22 2c 28 30 2d 31 29 29 2c 28 22 rvice",(0-1)),(" 73 69 67 6e 61 6c 22 2c 28 30 2d 35 29 29 2c 28 signal",(0-5)),( 22 72 6f 61 6d 22 2c 28 30 2c 31 29 29 2c 28 22 "roam",(0,1)),(" 62 61 74 74 63 68 67 22 2c 28 30 2d 35 29 29 2c battchg",(0-5)), 28 22 63 61 6c 6c 68 65 6c 64 22 2c 28 30 2d 32 ("callheld",(0-2 29 29 0d 0a 86 ))... > ACL Data RX: Handle 256 flags 0x02 dlen 14 [hci0] 20.947764 Channel: 64 len 10 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x0b cr 1 dlci 0x02 Control: 0xef poll/final 0 Length: 6 FCS: 0x9a 0d 0a 4f 4b 0d 0a 9a ..OK... Change-Id: I33126a19641b889f1749b642cbc5e63984d85b6d Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
This commit is contained in:
parent
39e7350a13
commit
128ef4dd99
2 changed files with 133 additions and 4 deletions
|
@ -37,6 +37,8 @@
|
||||||
#define BT_DBG(fmt, ...)
|
#define BT_DBG(fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_IND_STR_LEN 17
|
||||||
|
|
||||||
struct bt_hfp_hf_cb *bt_hf;
|
struct bt_hfp_hf_cb *bt_hf;
|
||||||
|
|
||||||
NET_BUF_POOL_DEFINE(hf_pool, CONFIG_BLUETOOTH_MAX_CONN + 1,
|
NET_BUF_POOL_DEFINE(hf_pool, CONFIG_BLUETOOTH_MAX_CONN + 1,
|
||||||
|
@ -45,6 +47,20 @@ NET_BUF_POOL_DEFINE(hf_pool, CONFIG_BLUETOOTH_MAX_CONN + 1,
|
||||||
|
|
||||||
static struct bt_hfp_hf bt_hfp_hf_pool[CONFIG_BLUETOOTH_MAX_CONN];
|
static struct bt_hfp_hf bt_hfp_hf_pool[CONFIG_BLUETOOTH_MAX_CONN];
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
char *name;
|
||||||
|
uint32_t min;
|
||||||
|
uint32_t max;
|
||||||
|
} ag_ind[] = {
|
||||||
|
{"service", 0, 1},
|
||||||
|
{"call", 0, 1},
|
||||||
|
{"callsetup", 0, 3},
|
||||||
|
{"callheld", 0, 2},
|
||||||
|
{"signal", 0, 5},
|
||||||
|
{"roam", 0, 1},
|
||||||
|
{"battchg", 0, 5}
|
||||||
|
};
|
||||||
|
|
||||||
void hf_slc_error(struct at_client *hf_at)
|
void hf_slc_error(struct at_client *hf_at)
|
||||||
{
|
{
|
||||||
BT_ERR("SLC error: disconnecting");
|
BT_ERR("SLC error: disconnecting");
|
||||||
|
@ -121,7 +137,91 @@ int brsf_resp(struct at_client *hf_at, struct net_buf *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int brsf_finish(struct at_client *hf_at, struct net_buf *buf,
|
static void cind_handle_values(struct at_client *hf_at, uint32_t index,
|
||||||
|
char *name, uint32_t min, uint32_t max)
|
||||||
|
{
|
||||||
|
struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
BT_DBG("index: %u, name: %s, min: %u, max:%u", index, name, min, max);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ag_ind); i++) {
|
||||||
|
if (strcmp(name, ag_ind[i].name) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (min != ag_ind[i].min || max != ag_ind[i].max) {
|
||||||
|
BT_ERR("%s indicator min/max value not matching", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
hf->ind_table[index] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int cind_handle(struct at_client *hf_at)
|
||||||
|
{
|
||||||
|
uint32_t index = 0;
|
||||||
|
|
||||||
|
/* Parsing Example: CIND: ("call",(0,1)) etc.. */
|
||||||
|
while (at_has_next_list(hf_at)) {
|
||||||
|
char name[MAX_IND_STR_LEN];
|
||||||
|
uint32_t min, max;
|
||||||
|
|
||||||
|
if (at_open_list(hf_at) < 0) {
|
||||||
|
BT_ERR("Could not get open list");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (at_list_get_string(hf_at, name, sizeof(name)) < 0) {
|
||||||
|
BT_ERR("Could not get string");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (at_open_list(hf_at) < 0) {
|
||||||
|
BT_ERR("Could not get open list");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (at_list_get_range(hf_at, &min, &max) < 0) {
|
||||||
|
BT_ERR("Could not get range");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (at_close_list(hf_at) < 0) {
|
||||||
|
BT_ERR("Could not get close list");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (at_close_list(hf_at) < 0) {
|
||||||
|
BT_ERR("Could not get close list");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
cind_handle_values(hf_at, index, name, min, max);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
BT_ERR("Error on CIND response");
|
||||||
|
hf_slc_error(hf_at);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cind_resp(struct at_client *hf_at, struct net_buf *buf)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = at_parse_cmd_input(hf_at, buf, "CIND", cind_handle);
|
||||||
|
if (err < 0) {
|
||||||
|
BT_ERR("Error parsing CMD input");
|
||||||
|
hf_slc_error(hf_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cind_finish(struct at_client *hf_at, struct net_buf *buf,
|
||||||
enum at_result result)
|
enum at_result result)
|
||||||
{
|
{
|
||||||
if (result != AT_RESULT_OK) {
|
if (result != AT_RESULT_OK) {
|
||||||
|
@ -130,7 +230,29 @@ int brsf_finish(struct at_client *hf_at, struct net_buf *buf,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Continue with SLC creation */
|
/* Continue SLC creation */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int brsf_finish(struct at_client *hf_at, struct net_buf *buf,
|
||||||
|
enum at_result result)
|
||||||
|
{
|
||||||
|
struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (result != AT_RESULT_OK) {
|
||||||
|
BT_ERR("SLC Connection ERROR in response");
|
||||||
|
hf_slc_error(hf_at);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hfp_hf_send_cmd(hf, cind_resp, cind_finish, "AT+CIND=?");
|
||||||
|
if (err < 0) {
|
||||||
|
hf_slc_error(hf_at);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +309,7 @@ static int bt_hfp_hf_accept(struct bt_conn *conn, struct bt_rfcomm_dlc **dlc)
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(bt_hfp_hf_pool); i++) {
|
for (i = 0; i < ARRAY_SIZE(bt_hfp_hf_pool); i++) {
|
||||||
struct bt_hfp_hf *hf = &bt_hfp_hf_pool[i];
|
struct bt_hfp_hf *hf = &bt_hfp_hf_pool[i];
|
||||||
|
int j;
|
||||||
|
|
||||||
if (hf->rfcomm_dlc.session) {
|
if (hf->rfcomm_dlc.session) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -203,6 +326,10 @@ static int bt_hfp_hf_accept(struct bt_conn *conn, struct bt_rfcomm_dlc **dlc)
|
||||||
/* Set the supported features*/
|
/* Set the supported features*/
|
||||||
hf->hf_features = BT_HFP_HF_SUPPORTED_FEATURES;
|
hf->hf_features = BT_HFP_HF_SUPPORTED_FEATURES;
|
||||||
|
|
||||||
|
for (j = 0; j < HF_MAX_AG_INDICATORS; j++) {
|
||||||
|
hf->ind_table[j] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BLUETOOTH_HFP_MAX_MTU 140
|
#define BLUETOOTH_HFP_MAX_MTU 140
|
||||||
#define BLUETOOTH_HF_CLIENT_MAX_PDU 20
|
#define BLUETOOTH_HF_CLIENT_MAX_PDU BLUETOOTH_HFP_MAX_MTU
|
||||||
|
|
||||||
/* HFP AG Features */
|
/* HFP AG Features */
|
||||||
#define BT_HFP_AG_FEATURE_3WAY_CALL 0x00000001 /* Three-way calling */
|
#define BT_HFP_AG_FEATURE_3WAY_CALL 0x00000001 /* Three-way calling */
|
||||||
|
@ -51,7 +51,8 @@
|
||||||
#define BT_HFP_HF_SUPPORTED_FEATURES (BT_HFP_HF_FEATURE_CLI | \
|
#define BT_HFP_HF_SUPPORTED_FEATURES (BT_HFP_HF_FEATURE_CLI | \
|
||||||
BT_HFP_HF_FEATURE_VOLUME)
|
BT_HFP_HF_FEATURE_VOLUME)
|
||||||
|
|
||||||
#define HF_MAX_BUF_LEN 20
|
#define HF_MAX_BUF_LEN BLUETOOTH_HF_CLIENT_MAX_PDU
|
||||||
|
#define HF_MAX_AG_INDICATORS 20
|
||||||
|
|
||||||
struct bt_hfp_hf {
|
struct bt_hfp_hf {
|
||||||
struct bt_rfcomm_dlc rfcomm_dlc;
|
struct bt_rfcomm_dlc rfcomm_dlc;
|
||||||
|
@ -59,4 +60,5 @@ struct bt_hfp_hf {
|
||||||
struct at_client at;
|
struct at_client at;
|
||||||
uint32_t hf_features;
|
uint32_t hf_features;
|
||||||
uint32_t ag_features;
|
uint32_t ag_features;
|
||||||
|
int8_t ind_table[HF_MAX_AG_INDICATORS];
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue