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