• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Timer Interface - main file
3  *  Copyright (c) 1998-2001 by Jaroslav Kysela <perex@perex.cz>
4  *
5  *
6  *   This library is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU Lesser General Public License as
8  *   published by the Free Software Foundation; either version 2.1 of
9  *   the License, or (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 #include "timer_local.h"
23 
24 #ifndef PIC
25 /* entry for static linking */
26 const char *_snd_module_timer_query_hw = "";
27 #endif
28 
29 #define SNDRV_FILE_TIMER		ALSA_DEVICE_DIRECTORY "timer"
30 #define SNDRV_TIMER_VERSION_MAX	SNDRV_PROTOCOL_VERSION(2, 0, 0)
31 
snd_timer_query_hw_close(snd_timer_query_t * handle)32 static int snd_timer_query_hw_close(snd_timer_query_t *handle)
33 {
34 	int res;
35 
36 	if (!handle)
37 		return -EINVAL;
38 	res = close(handle->poll_fd) < 0 ? -errno : 0;
39 	return res;
40 }
41 
snd_timer_query_hw_next_device(snd_timer_query_t * handle,snd_timer_id_t * tid)42 static int snd_timer_query_hw_next_device(snd_timer_query_t *handle, snd_timer_id_t * tid)
43 {
44 	if (!handle || !tid)
45 		return -EINVAL;
46 	if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_NEXT_DEVICE, tid) < 0)
47 		return -errno;
48 	return 0;
49 }
50 
snd_timer_query_hw_info(snd_timer_query_t * handle,snd_timer_ginfo_t * info)51 static int snd_timer_query_hw_info(snd_timer_query_t *handle, snd_timer_ginfo_t *info)
52 {
53 	if (!handle || !info)
54 		return -EINVAL;
55 	if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_GINFO, info) < 0)
56 		return -errno;
57 	return 0;
58 }
59 
snd_timer_query_hw_params(snd_timer_query_t * handle,snd_timer_gparams_t * params)60 static int snd_timer_query_hw_params(snd_timer_query_t *handle, snd_timer_gparams_t *params)
61 {
62 	if (!handle || !params)
63 		return -EINVAL;
64 	if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_GPARAMS, params) < 0)
65 		return -errno;
66 	return 0;
67 }
68 
snd_timer_query_hw_status(snd_timer_query_t * handle,snd_timer_gstatus_t * status)69 static int snd_timer_query_hw_status(snd_timer_query_t *handle, snd_timer_gstatus_t *status)
70 {
71 	if (!handle || !status)
72 		return -EINVAL;
73 	if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_GSTATUS, status) < 0)
74 		return -errno;
75 	return 0;
76 }
77 
78 static const snd_timer_query_ops_t snd_timer_query_hw_ops = {
79 	.close = snd_timer_query_hw_close,
80 	.next_device = snd_timer_query_hw_next_device,
81 	.info = snd_timer_query_hw_info,
82 	.params = snd_timer_query_hw_params,
83 	.status = snd_timer_query_hw_status
84 };
85 
snd_timer_query_hw_open(snd_timer_query_t ** handle,const char * name,int mode)86 int snd_timer_query_hw_open(snd_timer_query_t **handle, const char *name, int mode)
87 {
88 	int fd, ver, tmode;
89 	snd_timer_query_t *tmr;
90 
91 	*handle = NULL;
92 
93 	tmode = O_RDONLY;
94 	if (mode & SND_TIMER_OPEN_NONBLOCK)
95 		tmode |= O_NONBLOCK;
96 	fd = snd_open_device(SNDRV_FILE_TIMER, tmode);
97 	if (fd < 0)
98 		return -errno;
99 	if (ioctl(fd, SNDRV_TIMER_IOCTL_PVERSION, &ver) < 0) {
100 		close(fd);
101 		return -errno;
102 	}
103 	if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_TIMER_VERSION_MAX)) {
104 		close(fd);
105 		return -SND_ERROR_INCOMPATIBLE_VERSION;
106 	}
107 	tmr = (snd_timer_query_t *) calloc(1, sizeof(snd_timer_query_t));
108 	if (tmr == NULL) {
109 		close(fd);
110 		return -ENOMEM;
111 	}
112 	tmr->type = SND_TIMER_TYPE_HW;
113 	tmr->mode = tmode;
114 	tmr->name = strdup(name);
115 	tmr->poll_fd = fd;
116 	tmr->ops = &snd_timer_query_hw_ops;
117 	*handle = tmr;
118 	return 0;
119 }
120 
_snd_timer_query_hw_open(snd_timer_query_t ** timer,char * name,snd_config_t * root ATTRIBUTE_UNUSED,snd_config_t * conf,int mode)121 int _snd_timer_query_hw_open(snd_timer_query_t **timer, char *name,
122 			     snd_config_t *root ATTRIBUTE_UNUSED,
123 			     snd_config_t *conf, int mode)
124 {
125 	snd_config_iterator_t i, next;
126 	snd_config_for_each(i, next, conf) {
127 		snd_config_t *n = snd_config_iterator_entry(i);
128 		const char *id;
129 		if (snd_config_get_id(n, &id) < 0)
130 			continue;
131 		if (_snd_conf_generic_id(id))
132 			continue;
133 		SNDERR("Unexpected field %s", id);
134 		return -EINVAL;
135 	}
136 	return snd_timer_query_hw_open(timer, name, mode);
137 }
138 SND_DLSYM_BUILD_VERSION(_snd_timer_query_hw_open, SND_TIMER_QUERY_DLSYM_VERSION);
139