brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · 32ee3ce Raw
165 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * This test covers the functionality of userspace-driven ALSA timers. Such timers4 * are purely virtual (so they don't directly depend on the hardware), and they could be5 * created and triggered by userspace applications.6 *7 * Author: Ivan Orlov <ivan.orlov0322@gmail.com>8 */9#include "../kselftest_harness.h"10#include <sound/asound.h>11#include <unistd.h>12#include <fcntl.h>13#include <limits.h>14#include <sys/ioctl.h>15#include <stdlib.h>16#include <pthread.h>17#include <string.h>18 19#define FRAME_RATE 800020#define PERIOD_SIZE 441021#define UTIMER_DEFAULT_ID -122#define UTIMER_DEFAULT_FD -123#define NANO 1000000000ULL24#define TICKS_COUNT 1025#define TICKS_RECORDING_DELTA 526#define TIMER_OUTPUT_BUF_LEN 102427#define TIMER_FREQ_SEC 128#define RESULT_PREFIX_LEN strlen("Total ticks count: ")29 30enum timer_app_event {31	TIMER_APP_STARTED,32	TIMER_APP_RESULT,33	TIMER_NO_EVENT,34};35 36FIXTURE(timer_f) {37	struct snd_timer_uinfo *utimer_info;38};39 40FIXTURE_SETUP(timer_f) {41	int timer_dev_fd;42 43	if (geteuid())44		SKIP(return, "This test needs root to run!");45 46	self->utimer_info = calloc(1, sizeof(*self->utimer_info));47	ASSERT_NE(NULL, self->utimer_info);48 49	/* Resolution is the time the period of frames takes in nanoseconds */50	self->utimer_info->resolution = (NANO / FRAME_RATE * PERIOD_SIZE);51 52	timer_dev_fd = open("/dev/snd/timer", O_RDONLY);53	ASSERT_GE(timer_dev_fd, 0);54 55	ASSERT_EQ(ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, self->utimer_info), 0);56	ASSERT_GE(self->utimer_info->fd, 0);57 58	close(timer_dev_fd);59}60 61FIXTURE_TEARDOWN(timer_f) {62	close(self->utimer_info->fd);63	free(self->utimer_info);64}65 66static void *ticking_func(void *data)67{68	int i;69	int *fd = (int *)data;70 71	for (i = 0; i < TICKS_COUNT; i++) {72		/* Well, trigger the timer! */73		ioctl(*fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL);74		sleep(TIMER_FREQ_SEC);75	}76 77	return NULL;78}79 80static enum timer_app_event parse_timer_output(const char *s)81{82	if (strstr(s, "Timer has started"))83		return TIMER_APP_STARTED;84	if (strstr(s, "Total ticks count"))85		return TIMER_APP_RESULT;86 87	return TIMER_NO_EVENT;88}89 90static int parse_timer_result(const char *s)91{92	char *end;93	long d;94 95	d = strtol(s + RESULT_PREFIX_LEN, &end, 10);96	if (end == s + RESULT_PREFIX_LEN)97		return -1;98 99	return d;100}101 102/*103 * This test triggers the timer and counts ticks at the same time. The amount104 * of the timer trigger calls should be equal to the amount of ticks received.105 */106TEST_F(timer_f, utimer) {107	char command[64];108	pthread_t ticking_thread;109	int total_ticks = 0;110	FILE *rfp;111	char *buf = malloc(TIMER_OUTPUT_BUF_LEN);112 113	ASSERT_NE(buf, NULL);114 115	/* The timeout should be the ticks interval * count of ticks + some delta */116	sprintf(command, "./global-timer %d %d %d", SNDRV_TIMER_GLOBAL_UDRIVEN,117		self->utimer_info->id, TICKS_COUNT * TIMER_FREQ_SEC + TICKS_RECORDING_DELTA);118 119	rfp = popen(command, "r");120	while (fgets(buf, TIMER_OUTPUT_BUF_LEN, rfp)) {121		buf[TIMER_OUTPUT_BUF_LEN - 1] = 0;122		switch (parse_timer_output(buf)) {123		case TIMER_APP_STARTED:124			/* global-timer waits for timer to trigger, so start the ticking thread */125			pthread_create(&ticking_thread, NULL, ticking_func,126				       &self->utimer_info->fd);127			break;128		case TIMER_APP_RESULT:129			total_ticks = parse_timer_result(buf);130			break;131		case TIMER_NO_EVENT:132			break;133		}134	}135	pthread_join(ticking_thread, NULL);136	ASSERT_EQ(total_ticks, TICKS_COUNT);137	pclose(rfp);138}139 140TEST(wrong_timers_test) {141	int timer_dev_fd;142	int utimer_fd;143	size_t i;144	struct snd_timer_uinfo wrong_timer = {145		.resolution = 0,146		.id = UTIMER_DEFAULT_ID,147		.fd = UTIMER_DEFAULT_FD,148	};149 150	timer_dev_fd = open("/dev/snd/timer", O_RDONLY);151	ASSERT_GE(timer_dev_fd, 0);152 153	utimer_fd = ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, &wrong_timer);154	ASSERT_LT(utimer_fd, 0);155	/* Check that id was not updated */156	ASSERT_EQ(wrong_timer.id, UTIMER_DEFAULT_ID);157 158	/* Test the NULL as an argument is processed correctly */159	ASSERT_LT(ioctl(timer_dev_fd, SNDRV_TIMER_IOCTL_CREATE, NULL), 0);160 161	close(timer_dev_fd);162}163 164TEST_HARNESS_MAIN165