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:
Sathish Narasimman 2016-11-14 13:47:24 +05:30 committed by Johan Hedberg
commit 128ef4dd99
2 changed files with 133 additions and 4 deletions

View file

@ -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;
} }

View file

@ -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];
}; };