[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240811202337.48381-3-ivan.orlov0322@gmail.com>
Date: Sun, 11 Aug 2024 21:23:35 +0100
From: Ivan Orlov <ivan.orlov0322@...il.com>
To: perex@...ex.cz,
tiwai@...e.com,
corbet@....net,
broonie@...nel.org,
shuah@...nel.org
Cc: Ivan Orlov <ivan.orlov0322@...il.com>,
linux-kselftest@...r.kernel.org,
linux-doc@...r.kernel.org,
linux-sound@...r.kernel.org,
linux-kernel@...r.kernel.org,
christophe.jaillet@...adoo.fr,
aholzinger@....de
Subject: [PATCH v4 2/4] Docs/sound: Add documentation for userspace-driven ALSA timers
Add the documentation which describes the new userspace-driven timers
API introduced in this patch series. The documentation contains:
- Description of userspace-driven ALSA timers, what they are for
- Description of the timers API
- Example of how the timers can be created and triggered
- How the timers can be used as a timer sources for snd-aloop module
Suggested-by: Axel Holzinger <aholzinger@....de>
Signed-off-by: Ivan Orlov <ivan.orlov0322@...il.com>
---
V1 -> V2:
- No changes
V2 -> V3:
- No changes
V3 -> V4:
- Update the userspace-driver ALSA timer structure name and fields
in correspondence with the latest changes (remove pcm-specific
fields from the structure description)
- Update the snd-aloop paragraph to provide a way to calculate the timer
resolution from frame rate and period size
Documentation/sound/index.rst | 1 +
Documentation/sound/utimers.rst | 125 ++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+)
create mode 100644 Documentation/sound/utimers.rst
diff --git a/Documentation/sound/index.rst b/Documentation/sound/index.rst
index 7e67e12730d3..c437f2a4bc85 100644
--- a/Documentation/sound/index.rst
+++ b/Documentation/sound/index.rst
@@ -13,6 +13,7 @@ Sound Subsystem Documentation
alsa-configuration
hd-audio/index
cards/index
+ utimers
.. only:: subproject and html
diff --git a/Documentation/sound/utimers.rst b/Documentation/sound/utimers.rst
new file mode 100644
index 000000000000..df1aeccd3285
--- /dev/null
+++ b/Documentation/sound/utimers.rst
@@ -0,0 +1,125 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======================
+Userspace-driven timers
+=======================
+
+:Author: Ivan Orlov <ivan.orlov0322@...il.com>
+
+Preface
+=======
+
+This document describes the userspace-driven timers: virtual ALSA timers
+which could be created and controlled by userspace applications using
+IOCTL calls. Such timers could be useful when synchronizing audio
+stream with timer sources which we don't have ALSA timers exported for
+(e.g. PTP clocks), and when synchronizing the audio stream going through
+two virtual sound devices using ``snd-aloop`` (for instance, when
+we have a network application sending frames to one snd-aloop device,
+and another sound application listening on the other end of snd-aloop).
+
+Enabling userspace-driven timers
+================================
+
+The userspace-driven timers could be enabled in the kernel using the
+``CONFIG_SND_UTIMER`` configuration option. It depends on the
+``CONFIG_SND_TIMER`` option, so it also should be enabled.
+
+Userspace-driven timers API
+===========================
+
+Userspace application can create a userspace-driven ALSA timer by
+executing the ``SNDRV_TIMER_IOCTL_CREATE`` ioctl call on the
+``/dev/snd/timer`` device file descriptor. The ``snd_timer_uinfo``
+structure should be passed as an ioctl argument:
+
+::
+
+ struct snd_timer_uinfo {
+ __u64 resolution;
+ unsigned int id;
+ unsigned char reserved[16];
+ }
+
+The ``resolution`` field sets the desired resolution in nanoseconds for
+the virtual timer. ``resolution`` field simply provides an information
+about the virtual timer, but does not affect the timing itself. ``id``
+field gets overwritten by the ioctl, and the identifier you get in this
+field after the call can be used as a timer subdevice number when
+passing the timer to ``snd-aloop`` kernel module or other userspace
+applications. There could be up to 128 userspace-driven timers in the
+system at one moment of time, thus the id value ranges from 0 to 127.
+
+Besides from overwriting the ``snd_timer_uinfo`` struct, ioctl returns
+a timer file descriptor, which can be used to trigger the timer. This
+guarantees that the timer can only be triggered by the process which
+created it. The timer then can be triggered with
+``SNDRV_TIMER_IOCTL_TRIGGER`` ioctl call on the timer file descriptor.
+
+So, the example code for creating and triggering the timer would be:
+
+::
+
+ static const struct snd_timer_uinfo utimer_info = {
+ /* Timer is going to tick (presumably) every 1000000 ns */
+ .resolution = 1000000ULL,
+ .id = -1,
+ };
+
+ int timer_device_fd = open("/dev/snd/timer", O_RDWR | O_CLOEXEC);
+ int utimer_fd = ioctl(timer_device_fd, SNDRV_TIMER_IOCTL_CREATE, &utimer_info);
+
+ if (utimer_fd < 0) {
+ perror("Failed to create the timer");
+ return -1;
+ }
+
+ ...
+
+ /*
+ * Now we want to trigger the timer. Callbacks of all of the
+ * timer instances binded to this timer will be executed after
+ * this call.
+ */
+ ioctl(utimer_fd, SNDRV_TIMER_IOCTL_TRIGGER, NULL);
+
+ ...
+
+ /* Now, destroy the timer */
+ close(utimer_fd);
+
+
+More detailed example of creating and ticking the timer could be found
+in the utimer ALSA selftest.
+
+Userspace-driven timers and snd-aloop
+-------------------------------------
+
+Userspace-driven timers could be easily used with ``snd-aloop`` module
+when synchronizing two sound applications on both ends of the virtual
+sound loopback. For instance, if one of the applications receives sound
+frames from network and sends them to snd-aloop pcm device, and another
+application listens for frames on the other snd-aloop pcm device, it
+makes sense that the ALSA middle layer should initiate a data
+transaction when the new period of data is received through network, but
+not when the certain amount of jiffies elapses. Userspace-driven ALSA
+timers could be used to achieve this.
+
+To use userspace-driven ALSA timer as a timer source of snd-aloop, pass
+the following string as the snd-aloop ``timer_source`` parameter:
+
+::
+
+ # modprobe snd-aloop timer_source="-1.4.<utimer_id>"
+
+Where ``utimer_id`` is the id of the timer you created with
+``SNDRV_TIMER_IOCTL_CREATE``, and ``4`` is the number of
+userspace-driven timers device (``SNDRV_TIMER_GLOBAL_UDRIVEN``).
+
+``resolution`` for the userspace-driven ALSA timer used with snd-aloop
+should be calculated as ``1000000000ULL / frame_rate * period_size`` as
+the timer is going to tick every time a new period of frames is ready.
+
+After that, each time you trigger the timer with
+``SNDRV_TIMER_IOCTL_TRIGGER`` the new period of data will be transferred
+from one snd-aloop device to another.
--
2.34.1
Powered by blists - more mailing lists