summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSathish Narasimman <sathish.narasimman@intel.com>2017-01-04 19:47:06 +0530
committerJohan Hedberg <johan.hedberg@intel.com>2017-01-28 08:43:41 +0200
commitd903b53e6ba12b6e89e7aabbdb0bab752a861e1d (patch)
tree92a939ab9e587e692e28c5b816784447ffa27b32
parenta45dd12f0c50a13afed8d3434f71ee00d7d2582c (diff)
Bluetooth: AT: HFP HF: Handle unsolicited reponse
This implemnts the feature to handle the unsolicited response received from the AG. In the hfp_hf.c file the unsolicited_cb function process it. Change-Id: I3ca6c8d4a1522d02f7160e2fe4ae1598cd93ce7e Signed-off-by: Sathish Narasimman <sathish.narasimman@intel.com>
-rw-r--r--subsys/bluetooth/host/at.c35
-rw-r--r--subsys/bluetooth/host/at.h13
-rw-r--r--subsys/bluetooth/host/hfp_hf.c15
3 files changed, 49 insertions, 14 deletions
diff --git a/subsys/bluetooth/host/at.c b/subsys/bluetooth/host/at.c
index 07f5aaab0..7c8a68f75 100644
--- a/subsys/bluetooth/host/at.c
+++ b/subsys/bluetooth/host/at.c
@@ -232,7 +232,10 @@ static int at_state_process_result(struct at_client *at, struct net_buf *buf)
static int at_state_unsolicited_cmd(struct at_client *at, struct net_buf *buf)
{
- /* TODO return error temporarily*/
+ if (at->unsolicited) {
+ return at->unsolicited(at, buf);
+ }
+
return -ENODATA;
}
@@ -266,10 +269,13 @@ int at_parse_input(struct at_client *at, struct net_buf *buf)
}
static int at_cmd_start(struct at_client *at, struct net_buf *buf,
- const char *prefix, parse_val_t func)
+ const char *prefix, parse_val_t func,
+ enum at_cmd_type type)
{
if (!str_has_prefix(at->buf, prefix)) {
- at->state = AT_STATE_UNSOLICITED_CMD;
+ if (type == AT_CMD_TYPE_NORMAL) {
+ at->state = AT_STATE_UNSOLICITED_CMD;
+ }
return -ENODATA;
}
@@ -279,13 +285,15 @@ static int at_cmd_start(struct at_client *at, struct net_buf *buf,
}
static int at_cmd_get_value(struct at_client *at, struct net_buf *buf,
- const char *prefix, parse_val_t func)
+ const char *prefix, parse_val_t func,
+ enum at_cmd_type type)
{
return get_cmd_value(at, buf, '\r', AT_CMD_PROCESS_VALUE);
}
static int at_cmd_process_value(struct at_client *at, struct net_buf *buf,
- const char *prefix, parse_val_t func)
+ const char *prefix, parse_val_t func,
+ enum at_cmd_type type)
{
int ret;
@@ -296,7 +304,8 @@ static int at_cmd_process_value(struct at_client *at, struct net_buf *buf,
}
static int at_cmd_state_end_lf(struct at_client *at, struct net_buf *buf,
- const char *prefix, parse_val_t func)
+ const char *prefix, parse_val_t func,
+ enum at_cmd_type type)
{
int err;
@@ -319,7 +328,8 @@ static handle_cmd_input_t cmd_parser_cb[] = {
};
int at_parse_cmd_input(struct at_client *at, struct net_buf *buf,
- const char *prefix, parse_val_t func)
+ const char *prefix, parse_val_t func,
+ enum at_cmd_type type)
{
int ret;
@@ -328,12 +338,14 @@ int at_parse_cmd_input(struct at_client *at, struct net_buf *buf,
at->cmd_state >= AT_CMD_STATE_END) {
return -EINVAL;
}
- ret = cmd_parser_cb[at->cmd_state](at, buf, prefix, func);
+ ret = cmd_parser_cb[at->cmd_state](at, buf, prefix, func, type);
if (ret < 0) {
return ret;
}
/* Check for main state, the end of cmd parsing and return. */
- if (at->state == AT_STATE_START) {
+ if (at->state == AT_STATE_START ||
+ (at->state == AT_STATE_UNSOLICITED_CMD &&
+ type == AT_CMD_TYPE_UNSOLICITED)) {
return 0;
}
}
@@ -440,6 +452,11 @@ out:
return 0;
}
+void at_register_unsolicited(struct at_client *at, at_resp_cb_t unsolicited)
+{
+ at->unsolicited = unsolicited;
+}
+
void at_register(struct at_client *at, at_resp_cb_t resp, at_finish_cb_t finish)
{
at->resp = resp;
diff --git a/subsys/bluetooth/host/at.h b/subsys/bluetooth/host/at.h
index c3d0d9c27..2d62f1ebf 100644
--- a/subsys/bluetooth/host/at.h
+++ b/subsys/bluetooth/host/at.h
@@ -33,6 +33,11 @@ enum at_cmd_state {
AT_CMD_STATE_END
};
+enum at_cmd_type {
+ AT_CMD_TYPE_NORMAL,
+ AT_CMD_TYPE_UNSOLICITED
+};
+
struct at_client;
/* Callback at_resp_cb_t used to parse response value received for the
@@ -48,7 +53,8 @@ typedef int (*at_finish_cb_t)(struct at_client *at, struct net_buf *buf,
typedef int (*parse_val_t)(struct at_client *at);
typedef int (*handle_parse_input_t)(struct at_client *at, struct net_buf *buf);
typedef int (*handle_cmd_input_t)(struct at_client *at, struct net_buf *buf,
- const char *prefix, parse_val_t func);
+ const char *prefix, parse_val_t func,
+ enum at_cmd_type type);
struct at_client {
char *buf;
@@ -57,18 +63,21 @@ struct at_client {
uint8_t state;
uint8_t cmd_state;
at_resp_cb_t resp;
+ at_resp_cb_t unsolicited;
at_finish_cb_t finish;
};
/* Register the callback functions */
void at_register(struct at_client *at, at_resp_cb_t resp,
at_finish_cb_t finish);
+void at_register_unsolicited(struct at_client *at, at_resp_cb_t unsolicited);
int at_get_number(struct at_client *at, uint32_t *val);
/* This parsing will only works for non-fragmented net_buf */
int at_parse_input(struct at_client *at, struct net_buf *buf);
/* This command parsing will only works for non-fragmented net_buf */
int at_parse_cmd_input(struct at_client *at, struct net_buf *buf,
- const char *prefix, parse_val_t func);
+ const char *prefix, parse_val_t func,
+ enum at_cmd_type type);
int at_check_byte(struct net_buf *buf, char check_byte);
int at_list_get_range(struct at_client *at, uint32_t *min, uint32_t *max);
int at_list_get_string(struct at_client *at, char *name, uint8_t len);
diff --git a/subsys/bluetooth/host/hfp_hf.c b/subsys/bluetooth/host/hfp_hf.c
index d2b0cbc45..8da777bcd 100644
--- a/subsys/bluetooth/host/hfp_hf.c
+++ b/subsys/bluetooth/host/hfp_hf.c
@@ -112,7 +112,8 @@ int brsf_resp(struct at_client *hf_at, struct net_buf *buf)
BT_DBG("");
- err = at_parse_cmd_input(hf_at, buf, "BRSF", brsf_handle);
+ err = at_parse_cmd_input(hf_at, buf, "BRSF", brsf_handle,
+ AT_CMD_TYPE_NORMAL);
if (err < 0) {
/* Returning negative value is avoided before SLC connection
* established.
@@ -199,7 +200,8 @@ 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);
+ err = at_parse_cmd_input(hf_at, buf, "CIND", cind_handle,
+ AT_CMD_TYPE_NORMAL);
if (err < 0) {
BT_ERR("Error parsing CMD input");
hf_slc_error(hf_at);
@@ -296,7 +298,8 @@ int cind_status_resp(struct at_client *hf_at, struct net_buf *buf)
{
int err;
- err = at_parse_cmd_input(hf_at, buf, "CIND", cind_status_handle);
+ err = at_parse_cmd_input(hf_at, buf, "CIND", cind_status_handle,
+ AT_CMD_TYPE_NORMAL);
if (err < 0) {
BT_ERR("Error parsing CMD input");
hf_slc_error(hf_at);
@@ -305,6 +308,11 @@ int cind_status_resp(struct at_client *hf_at, struct net_buf *buf)
return 0;
}
+int unsolicited_cb(struct at_client *hf_at, struct net_buf *buf)
+{
+ return -EINVAL;
+}
+
int cmer_finish(struct at_client *hf_at, struct net_buf *buf,
enum at_result result)
{
@@ -329,6 +337,7 @@ int cind_status_finish(struct at_client *hf_at, struct net_buf *buf,
return -EINVAL;
}
+ at_register_unsolicited(hf_at, unsolicited_cb);
err = hfp_hf_send_cmd(hf, NULL, cmer_finish, "AT+CMER=3,0,0,1");
if (err < 0) {
hf_slc_error(hf_at);