xref: /third_party/alsa-lib/src/timer/timer.c (revision d5ac70f0)
1/**
2 * \file timer/timer.c
3 * \brief Timer Interface
4 * \author Jaroslav Kysela <perex@perex.cz>
5 * \date 1998-2001
6 *
7 * Timer Interface is designed to access timers.
8 * See \ref timer page for more details.
9 */
10/*
11 *  Timer Interface - main file
12 *  Copyright (c) 1998-2001 by Jaroslav Kysela <perex@perex.cz>
13 *
14 *
15 *   This library is free software; you can redistribute it and/or modify
16 *   it under the terms of the GNU Lesser General Public License as
17 *   published by the Free Software Foundation; either version 2.1 of
18 *   the License, or (at your option) any later version.
19 *
20 *   This program is distributed in the hope that it will be useful,
21 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
22 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 *   GNU Lesser General Public License for more details.
24 *
25 *   You should have received a copy of the GNU Lesser General Public
26 *   License along with this library; if not, write to the Free Software
27 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28 *
29 */
30
31/*! \page timer Timer interface
32
33<P> Timer interface is designed to use internal timers in sound hardware, but
34it can be driven with any timer.
35
36\section timer_general_overview General overview
37
38The timer implementation uses ring buffer to store information about timing
39events. In this buffer is recorded count of ticks and current tick resolution
40in nanoseconds.
41
42\section timer_open Opening
43
44Timer devices can be opened in two ways. When #SND_TIMER_OPEN_NONBLOCK flag
45is used, then the open functions return immediately with -EBUSY error code when
46resources are occupied with another application. When #SND_TIMER_OPEN_NONBLOCK
47is not used (by default) the open functions block the application requesting
48device until resources are not free.
49
50\section timer_events Events
51
52Events are read via snd_timer_read() function.
53
54\section timer_examples Examples
55
56The full featured examples with cross-links:
57
58\par Simple timer test program
59\link example_test_timer example code \endlink
60\par
61This example shows opening a timer device and reading of timer events.
62
63*/
64
65/**
66 * \example ../test/timer.c
67 * \anchor example_test_timer
68 */
69
70#include "timer_local.h"
71
72#include <signal.h>
73
74static int snd_timer_open_conf(snd_timer_t **timer,
75			       const char *name, snd_config_t *timer_root,
76			       snd_config_t *timer_conf, int mode)
77{
78	const char *str;
79	char buf[256], errbuf[256];
80	int err;
81	snd_config_t *conf, *type_conf = NULL;
82	snd_config_iterator_t i, next;
83	const char *id;
84	const char *lib = NULL, *open_name = NULL;
85	int (*open_func)(snd_timer_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
86#ifndef PIC
87	extern void *snd_timer_open_symbols(void);
88#endif
89	void *h = NULL;
90	if (snd_config_get_type(timer_conf) != SND_CONFIG_TYPE_COMPOUND) {
91		if (name)
92			SNDERR("Invalid type for TIMER %s definition", name);
93		else
94			SNDERR("Invalid type for TIMER definition");
95		return -EINVAL;
96	}
97	err = snd_config_search(timer_conf, "type", &conf);
98	if (err < 0) {
99		SNDERR("type is not defined");
100		return err;
101	}
102	err = snd_config_get_id(conf, &id);
103	if (err < 0) {
104		SNDERR("unable to get id");
105		return err;
106	}
107	err = snd_config_get_string(conf, &str);
108	if (err < 0) {
109		SNDERR("Invalid type for %s", id);
110		return err;
111	}
112	err = snd_config_search_definition(timer_root, "timer_type", str, &type_conf);
113	if (err >= 0) {
114		if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
115			SNDERR("Invalid type for TIMER type %s definition", str);
116			goto _err;
117		}
118		snd_config_for_each(i, next, type_conf) {
119			snd_config_t *n = snd_config_iterator_entry(i);
120			const char *id;
121			if (snd_config_get_id(n, &id) < 0)
122				continue;
123			if (strcmp(id, "comment") == 0)
124				continue;
125			if (strcmp(id, "lib") == 0) {
126				err = snd_config_get_string(n, &lib);
127				if (err < 0) {
128					SNDERR("Invalid type for %s", id);
129					goto _err;
130				}
131				continue;
132			}
133			if (strcmp(id, "open") == 0) {
134				err = snd_config_get_string(n, &open_name);
135				if (err < 0) {
136					SNDERR("Invalid type for %s", id);
137					goto _err;
138				}
139				continue;
140			}
141			SNDERR("Unknown field %s", id);
142			err = -EINVAL;
143			goto _err;
144		}
145	}
146	if (!open_name) {
147		open_name = buf;
148		snprintf(buf, sizeof(buf), "_snd_timer_%s_open", str);
149	}
150#ifndef PIC
151	snd_timer_open_symbols();
152#endif
153	h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
154	if (h)
155		open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_TIMER_DLSYM_VERSION));
156	err = 0;
157	if (!h) {
158		SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
159		err = -ENOENT;
160	} else if (!open_func) {
161		SNDERR("symbol %s is not defined inside %s", open_name, lib);
162		snd_dlclose(h);
163		err = -ENXIO;
164	}
165       _err:
166	if (type_conf)
167		snd_config_delete(type_conf);
168	if (! err) {
169		err = open_func(timer, name, timer_root, timer_conf, mode);
170		if (err < 0)
171			snd_dlclose(h);
172		else
173			(*timer)->dl_handle = h;
174	}
175	return err;
176}
177
178static int snd_timer_open_noupdate(snd_timer_t **timer, snd_config_t *root, const char *name, int mode)
179{
180	int err;
181	snd_config_t *timer_conf;
182	err = snd_config_search_definition(root, "timer", name, &timer_conf);
183	if (err < 0) {
184		SNDERR("Unknown timer %s", name);
185		return err;
186	}
187	err = snd_timer_open_conf(timer, name, root, timer_conf, mode);
188	snd_config_delete(timer_conf);
189	return err;
190}
191
192/**
193 * \brief Opens a new connection to the timer interface.
194 * \param timer Returned handle (NULL if not wanted)
195 * \param name ASCII identifier of the timer handle
196 * \param mode Open mode
197 * \return 0 on success otherwise a negative error code
198 *
199 * Opens a new connection to the timer interface specified with
200 * an ASCII identifier and mode.
201 */
202int snd_timer_open(snd_timer_t **timer, const char *name, int mode)
203{
204	snd_config_t *top;
205	int err;
206
207	assert(timer && name);
208	if (_snd_is_ucm_device(name)) {
209		name = uc_mgr_alibcfg_by_device(&top, name);
210		if (name == NULL)
211			return -ENODEV;
212	} else {
213		err = snd_config_update_ref(&top);
214		if (err < 0)
215			return err;
216	}
217	err = snd_timer_open_noupdate(timer, top, name, mode);
218	snd_config_unref(top);
219	return err;
220}
221
222/**
223 * \brief Opens a new connection to the timer interface using local configuration
224 * \param timer Returned handle (NULL if not wanted)
225 * \param name ASCII identifier of the timer handle
226 * \param mode Open mode
227 * \param lconf Local configuration
228 * \return 0 on success otherwise a negative error code
229 *
230 * Opens a new connection to the timer interface specified with
231 * an ASCII identifier and mode.
232 */
233int snd_timer_open_lconf(snd_timer_t **timer, const char *name,
234			 int mode, snd_config_t *lconf)
235{
236	assert(timer && name && lconf);
237	return snd_timer_open_noupdate(timer, lconf, name, mode);
238}
239
240/**
241 * \brief close timer handle
242 * \param timer timer handle
243 * \return 0 on success otherwise a negative error code
244 *
245 * Closes the specified timer handle and frees all associated
246 * resources.
247 */
248int snd_timer_close(snd_timer_t *timer)
249{
250	int err;
251  	assert(timer);
252	while (!list_empty(&timer->async_handlers)) {
253		snd_async_handler_t *h = list_entry(timer->async_handlers.next, snd_async_handler_t, hlist);
254		snd_async_del_handler(h);
255	}
256	err = timer->ops->close(timer);
257	if (timer->dl_handle)
258		snd_dlclose(timer->dl_handle);
259	free(timer->name);
260	free(timer);
261	return err;
262}
263
264/**
265 * \brief get identifier of timer handle
266 * \param timer a timer handle
267 * \return ascii identifier of timer handle
268 *
269 * Returns the ASCII identifier of given timer handle. It's the same
270 * identifier specified in snd_timer_open().
271 */
272const char *snd_timer_name(snd_timer_t *timer)
273{
274	assert(timer);
275	return timer->name;
276}
277
278/**
279 * \brief get type of timer handle
280 * \param timer a timer handle
281 * \return type of timer handle
282 *
283 * Returns the type #snd_timer_type_t of given timer handle.
284 */
285snd_timer_type_t snd_timer_type(snd_timer_t *timer)
286{
287	assert(timer);
288	return timer->type;
289}
290
291/**
292 * \brief Add an async handler for a timer
293 * \param handler Returned handler handle
294 * \param timer timer handle
295 * \param callback Callback function
296 * \param private_data Callback private data
297 * \return 0 otherwise a negative error code on failure
298 *
299 * The asynchronous callback is called when new timer event occurs.
300 */
301int snd_async_add_timer_handler(snd_async_handler_t **handler, snd_timer_t *timer,
302				snd_async_callback_t callback, void *private_data)
303{
304	int err;
305	int was_empty;
306	snd_async_handler_t *h;
307	err = snd_async_add_handler(&h, timer->poll_fd,
308				    callback, private_data);
309	if (err < 0)
310		return err;
311	h->type = SND_ASYNC_HANDLER_TIMER;
312	h->u.timer = timer;
313	was_empty = list_empty(&timer->async_handlers);
314	list_add_tail(&h->hlist, &timer->async_handlers);
315	if (was_empty) {
316		err = snd_timer_async(timer, snd_async_handler_get_signo(h), getpid());
317		if (err < 0) {
318			snd_async_del_handler(h);
319			return err;
320		}
321	}
322	*handler = h;
323	return 0;
324}
325
326/**
327 * \brief Return timer handle related to an async handler
328 * \param handler Async handler handle
329 * \return timer handle
330 */
331snd_timer_t *snd_async_handler_get_timer(snd_async_handler_t *handler)
332{
333	if (handler->type != SND_ASYNC_HANDLER_TIMER) {
334		SNDMSG("invalid handler type %d", handler->type);
335		return NULL;
336	}
337	return handler->u.timer;
338}
339
340/**
341 * \brief get count of poll descriptors for timer handle
342 * \param timer timer handle
343 * \return count of poll descriptors
344 */
345int snd_timer_poll_descriptors_count(snd_timer_t *timer)
346{
347	assert(timer);
348	return 1;
349}
350
351/**
352 * \brief get poll descriptors
353 * \param timer timer handle
354 * \param pfds array of poll descriptors
355 * \param space space in the poll descriptor array
356 * \return count of filled descriptors
357 */
358int snd_timer_poll_descriptors(snd_timer_t *timer, struct pollfd *pfds, unsigned int space)
359{
360	assert(timer);
361	if (space >= 1) {
362		pfds->fd = timer->poll_fd;
363		switch (timer->mode & O_ACCMODE) {
364		case O_WRONLY:
365			pfds->events = POLLOUT|POLLERR|POLLNVAL;
366			break;
367		case O_RDONLY:
368			pfds->events = POLLIN|POLLERR|POLLNVAL;
369			break;
370		case O_RDWR:
371			pfds->events = POLLOUT|POLLIN|POLLERR|POLLNVAL;
372			break;
373		default:
374			return -EIO;
375		}
376		return 1;
377	}
378	return 0;
379}
380
381/**
382 * \brief get returned events from poll descriptors
383 * \param timer timer handle
384 * \param pfds array of poll descriptors
385 * \param nfds count of poll descriptors
386 * \param revents returned events
387 * \return zero if success, otherwise a negative error code
388 */
389int snd_timer_poll_descriptors_revents(snd_timer_t *timer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
390{
391        assert(timer && pfds && revents);
392        if (nfds == 1) {
393                *revents = pfds->revents;
394                return 0;
395        }
396        return -EINVAL;
397}
398
399/**
400 * \brief set nonblock mode
401 * \param timer timer handle
402 * \param nonblock 0 = block, 1 = nonblock mode
403 * \return 0 on success otherwise a negative error code
404 */
405int snd_timer_nonblock(snd_timer_t *timer, int nonblock)
406{
407	int err;
408	assert(timer);
409	if ((err = timer->ops->nonblock(timer, nonblock)) < 0)
410		return err;
411	if (nonblock)
412		timer->mode |= SND_TIMER_OPEN_NONBLOCK;
413	else
414		timer->mode &= ~SND_TIMER_OPEN_NONBLOCK;
415	return 0;
416}
417
418#ifndef DOC_HIDDEN
419/**
420 * \brief set async mode
421 * \param timer timer handle
422 * \param sig Signal to raise: < 0 disable, 0 default (SIGIO)
423 * \param pid Process ID to signal: 0 current
424 * \return 0 on success otherwise a negative error code
425 *
426 * A signal is raised every period.
427 */
428int snd_timer_async(snd_timer_t *timer, int sig, pid_t pid)
429{
430	assert(timer);
431        if (sig == 0)
432                sig = SIGIO;
433	if (pid == 0)
434		pid = getpid();
435	return timer->ops->async(timer, sig, pid);
436}
437#endif
438
439/**
440 * \brief get size of the snd_timer_info_t structure in bytes
441 * \return size of the snd_timer_info_t structure in bytes
442 */
443size_t snd_timer_info_sizeof()
444{
445	return sizeof(snd_timer_info_t);
446}
447
448/**
449 * \brief allocate a new snd_timer_info_t structure
450 * \param info returned pointer
451 * \return 0 on success otherwise a negative error code if fails
452 *
453 * Allocates a new snd_timer_info_t structure using the standard
454 * malloc C library function.
455 */
456int snd_timer_info_malloc(snd_timer_info_t **info)
457{
458	assert(info);
459	*info = calloc(1, sizeof(snd_timer_info_t));
460	if (!*info)
461		return -ENOMEM;
462	return 0;
463}
464
465/**
466 * \brief frees the snd_timer_info_t structure
467 * \param info pointer to the snd_timer_info_t structure to free
468 *
469 * Frees the given snd_timer_info_t structure using the standard
470 * free C library function.
471 */
472void snd_timer_info_free(snd_timer_info_t *info)
473{
474	assert(info);
475	free(info);
476}
477
478/**
479 * \brief copy one snd_timer_info_t structure to another
480 * \param dst destination snd_timer_info_t structure
481 * \param src source snd_timer_info_t structure
482 */
483void snd_timer_info_copy(snd_timer_info_t *dst, const snd_timer_info_t *src)
484{
485	assert(dst && src);
486	*dst = *src;
487}
488
489/**
490 * \brief determine, if timer is slave
491 * \param info pointer to #snd_timer_info_t structure
492 * \return nonzero if timer is slave
493 */
494int snd_timer_info_is_slave(snd_timer_info_t * info)
495{
496	assert(info);
497	return info->flags & SNDRV_TIMER_FLG_SLAVE ? 1 : 0;
498}
499
500/**
501 * \brief get timer card
502 * \param info pointer to #snd_timer_info_t structure
503 * \return timer card number
504 */
505int snd_timer_info_get_card(snd_timer_info_t * info)
506{
507	assert(info);
508	return info->card;
509}
510
511/**
512 * \brief get timer id
513 * \param info pointer to #snd_timer_info_t structure
514 * \return timer id
515 */
516const char *snd_timer_info_get_id(snd_timer_info_t * info)
517{
518	assert(info);
519	return (const char *)info->id;
520}
521
522/**
523 * \brief get timer name
524 * \param info pointer to #snd_timer_info_t structure
525 * \return timer name
526 */
527const char *snd_timer_info_get_name(snd_timer_info_t * info)
528{
529	assert(info);
530	return (const char *)info->name;
531}
532
533
534/**
535 * \brief get timer resolution in us
536 * \param info pointer to #snd_timer_info_t structure
537 * \return timer resolution
538 */
539long snd_timer_info_get_resolution(snd_timer_info_t * info)
540{
541	assert(info);
542	return info->resolution;
543}
544
545/**
546 * \brief get information about timer handle
547 * \param timer timer handle
548 * \param info pointer to a snd_timer_info_t structure to be filled
549 * \return 0 on success otherwise a negative error code
550 */
551int snd_timer_info(snd_timer_t *timer, snd_timer_info_t * info)
552{
553	assert(timer);
554	assert(info);
555	return timer->ops->info(timer, info);
556}
557
558/**
559 * \brief get size of the snd_timer_params_t structure in bytes
560 * \return size of the snd_timer_params_t structure in bytes
561 */
562size_t snd_timer_params_sizeof()
563{
564	return sizeof(snd_timer_params_t);
565}
566
567/**
568 * \brief allocate a new snd_timer_params_t structure
569 * \param params returned pointer
570 * \return 0 on success otherwise a negative error code if fails
571 *
572 * Allocates a new snd_timer_params_t structure using the standard
573 * malloc C library function.
574 */
575int snd_timer_params_malloc(snd_timer_params_t **params)
576{
577	assert(params);
578	*params = calloc(1, sizeof(snd_timer_params_t));
579	if (!*params)
580		return -ENOMEM;
581	return 0;
582}
583
584/**
585 * \brief frees the snd_timer_params_t structure
586 * \param params pointer to the snd_timer_params_t structure to free
587 *
588 * Frees the given snd_timer_params_t structure using the standard
589 * free C library function.
590 */
591void snd_timer_params_free(snd_timer_params_t *params)
592{
593	assert(params);
594	free(params);
595}
596
597/**
598 * \brief copy one snd_timer_params_t structure to another
599 * \param dst destination snd_timer_params_t structure
600 * \param src source snd_timer_params_t structure
601 */
602void snd_timer_params_copy(snd_timer_params_t *dst, const snd_timer_params_t *src)
603{
604	assert(dst && src);
605	*dst = *src;
606}
607
608/**
609 * \brief set timer auto start
610 * \param params pointer to #snd_timer_params_t structure
611 * \param auto_start The boolean value to set
612 */
613int snd_timer_params_set_auto_start(snd_timer_params_t * params, int auto_start)
614{
615	assert(params);
616	if (auto_start)
617		params->flags |= SNDRV_TIMER_PSFLG_AUTO;
618	else
619		params->flags &= ~SNDRV_TIMER_PSFLG_AUTO;
620	return 0;
621}
622
623/**
624 * \brief determine if timer has auto start flag
625 * \param params pointer to #snd_timer_params_t structure
626 * \return nonzero if timer has auto start flag
627 */
628int snd_timer_params_get_auto_start(snd_timer_params_t * params)
629{
630	assert(params);
631	return params->flags & SNDRV_TIMER_PSFLG_AUTO ? 1 : 0;
632}
633
634/**
635 * \brief set timer exclusive use
636 * \param params pointer to #snd_timer_params_t structure
637 * \param exclusive The boolean value to set
638 */
639#ifndef DOXYGEN
640EXPORT_SYMBOL int INTERNAL(snd_timer_params_set_exclusive)(snd_timer_params_t * params, int exclusive)
641#else
642int snd_timer_params_set_exclusive(snd_timer_params_t * params, int exclusive)
643#endif
644{
645	assert(params);
646	if (exclusive)
647		params->flags |= SNDRV_TIMER_PSFLG_EXCLUSIVE;
648	else
649		params->flags &= ~SNDRV_TIMER_PSFLG_EXCLUSIVE;
650	return 0;
651}
652use_default_symbol_version(__snd_timer_params_set_exclusive, snd_timer_params_set_exclusive, ALSA_0.9.0);
653
654/**
655 * \brief determine if timer has exclusive flag
656 * \param params pointer to #snd_timer_params_t structure
657 * \return nonzero if timer has exclusive flag
658 */
659#ifndef DOXYGEN
660EXPORT_SYMBOL int INTERNAL(snd_timer_params_get_exclusive)(snd_timer_params_t * params)
661#else
662int snd_timer_params_get_exclusive(snd_timer_params_t * params)
663#endif
664{
665	assert(params);
666	return params->flags & SNDRV_TIMER_PSFLG_EXCLUSIVE ? 1 : 0;
667}
668use_default_symbol_version(__snd_timer_params_get_exclusive, snd_timer_params_get_exclusive, ALSA_0.9.0);
669
670/**
671 * \brief set timer early event
672 * \param params pointer to #snd_timer_params_t structure
673 * \param early_event The boolean value to set
674 */
675int snd_timer_params_set_early_event(snd_timer_params_t * params, int early_event)
676{
677	assert(params);
678	if (early_event)
679		params->flags |= SNDRV_TIMER_PSFLG_EARLY_EVENT;
680	else
681		params->flags &= ~SNDRV_TIMER_PSFLG_EARLY_EVENT;
682	return 0;
683}
684
685/**
686 * \brief determine if timer has early event flag
687 * \param params pointer to #snd_timer_params_t structure
688 * \return nonzero if timer has early event flag set
689 */
690int snd_timer_params_get_early_event(snd_timer_params_t * params)
691{
692	assert(params);
693	return params->flags & SNDRV_TIMER_PSFLG_EARLY_EVENT ? 1 : 0;
694}
695
696/**
697 * \brief set timer ticks
698 * \param params pointer to #snd_timer_params_t structure
699 * \param ticks Ticks to set
700 */
701void snd_timer_params_set_ticks(snd_timer_params_t * params, long ticks)
702{
703	assert(params);
704	params->ticks = ticks;
705}
706
707/**
708 * \brief get timer ticks
709 * \param params pointer to #snd_timer_params_t structure
710 * \return timer ticks
711 */
712long snd_timer_params_get_ticks(snd_timer_params_t * params)
713{
714	assert(params);
715	return params->ticks;
716}
717
718/**
719 * \brief set timer queue size (32-1024)
720 * \param params pointer to #snd_timer_params_t structure
721 * \param queue_size The queue size to set
722 */
723void snd_timer_params_set_queue_size(snd_timer_params_t * params, long queue_size)
724{
725	assert(params);
726	params->queue_size = queue_size;
727}
728
729/**
730 * \brief get queue size
731 * \param params pointer to #snd_timer_params_t structure
732 * \return queue size
733 */
734long snd_timer_params_get_queue_size(snd_timer_params_t * params)
735{
736	assert(params);
737	return params->queue_size;
738}
739
740/**
741 * \brief set timer event filter
742 * \param params pointer to #snd_timer_params_t structure
743 * \param filter The event filter bits to set
744 */
745#ifndef DOXYGEN
746EXPORT_SYMBOL void INTERNAL(snd_timer_params_set_filter)(snd_timer_params_t * params, unsigned int filter)
747#else
748void snd_timer_params_set_filter(snd_timer_params_t * params, unsigned int filter)
749#endif
750{
751	assert(params);
752	params->filter = filter;
753}
754use_default_symbol_version(__snd_timer_params_set_filter, snd_timer_params_set_filter, ALSA_0.9.0);
755
756/**
757 * \brief get timer event filter
758 * \param params pointer to #snd_timer_params_t structure
759 * \return timer event filter
760 */
761#ifndef DOXYGEN
762EXPORT_SYMBOL unsigned int INTERNAL(snd_timer_params_get_filter)(snd_timer_params_t * params)
763#else
764unsigned int snd_timer_params_get_filter(snd_timer_params_t * params)
765#endif
766{
767	assert(params);
768	return params->filter;
769}
770use_default_symbol_version(__snd_timer_params_get_filter, snd_timer_params_get_filter, ALSA_0.9.0);
771
772/**
773 * \brief set parameters for timer handle
774 * \param timer timer handle
775 * \param params pointer to a #snd_timer_params_t structure
776 * \return 0 on success otherwise a negative error code
777 */
778int snd_timer_params(snd_timer_t *timer, snd_timer_params_t * params)
779{
780	assert(timer);
781	assert(params);
782	return timer->ops->params(timer, params);
783}
784
785/**
786 * \brief get size of the snd_timer_status_t structure in bytes
787 * \return size of the snd_timer_status_t structure in bytes
788 */
789size_t snd_timer_status_sizeof()
790{
791	return sizeof(snd_timer_status_t);
792}
793
794/**
795 * \brief allocate a new snd_timer_status_t structure
796 * \param status returned pointer
797 * \return 0 on success otherwise a negative error code if fails
798 *
799 * Allocates a new snd_timer_status_t structure using the standard
800 * malloc C library function.
801 */
802int snd_timer_status_malloc(snd_timer_status_t **status)
803{
804	assert(status);
805	*status = calloc(1, sizeof(snd_timer_status_t));
806	if (!*status)
807		return -ENOMEM;
808	return 0;
809}
810
811/**
812 * \brief frees the snd_timer_status_t structure
813 * \param status pointer to the snd_timer_status_t structure to free
814 *
815 * Frees the given snd_timer_status_t structure using the standard
816 * free C library function.
817 */
818void snd_timer_status_free(snd_timer_status_t *status)
819{
820	assert(status);
821	free(status);
822}
823
824/**
825 * \brief copy one snd_timer_status_t structure to another
826 * \param dst destination snd_timer_status_t structure
827 * \param src source snd_timer_status_t structure
828 */
829void snd_timer_status_copy(snd_timer_status_t *dst, const snd_timer_status_t *src)
830{
831	assert(dst && src);
832	*dst = *src;
833}
834
835
836
837/**
838 * \brief get timestamp
839 * \param status pointer to #snd_timer_status_t structure
840 * \return timestamp
841 */
842snd_htimestamp_t snd_timer_status_get_timestamp(snd_timer_status_t * status)
843{
844	assert(status);
845	return status->tstamp;
846}
847
848/**
849 * \brief get resolution in us
850 * \param status pointer to #snd_timer_status_t structure
851 * \return resolution
852 */
853long snd_timer_status_get_resolution(snd_timer_status_t * status)
854{
855	assert(status);
856	return status->resolution;
857}
858
859/**
860 * \brief get master tick lost count
861 * \param status pointer to #snd_timer_status_t structure
862 * \return master tick lost count
863 */
864long snd_timer_status_get_lost(snd_timer_status_t * status)
865{
866	assert(status);
867	return status->lost;
868}
869
870/**
871 * \brief get overrun count
872 * \param status pointer to #snd_timer_status_t structure
873 * \return overrun count
874 */
875long snd_timer_status_get_overrun(snd_timer_status_t * status)
876{
877	assert(status);
878	return status->overrun;
879}
880
881/**
882 * \brief get count of used queue elements
883 * \param status pointer to #snd_timer_status_t structure
884 * \return count of used queue elements
885 */
886long snd_timer_status_get_queue(snd_timer_status_t * status)
887{
888	assert(status);
889	return status->queue;
890}
891
892/**
893 * \brief get status from timer handle
894 * \param timer timer handle
895 * \param status pointer to a #snd_timer_status_t structure to be filled
896 * \return 0 on success otherwise a negative error code
897 */
898int snd_timer_status(snd_timer_t *timer, snd_timer_status_t * status)
899{
900	assert(timer);
901	assert(status);
902	return timer->ops->status(timer, status);
903}
904
905/**
906 * \brief start the timer
907 * \param timer timer handle
908 * \return 0 on success otherwise a negative error code
909 */
910int snd_timer_start(snd_timer_t *timer)
911{
912	assert(timer);
913	return timer->ops->rt_start(timer);
914}
915
916/**
917 * \brief stop the timer
918 * \param timer timer handle
919 * \return 0 on success otherwise a negative error code
920 */
921int snd_timer_stop(snd_timer_t *timer)
922{
923	assert(timer);
924	return timer->ops->rt_stop(timer);
925}
926
927/**
928 * \brief continue the timer
929 * \param timer timer handle
930 * \return 0 on success otherwise a negative error code
931 */
932int snd_timer_continue(snd_timer_t *timer)
933{
934	assert(timer);
935	return timer->ops->rt_continue(timer);
936}
937
938/**
939 * \brief read bytes using timer handle
940 * \param timer timer handle
941 * \param buffer buffer to store the input bytes
942 * \param size input buffer size in bytes
943 */
944ssize_t snd_timer_read(snd_timer_t *timer, void *buffer, size_t size)
945{
946	assert(timer);
947	assert(((timer->mode & O_ACCMODE) == O_RDONLY) || ((timer->mode & O_ACCMODE) == O_RDWR));
948	assert(buffer || size == 0);
949	return (timer->ops->read)(timer, buffer, size);
950}
951
952/**
953 * \brief (DEPRECATED) get maximum timer ticks
954 * \param info pointer to #snd_timer_info_t structure
955 * \return maximum timer ticks
956 */
957long snd_timer_info_get_ticks(snd_timer_info_t * info)
958{
959	assert(info);
960	return 1;
961}
962#ifndef DOC_HIDDEN
963link_warning(snd_timer_info_get_ticks, "Warning: snd_timer_info_get_ticks is deprecated");
964#endif
965