// SPDX-License-Identifier: GPL-2.0 /* * This test covers the functionality of userspace-driven ALSA timers. Such timers * are purely virtual (so they don't directly depend on the hardware), and they could be * created and triggered by userspace applications. * * Author: Ivan Orlov <ivan.orlov0322@gmail.com>
*/ #include"../kselftest_harness.h" #include <sound/asound.h> #include <unistd.h> #include <fcntl.h> #include <limits.h> #include <sys/ioctl.h> #include <stdlib.h> #include <pthread.h> #include <string.h>
staticvoid *ticking_func(void *data)
{ int i; int *fd = (int *)data;
for (i = 0; i < TICKS_COUNT; i++) { /* Well, trigger the timer! */
ioctl(*fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL);
sleep(TIMER_FREQ_SEC);
}
return NULL;
}
staticenum timer_app_event parse_timer_output(constchar *s)
{ if (strstr(s, "Timer has started")) return TIMER_APP_STARTED; if (strstr(s, "Total ticks count")) return TIMER_APP_RESULT;
return TIMER_NO_EVENT;
}
staticint parse_timer_result(constchar *s)
{ char *end; long d;
d = strtol(s + RESULT_PREFIX_LEN, &end, 10); if (end == s + RESULT_PREFIX_LEN) return -1;
return d;
}
/* * This test triggers the timer and counts ticks at the same time. The amount * of the timer trigger calls should be equal to the amount of ticks received.
*/
TEST_F(timer_f, utimer) { char command[64];
pthread_t ticking_thread; int total_ticks = 0;
FILE *rfp; char *buf = malloc(TIMER_OUTPUT_BUF_LEN);
ASSERT_NE(buf, NULL);
/* The timeout should be the ticks interval * count of ticks + some delta */
sprintf(command, "./global-timer %d %d %d", SNDRV_TIMER_GLOBAL_UDRIVEN,
self->utimer_info->id, TICKS_COUNT * TIMER_FREQ_SEC + TICKS_RECORDING_DELTA);
rfp = popen(command, "r"); while (fgets(buf, TIMER_OUTPUT_BUF_LEN, rfp)) {
buf[TIMER_OUTPUT_BUF_LEN - 1] = 0; switch (parse_timer_output(buf)) { case TIMER_APP_STARTED: /* global-timer waits for timer to trigger, so start the ticking thread */
pthread_create(&ticking_thread, NULL, ticking_func,
&self->utimer_info->fd); break; case TIMER_APP_RESULT:
total_ticks = parse_timer_result(buf); break; case TIMER_NO_EVENT: break;
}
}
pthread_join(ticking_thread, NULL);
ASSERT_EQ(total_ticks, TICKS_COUNT);
pclose(rfp);
free(buf);
}
utimer_fd = ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, &wrong_timer);
ASSERT_LT(utimer_fd, 0); /* Check that id was not updated */
ASSERT_EQ(wrong_timer.id, UTIMER_DEFAULT_ID);
/* Test the NULL as an argument is processed correctly */
ASSERT_LT(ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, NULL), 0);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.