Add test: SCO CVSD Send - TX Timestamping --- tools/sco-tester.c | 96 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/tools/sco-tester.c b/tools/sco-tester.c index ecc65e092..d146a6937 100644 --- a/tools/sco-tester.c +++ b/tools/sco-tester.c @@ -31,6 +31,8 @@ #include "src/shared/mgmt.h" #include "src/shared/util.h" +#include "tester.h" + struct test_data { const void *test_data; struct mgmt *mgmt; @@ -38,15 +40,24 @@ struct test_data { struct hciemu *hciemu; enum hciemu_type hciemu_type; unsigned int io_id; + unsigned int err_io_id; int sk; bool disable_esco; bool enable_codecs; + int step; + struct tx_tstamp_data tx_ts; }; struct sco_client_data { int expect_err; const uint8_t *send_data; uint16_t data_len; + + /* Enable SO_TIMESTAMPING with these flags */ + uint32_t so_timestamping; + + /* Number of additional packets to send. */ + unsigned int repeat_send; }; static void print_debug(const char *str, void *user_data) @@ -227,8 +238,10 @@ static void test_data_free(void *test_data) break; \ user->hciemu_type = HCIEMU_TYPE_BREDRLE; \ user->io_id = 0; \ + user->err_io_id = 0; \ user->sk = -1; \ user->test_data = data; \ + user->step = 0; \ user->disable_esco = _disable_esco; \ user->enable_codecs = _enable_codecs; \ tester_add_full(name, data, \ @@ -265,6 +278,16 @@ static const struct sco_client_data connect_send_success = { .send_data = data }; +static const struct sco_client_data connect_send_tx_timestamping = { + .expect_err = 0, + .data_len = sizeof(data), + .send_data = data, + .so_timestamping = (SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_OPT_ID | + SOF_TIMESTAMPING_TX_SOFTWARE), + .repeat_send = 2, +}; + static void client_connectable_complete(uint16_t opcode, uint8_t status, const void *param, uint8_t len, void *user_data) @@ -595,6 +618,59 @@ static int connect_sco_sock(struct test_data *data, int sk) return 0; } +static gboolean recv_errqueue(GIOChannel *io, GIOCondition cond, + gpointer user_data) +{ + struct test_data *data = user_data; + const struct sco_client_data *scodata = data->test_data; + int sk = g_io_channel_unix_get_fd(io); + int err; + + data->step--; + + err = tx_tstamp_recv(&data->tx_ts, sk, scodata->data_len); + if (err > 0) + return TRUE; + else if (!err && !data->step) + tester_test_passed(); + else + tester_test_failed(); + + data->err_io_id = 0; + return FALSE; +} + +static void sco_tx_timestamping(struct test_data *data, GIOChannel *io) +{ + const struct sco_client_data *scodata = data->test_data; + int so = scodata->so_timestamping; + int sk; + int err; + unsigned int count; + + if (!(scodata->so_timestamping & SOF_TIMESTAMPING_TX_RECORD_MASK)) + return; + + sk = g_io_channel_unix_get_fd(io); + + tester_print("Enabling TX timestamping"); + + tx_tstamp_init(&data->tx_ts, scodata->so_timestamping); + + for (count = 0; count < scodata->repeat_send + 1; ++count) + data->step += tx_tstamp_expect(&data->tx_ts); + + err = setsockopt(sk, SOL_SOCKET, SO_TIMESTAMPING, &so, sizeof(so)); + if (err < 0) { + tester_warn("setsockopt SO_TIMESTAMPING: %s (%d)", + strerror(errno), errno); + tester_test_failed(); + return; + } + + data->err_io_id = g_io_add_watch(io, G_IO_ERR, recv_errqueue, data); +} + static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { @@ -619,10 +695,20 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond, if (scodata->send_data) { ssize_t ret; + unsigned int count; + + data->step = 0; - tester_print("Writing %u bytes of data", scodata->data_len); + sco_tx_timestamping(data, io); - ret = write(sk, scodata->send_data, scodata->data_len); + tester_print("Writing %u*%u bytes of data", + scodata->repeat_send + 1, scodata->data_len); + + for (count = 0; count < scodata->repeat_send + 1; ++count) { + ret = write(sk, scodata->send_data, scodata->data_len); + if (scodata->data_len != ret) + break; + } if (scodata->data_len != ret) { tester_warn("Failed to write %u bytes: %zu %s (%d)", scodata->data_len, ret, strerror(errno), @@ -633,7 +719,7 @@ static gboolean sco_connect_cb(GIOChannel *io, GIOCondition cond, if (-err != scodata->expect_err) tester_test_failed(); - else + else if (!data->step) tester_test_passed(); return FALSE; @@ -869,6 +955,10 @@ int main(int argc, char *argv[]) test_sco("SCO CVSD Send - Success", &connect_send_success, setup_powered, test_connect); + test_sco("SCO CVSD Send - TX Timestamping", + &connect_send_tx_timestamping, + setup_powered, test_connect); + test_offload_sco("Basic SCO Get Socket Option - Offload - Success", NULL, setup_powered, test_codecs_getsockopt); -- 2.44.0