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