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