Patchset contains sdp search fix and channel connect and destroy
test cases.
Ravi kumar Veeramally (5):
android/health: Avoid multiple times of sdp search
android/tester: Add HDP Connect Source Reliable Channel test case
android/tester: Add HDP Destroy Source Reliable Channel test case
android/tester: Add HDP Connect Sink Streaming Channel test case
android/tester: Add HDP Destroy Sink Streaming Channel test case
android/health.c | 75 ++++++-----
android/tester-hdp.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 407 insertions(+), 35 deletions(-)
--
1.9.1
Hi Ravi,
On Wednesday 27 August 2014 15:38:55 Ravi kumar Veeramally wrote:
> Patchset contains sdp search fix and channel connect and destroy
> test cases.
>
> Ravi kumar Veeramally (5):
> android/health: Avoid multiple times of sdp search
> android/tester: Add HDP Connect Source Reliable Channel test case
> android/tester: Add HDP Destroy Source Reliable Channel test case
> android/tester: Add HDP Connect Sink Streaming Channel test case
> android/tester: Add HDP Destroy Sink Streaming Channel test case
>
> android/health.c | 75 ++++++-----
> android/tester-hdp.c | 367
> +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 407
> insertions(+), 35 deletions(-)
All patches applied, thanks.
--
Szymon K. Janc
[email protected]
---
android/tester-hdp.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/android/tester-hdp.c b/android/tester-hdp.c
index 7609683..ca8cb51 100644
--- a/android/tester-hdp.c
+++ b/android/tester-hdp.c
@@ -391,6 +391,42 @@ static void hdp_destroy_source_reliable_action(void)
schedule_action_verification(step);
}
+static void hdp_connect_sink_reliable_action(void)
+{
+ struct test_data *data = tester_get_data();
+ const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu);
+ struct step *step = g_new0(struct step, 1);
+ bt_bdaddr_t bdaddr;
+ int app_id, channel_id, mdep_cfg_index;
+
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ app_id = 1;
+ mdep_cfg_index = 0;
+ channel_id = 0;
+ step->action_status = data->if_hdp->connect_channel(app_id, &bdaddr,
+ mdep_cfg_index, &channel_id);
+
+ schedule_action_verification(step);
+}
+
+static void hdp_connect_sink_stream_action(void)
+{
+ struct test_data *data = tester_get_data();
+ const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu);
+ struct step *step = g_new0(struct step, 1);
+ bt_bdaddr_t bdaddr;
+ int app_id, channel_id, mdep_cfg_index;
+
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ app_id = 1;
+ mdep_cfg_index = 1;
+ channel_id = 0;
+ step->action_status = data->if_hdp->connect_channel(app_id, &bdaddr,
+ mdep_cfg_index, &channel_id);
+
+ schedule_action_verification(step);
+}
+
static struct test_case test_cases[] = {
TEST_CASE_BREDRLE("HDP Init",
ACTION_SUCCESS(dummy_action, NULL),
@@ -466,6 +502,29 @@ static struct test_case test_cases[] = {
CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
BTHL_CONN_STATE_DESTROYED),
),
+ TEST_CASE_BREDRLE("HDP Connect Sink Streaming Channel",
+ ACTION_SUCCESS(bluetooth_enable_action, NULL),
+ CALLBACK_STATE(CB_BT_ADAPTER_STATE_CHANGED, BT_STATE_ON),
+ ACTION_SUCCESS(emu_setup_powered_remote_action, NULL),
+ ACTION_SUCCESS(emu_set_ssp_mode_action, NULL),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_sdp_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_cc_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_dc_data),
+ ACTION_SUCCESS(hdp_register_sink_stream_app_action, NULL),
+ CALLBACK_HDP_APP_REG_STATE(CB_HDP_APP_REG_STATE, 1,
+ BTHL_APP_REG_STATE_REG_SUCCESS),
+ ACTION_SUCCESS(hdp_connect_sink_reliable_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTING),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTED),
+ ACTION_SUCCESS(hdp_connect_sink_stream_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 2, 1,
+ BTHL_CONN_STATE_CONNECTED),
+ ),
};
struct queue *get_hdp_tests(void)
--
1.9.1
---
android/tester-hdp.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/android/tester-hdp.c b/android/tester-hdp.c
index ca8cb51..bb73681 100644
--- a/android/tester-hdp.c
+++ b/android/tester-hdp.c
@@ -427,6 +427,24 @@ static void hdp_connect_sink_stream_action(void)
schedule_action_verification(step);
}
+static void hdp_destroy_sink_reliable_action(void)
+{
+ struct test_data *data = tester_get_data();
+ struct step *step = g_new0(struct step, 1);
+
+ step->action_status = data->if_hdp->destroy_channel(1);
+ schedule_action_verification(step);
+}
+
+static void hdp_destroy_sink_stream_action(void)
+{
+ struct test_data *data = tester_get_data();
+ struct step *step = g_new0(struct step, 1);
+
+ step->action_status = data->if_hdp->destroy_channel(2);
+ schedule_action_verification(step);
+}
+
static struct test_case test_cases[] = {
TEST_CASE_BREDRLE("HDP Init",
ACTION_SUCCESS(dummy_action, NULL),
@@ -525,6 +543,35 @@ static struct test_case test_cases[] = {
CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 2, 1,
BTHL_CONN_STATE_CONNECTED),
),
+ TEST_CASE_BREDRLE("HDP Destroy Sink Streaming Channel",
+ ACTION_SUCCESS(bluetooth_enable_action, NULL),
+ CALLBACK_STATE(CB_BT_ADAPTER_STATE_CHANGED, BT_STATE_ON),
+ ACTION_SUCCESS(emu_setup_powered_remote_action, NULL),
+ ACTION_SUCCESS(emu_set_ssp_mode_action, NULL),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_sdp_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_cc_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_dc_data),
+ ACTION_SUCCESS(hdp_register_sink_stream_app_action, NULL),
+ CALLBACK_HDP_APP_REG_STATE(CB_HDP_APP_REG_STATE, 1,
+ BTHL_APP_REG_STATE_REG_SUCCESS),
+ ACTION_SUCCESS(hdp_connect_sink_reliable_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTING),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTED),
+ ACTION_SUCCESS(hdp_connect_sink_stream_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 2, 1,
+ BTHL_CONN_STATE_CONNECTED),
+ ACTION_SUCCESS(hdp_destroy_sink_reliable_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_DESTROYED),
+ ACTION_SUCCESS(hdp_destroy_sink_stream_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 2, 1,
+ BTHL_CONN_STATE_DESTROYED),
+ ),
};
struct queue *get_hdp_tests(void)
--
1.9.1
---
android/tester-hdp.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/android/tester-hdp.c b/android/tester-hdp.c
index c1eba7e..7609683 100644
--- a/android/tester-hdp.c
+++ b/android/tester-hdp.c
@@ -382,6 +382,15 @@ static void hdp_connect_source_reliable_action(void)
schedule_action_verification(step);
}
+static void hdp_destroy_source_reliable_action(void)
+{
+ struct test_data *data = tester_get_data();
+ struct step *step = g_new0(struct step, 1);
+
+ step->action_status = data->if_hdp->destroy_channel(1);
+ schedule_action_verification(step);
+}
+
static struct test_case test_cases[] = {
TEST_CASE_BREDRLE("HDP Init",
ACTION_SUCCESS(dummy_action, NULL),
@@ -434,7 +443,29 @@ static struct test_case test_cases[] = {
CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
BTHL_CONN_STATE_CONNECTED),
),
-
+ TEST_CASE_BREDRLE("HDP Destroy Source Reliable Channel",
+ ACTION_SUCCESS(bluetooth_enable_action, NULL),
+ CALLBACK_STATE(CB_BT_ADAPTER_STATE_CHANGED, BT_STATE_ON),
+ ACTION_SUCCESS(emu_setup_powered_remote_action, NULL),
+ ACTION_SUCCESS(emu_set_ssp_mode_action, NULL),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_sdp_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_cc_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_dc_data),
+ ACTION_SUCCESS(hdp_register_source_reliable_app_action, NULL),
+ CALLBACK_HDP_APP_REG_STATE(CB_HDP_APP_REG_STATE, 1,
+ BTHL_APP_REG_STATE_REG_SUCCESS),
+ ACTION_SUCCESS(hdp_connect_source_reliable_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTING),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTED),
+ ACTION_SUCCESS(hdp_destroy_source_reliable_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_DESTROYED),
+ ),
};
struct queue *get_hdp_tests(void)
--
1.9.1
First it searches for control and data PSMs and then search again
for remote mdep id. It would be better to search remote mdep id
and cache in first time itself. Patch avoids load of sdp search
request for second time.
---
android/health.c | 75 ++++++++++++++++++++++++++++++--------------------------
1 file changed, 40 insertions(+), 35 deletions(-)
diff --git a/android/health.c b/android/health.c
index 2c05fb8..abf01b4 100644
--- a/android/health.c
+++ b/android/health.c
@@ -1723,36 +1723,48 @@ static bool get_mdep_from_rec(const sdp_record_t *rec, uint8_t role,
return false;
}
-static void get_mdep_cb(sdp_list_t *recs, int err, gpointer user_data)
+static bool get_remote_mdep(sdp_list_t *recs, struct health_channel *channel)
{
- struct health_channel *channel = user_data;
struct health_app *app;
struct mdep_cfg *mdep;
- uint8_t mdep_id, type;
- GError *gerr = NULL;
-
- if (err < 0 || !recs) {
- error("health: error getting remote SDP records");
- goto fail;
- }
+ uint8_t mdep_id;
app = queue_find(apps, match_app_by_id,
INT_TO_PTR(channel->dev->app_id));
if (!app)
- goto fail;
+ return false;
mdep = queue_find(app->mdeps, match_mdep_by_id,
INT_TO_PTR(channel->mdep_id));
if (!mdep)
- goto fail;
+ return false;
if (!get_mdep_from_rec(recs->data, mdep->role, mdep->data_type,
&mdep_id)) {
error("health: no matching MDEP: %u", channel->mdep_id);
- goto fail;
+ return false;
}
channel->remote_mdep = mdep_id;
+ return true;
+}
+
+static bool create_mdl(struct health_channel *channel)
+{
+ struct health_app *app;
+ struct mdep_cfg *mdep;
+ uint8_t type;
+ GError *gerr = NULL;
+
+ app = queue_find(apps, match_app_by_id,
+ INT_TO_PTR(channel->dev->app_id));
+ if (!app)
+ return false;
+
+ mdep = queue_find(app->mdeps, match_mdep_by_id,
+ INT_TO_PTR(channel->mdep_id));
+ if (!mdep)
+ return false;
if (mdep->role == HAL_HEALTH_MDEP_ROLE_SOURCE)
type = channel->type;
@@ -1763,25 +1775,10 @@ static void get_mdep_cb(sdp_list_t *recs, int err, gpointer user_data)
type, create_mdl_cb, channel, NULL, &gerr)) {
error("health: error creating mdl %s", gerr->message);
g_error_free(gerr);
- goto fail;
+ return false;
}
- return;
-
-fail:
- destroy_channel(channel);
-}
-
-static int get_mdep(struct health_channel *channel)
-{
- uuid_t uuid;
-
- DBG("");
-
- bt_string2uuid(&uuid, HDP_UUID);
-
- return bt_search_service(&adapter_addr, &channel->dev->dst, &uuid,
- get_mdep_cb, channel, NULL, 0);
+ return true;
}
static bool set_mcl_cb(struct mcap_mcl *mcl, gpointer user_data, GError **err)
@@ -1821,10 +1818,8 @@ static void create_mcl_cb(struct mcap_mcl *mcl, GError *err, gpointer data)
goto fail;
}
- if (get_mdep(channel) < 0) {
- error("health: error getting remote MDEP from SDP record");
+ if (!create_mdl(channel))
goto fail;
- }
return;
@@ -1854,6 +1849,11 @@ static void search_cb(sdp_list_t *recs, int err, gpointer data)
goto fail;
}
+ if (!get_remote_mdep(recs, channel)) {
+ error("health: Can't get remote MDEP data");
+ goto fail;
+ }
+
if (!mcap_create_mcl(mcap, &channel->dev->dst, channel->dev->ccpsm,
create_mcl_cb, channel, NULL, &gerr)) {
error("health: error creating mcl %s", gerr->message);
@@ -1861,7 +1861,6 @@ static void search_cb(sdp_list_t *recs, int err, gpointer data)
goto fail;
}
- send_channel_state_notify(channel, HAL_HEALTH_CHANNEL_CONNECTING, -1);
return;
fail:
@@ -1871,13 +1870,19 @@ fail:
static int connect_mcl(struct health_channel *channel)
{
uuid_t uuid;
+ int err;
DBG("");
bt_string2uuid(&uuid, HDP_UUID);
- return bt_search_service(&adapter_addr, &channel->dev->dst, &uuid,
+ err = bt_search_service(&adapter_addr, &channel->dev->dst, &uuid,
search_cb, channel, NULL, 0);
+ if (!err)
+ send_channel_state_notify(channel,
+ HAL_HEALTH_CHANNEL_CONNECTING, -1);
+
+ return err;
}
static struct health_app *get_app(uint16_t app_id)
@@ -1944,7 +1949,7 @@ static void bt_health_connect_channel(const void *buf, uint16_t len)
goto fail;
/* create mdl if it does not exists */
- if (!channel->mdl && get_mdep(channel) < 0)
+ if (!channel->mdl && !create_mdl(channel) < 0)
goto fail;
/* reconnect mdl if it exists */
--
1.9.1
---
android/tester-hdp.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 230 insertions(+)
diff --git a/android/tester-hdp.c b/android/tester-hdp.c
index bfe8a99..c1eba7e 100644
--- a/android/tester-hdp.c
+++ b/android/tester-hdp.c
@@ -28,6 +28,17 @@ typedef enum {
HDP_APP_SOURCE_STREAM,
} hdp_app_reg_type;
+struct emu_cid_data {
+ uint16_t sdp_handle;
+ uint16_t sdp_cid;
+ uint16_t ctrl_handle;
+ uint16_t ctrl_cid;
+ uint16_t data_handle;
+ uint16_t data_cid;
+};
+
+struct emu_cid_data cid_data;
+
static struct queue *list; /* List of hdp test cases */
static bthl_reg_param_t *create_app(hdp_app_reg_type type)
@@ -173,6 +184,204 @@ static void hdp_unregister_app_action(void)
schedule_action_verification(step);
}
+static uint8_t hdp_rsp_pdu[] = { 0x07, /* PDU id */
+ 0x00, 0x00, /* Transaction id */
+ 0x01, 0xc8, /* Response length */
+ 0x01, 0xc5, /* Attributes length */
+ 0x36, 0x01, 0xc2, 0x36, 0x01, 0xbf, 0x09, 0x00, 0x00,
+ 0x0a, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x01, 0x35,
+ 0x03, 0x19, 0x14, 0x01, 0x09, 0x00, 0x04, 0x35, 0x10,
+ 0x35, 0x06, 0x19, 0x01, 0x00, 0x09, 0x10, 0x01, 0x35,
+ 0x06, 0x19, 0x00, 0x1e, 0x09, 0x01, 0x00, 0x09, 0x00,
+ 0x09, 0x35, 0x08, 0x35, 0x06, 0x19, 0x14, 0x00, 0x09,
+ 0x01, 0x01, 0x09, 0x00, 0x0d, 0x35, 0x0f, 0x35, 0x0d,
+ 0x35, 0x06, 0x19, 0x01, 0x00, 0x09, 0x10, 0x03, 0x35,
+ 0x03, 0x19, 0x00, 0x1f, 0x09, 0x01, 0x00, 0x25, 0x03,
+ 0x48, 0x44, 0x50, 0x09, 0x01, 0x01, 0x25, 0x28, 0x43,
+ 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x64,
+ 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x72, 0x65, 0x8b, 0x6c, 0x61, 0x79,
+ 0x20, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x20, 0x64,
+ 0x61, 0x74, 0x61, 0x09, 0x01, 0x02, 0x25, 0x0d, 0x42,
+ 0x4c, 0x55, 0x45, 0x54, 0x4f, 0x4f, 0x54, 0x48, 0x20,
+ 0x53, 0x49, 0x47, 0x09, 0x02, 0x00, 0x36, 0x01, 0x22,
+ 0x35, 0x18, 0x08, 0x01, 0x09, 0x10, 0x04, 0x08, 0x00,
+ 0x25, 0x0f, 0x50, 0x75, 0x6c, 0x73, 0x65, 0x20, 0x4f,
+ 0x78, 0x69, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x0d, 0x35,
+ 0x20, 0x08, 0x02, 0x09, 0x10, 0x07, 0x08, 0x00, 0x25,
+ 0x17, 0x42, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x50, 0x72,
+ 0x65, 0x73, 0x73, 0x75, 0x72, 0x65, 0x20, 0x4d, 0x6f,
+ 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x0d, 0x35, 0x1a, 0x08,
+ 0x03, 0x09, 0x10, 0x08, 0x08, 0x00, 0x25, 0x11, 0x42,
+ 0x6f, 0x64, 0x79, 0x20, 0x54, 0x68, 0x65, 0x72, 0x6d,
+ 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x0d, 0x35, 0x1e,
+ 0x08, 0x04, 0x09, 0x10, 0x0f, 0x08, 0x00, 0x25, 0x15,
+ 0x42, 0x6f, 0x64, 0x79, 0x20, 0x57, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x09,
+ 0x09, 0x09, 0x0d, 0x35, 0x17, 0x08, 0x05, 0x09, 0x10,
+ 0x11, 0x08, 0x00, 0x25, 0x0e, 0x47, 0x6c, 0x75, 0x63,
+ 0x6f, 0x73, 0x65, 0x20, 0x4d, 0x65, 0x74, 0x65, 0x72,
+ 0x0d, 0x35, 0x18, 0x08, 0x06, 0x09, 0x10, 0x04, 0x08,
+ 0x01, 0x25, 0x0f, 0x50, 0x75, 0x6c, 0x73, 0x65, 0x20,
+ 0x4f, 0x78, 0x69, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x0d,
+ 0x35, 0x20, 0x08, 0x07, 0x09, 0x10, 0x07, 0x08, 0x01,
+ 0x25, 0x17, 0x42, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x50,
+ 0x72, 0x65, 0x73, 0x73, 0x75, 0x72, 0x65, 0x20, 0x4d,
+ 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x0d, 0x35, 0x1a,
+ 0x08, 0x08, 0x09, 0x10, 0x08, 0x08, 0x01, 0x25, 0x11,
+ 0x42, 0x6f, 0x64, 0x79, 0x20, 0x54, 0x68, 0x65, 0x72,
+ 0x6d, 0x6f, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x0d, 0x35,
+ 0x1e, 0x08, 0x09, 0x09, 0x10, 0x0f, 0x08, 0x01, 0x25,
+ 0x15, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x57, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x53, 0x63, 0x61, 0x6c, 0x65,
+ 0x09, 0x09, 0x09, 0x0d, 0x35, 0x17, 0x08, 0x0a, 0x09,
+ 0x10, 0x11, 0x08, 0x01, 0x25, 0x0e, 0x47, 0x6c, 0x75,
+ 0x63, 0x6f, 0x73, 0x65, 0x20, 0x4d, 0x65, 0x74, 0x65,
+ 0x72, 0x0d, 0x09, 0x03, 0x01, 0x08, 0x01, 0x09, 0x03,
+ 0x02, 0x08, 0x00,
+ 0x00 };
+
+static void hdp_sdp_cid_hook_cb(const void *data, uint16_t len, void *user_data)
+{
+ struct test_data *t_data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(t_data->hciemu);
+ struct emu_cid_data *cid_data = user_data;
+
+ hdp_rsp_pdu[1] = ((uint8_t *) data)[1];
+ hdp_rsp_pdu[2] = ((uint8_t *) data)[2];
+
+ bthost_send_cid(bthost, cid_data->sdp_handle, cid_data->sdp_cid,
+ hdp_rsp_pdu, sizeof(hdp_rsp_pdu));
+}
+
+static void hdp_sdp_search_cb(uint16_t handle, uint16_t cid, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+ cid_data.sdp_handle = handle;
+ cid_data.sdp_cid = cid;
+
+ bthost_add_cid_hook(bthost, handle, cid, hdp_sdp_cid_hook_cb,
+ &cid_data);
+}
+
+static void mcap_ctrl_cid_hook_cb(const void *data, uint16_t len,
+ void *user_data)
+{
+ struct test_data *t_data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(t_data->hciemu);
+ uint8_t crt_rsp[5], del_rsp[4], config;
+ uint8_t opcode = ((uint8_t *) data)[0];
+ static bool reliable = false;
+
+ switch (opcode) {
+ case 0x01: /* MD_CREATE_MDL_REQ */
+ crt_rsp[0] = 0x02; /* MD_CREATE_MDL_RSP */
+ crt_rsp[1] = 0x00; /* Response code - Success */
+ crt_rsp[2] = ((uint8_t *) data)[1]; /* mdlid */
+ crt_rsp[3] = ((uint8_t *) data)[2];
+ config = ((uint8_t *) data)[4];
+
+ if (config == 0x00) {
+ if (!reliable) {
+ crt_rsp[4] = 0x01;
+ reliable = true;
+ } else {
+ crt_rsp[4] = 0x02;
+ reliable = false;
+ }
+ } else {
+ crt_rsp[4] = config;
+ }
+
+ bthost_send_cid(bthost, cid_data.ctrl_handle,
+ cid_data.ctrl_cid,
+ crt_rsp, sizeof(crt_rsp));
+ break;
+ case 0x03: /* MD_RECONNECT_MDL_REQ */
+ case 0x05: /* MD_ABORT_MDL_REQ */
+ break;
+ case 0x07: /* MD_DELETE_MDL_REQ */
+ del_rsp[0] = 0x08; /* MD_DELETE_MDL_RSP */
+ del_rsp[1] = 0x00; /* Response code - Success */
+ del_rsp[2] = ((uint8_t *) data)[1]; /* mdlid */
+ del_rsp[3] = ((uint8_t *) data)[2];
+ bthost_send_cid(bthost, cid_data.ctrl_handle,
+ cid_data.ctrl_cid,
+ del_rsp, sizeof(del_rsp));
+ break;
+ }
+}
+
+static void mcap_ctrl_connect_cb(uint16_t handle, uint16_t cid, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+ cid_data.ctrl_handle = handle;
+ cid_data.ctrl_cid = cid;
+
+ bthost_add_cid_hook(bthost, handle, cid, mcap_ctrl_cid_hook_cb,
+ &cid_data);
+}
+
+static void mcap_data_cid_hook_cb(const void *data, uint16_t len,
+ void *user_data)
+{
+}
+
+static void mcap_data_connect_cb(uint16_t handle, uint16_t cid, void *user_data)
+{
+ struct test_data *data = tester_get_data();
+ struct bthost *bthost = hciemu_client_get_host(data->hciemu);
+
+ cid_data.data_handle = handle;
+ cid_data.data_cid = cid;
+
+ bthost_add_cid_hook(bthost, handle, cid, mcap_data_cid_hook_cb,
+ &cid_data);
+}
+
+/* Emulate SDP (PSM = 1) */
+static struct emu_set_l2cap_data l2cap_setup_sdp_data = {
+ .psm = 1,
+ .func = hdp_sdp_search_cb,
+ .user_data = NULL,
+};
+
+/* Emulate Control Channel (PSM = 0x1001) */
+static struct emu_set_l2cap_data l2cap_setup_cc_data = {
+ .psm = 0x1001,
+ .func = mcap_ctrl_connect_cb,
+ .user_data = NULL,
+};
+
+/* Emulate Data Channel (PSM = 0x1003) */
+static struct emu_set_l2cap_data l2cap_setup_dc_data = {
+ .psm = 0x1003,
+ .func = mcap_data_connect_cb,
+ .user_data = NULL,
+};
+
+static void hdp_connect_source_reliable_action(void)
+{
+ struct test_data *data = tester_get_data();
+ const uint8_t *hid_addr = hciemu_get_client_bdaddr(data->hciemu);
+ struct step *step = g_new0(struct step, 1);
+ bt_bdaddr_t bdaddr;
+ int app_id, channel_id, mdep_cfg_index;
+
+ bdaddr2android((const bdaddr_t *) hid_addr, &bdaddr);
+ app_id = 1;
+ mdep_cfg_index = 0;
+ channel_id = 0;
+ step->action_status = data->if_hdp->connect_channel(app_id, &bdaddr,
+ mdep_cfg_index, &channel_id);
+
+ schedule_action_verification(step);
+}
+
static struct test_case test_cases[] = {
TEST_CASE_BREDRLE("HDP Init",
ACTION_SUCCESS(dummy_action, NULL),
@@ -205,6 +414,27 @@ static struct test_case test_cases[] = {
CALLBACK_HDP_APP_REG_STATE(CB_HDP_APP_REG_STATE, 1,
BTHL_APP_REG_STATE_DEREG_SUCCESS),
),
+ TEST_CASE_BREDRLE("HDP Connect Source Reliable Channel",
+ ACTION_SUCCESS(bluetooth_enable_action, NULL),
+ CALLBACK_STATE(CB_BT_ADAPTER_STATE_CHANGED, BT_STATE_ON),
+ ACTION_SUCCESS(emu_setup_powered_remote_action, NULL),
+ ACTION_SUCCESS(emu_set_ssp_mode_action, NULL),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_sdp_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_cc_data),
+ ACTION_SUCCESS(emu_add_l2cap_server_action,
+ &l2cap_setup_dc_data),
+ ACTION_SUCCESS(hdp_register_source_reliable_app_action, NULL),
+ CALLBACK_HDP_APP_REG_STATE(CB_HDP_APP_REG_STATE, 1,
+ BTHL_APP_REG_STATE_REG_SUCCESS),
+ ACTION_SUCCESS(hdp_connect_source_reliable_action, NULL),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTING),
+ CALLBACK_HDP_CHANNEL_STATE(CB_HDP_CHANNEL_STATE, 1, 1, 0,
+ BTHL_CONN_STATE_CONNECTED),
+ ),
+
};
struct queue *get_hdp_tests(void)
--
1.9.1