Lines Matching defs:*
2 * Timer Interface - main file
3 * Copyright (c) 1998-2001 by Jaroslav Kysela <perex@perex.cz>
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include "timer_local.h"
30 #ifndef PIC
31 /* entry for static linking */
32 const char *_snd_module_timer_hw = "";
33 #endif
35 #define SNDRV_FILE_TIMER ALSA_DEVICE_DIRECTORY "timer"
36 #define SNDRV_TIMER_VERSION_MAX SNDRV_PROTOCOL_VERSION(2, 0, 5)
38 #define SNDRV_TIMER_IOCTL_STATUS_OLD _IOW('T', 0x14, struct sndrv_timer_status)
40 enum {
41 SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
42 SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
43 SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22),
44 SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
47 static int snd_timer_hw_close(snd_timer_t *handle)
49 snd_timer_t *tmr = handle;
50 int res;
52 if (!tmr)
53 return -EINVAL;
54 res = close(tmr->poll_fd) < 0 ? -errno : 0;
55 return res;
58 static int snd_timer_hw_nonblock(snd_timer_t *timer, int nonblock)
60 long flags;
61 assert(timer);
62 if ((flags = fcntl(timer->poll_fd, F_GETFL)) < 0)
63 return -errno;
64 if (nonblock)
65 flags |= O_NONBLOCK;
66 else
67 flags &= ~O_NONBLOCK;
68 if (fcntl(timer->poll_fd, F_SETFL, flags) < 0)
69 return -errno;
70 return 0;
73 static int snd_timer_hw_async(snd_timer_t *timer, int sig, pid_t pid)
75 long flags;
76 int fd;
78 assert(timer);
79 fd = timer->poll_fd;
80 if ((flags = fcntl(fd, F_GETFL)) < 0) {
81 SYSERR("F_GETFL failed");
82 return -errno;
84 if (sig >= 0)
85 flags |= O_ASYNC;
86 else
87 flags &= ~O_ASYNC;
88 if (fcntl(fd, F_SETFL, flags) < 0) {
89 SYSERR("F_SETFL for O_ASYNC failed");
90 return -errno;
92 if (sig < 0)
93 return 0;
94 if (fcntl(fd, F_SETSIG, (long)sig) < 0) {
95 SYSERR("F_SETSIG failed");
96 return -errno;
98 if (fcntl(fd, F_SETOWN, (long)pid) < 0) {
99 SYSERR("F_SETOWN failed");
100 return -errno;
102 return 0;
105 static int snd_timer_hw_info(snd_timer_t *handle, snd_timer_info_t * info)
107 snd_timer_t *tmr;
109 tmr = handle;
110 if (!tmr || !info)
111 return -EINVAL;
112 if (ioctl(tmr->poll_fd, SNDRV_TIMER_IOCTL_INFO, info) < 0)
113 return -errno;
114 return 0;
117 static int snd_timer_hw_params(snd_timer_t *handle, snd_timer_params_t * params)
119 snd_timer_t *tmr;
121 tmr = handle;
122 if (!tmr || !params)
123 return -EINVAL;
124 if (ioctl(tmr->poll_fd, SNDRV_TIMER_IOCTL_PARAMS, params) < 0)
125 return -errno;
126 return 0;
129 static int snd_timer_hw_status(snd_timer_t *handle, snd_timer_status_t * status)
131 snd_timer_t *tmr;
132 int cmd;
134 tmr = handle;
135 if (!tmr || !status)
136 return -EINVAL;
137 if (tmr->version < SNDRV_PROTOCOL_VERSION(2, 0, 1))
138 cmd = SNDRV_TIMER_IOCTL_STATUS_OLD;
139 else
140 cmd = SNDRV_TIMER_IOCTL_STATUS;
141 if (ioctl(tmr->poll_fd, cmd, status) < 0)
142 return -errno;
143 return 0;
146 static int snd_timer_hw_start(snd_timer_t *handle)
148 snd_timer_t *tmr;
149 unsigned int cmd;
151 tmr = handle;
152 if (!tmr)
153 return -EINVAL;
154 if (tmr->version < SNDRV_PROTOCOL_VERSION(2, 0, 4))
155 cmd = SNDRV_TIMER_IOCTL_START_OLD;
156 else
157 cmd = SNDRV_TIMER_IOCTL_START;
158 if (ioctl(tmr->poll_fd, cmd) < 0)
159 return -errno;
160 return 0;
163 static int snd_timer_hw_stop(snd_timer_t *handle)
165 snd_timer_t *tmr;
166 unsigned int cmd;
168 tmr = handle;
169 if (!tmr)
170 return -EINVAL;
171 if (tmr->version < SNDRV_PROTOCOL_VERSION(2, 0, 4))
172 cmd = SNDRV_TIMER_IOCTL_STOP_OLD;
173 else
174 cmd = SNDRV_TIMER_IOCTL_STOP;
175 if (ioctl(tmr->poll_fd, cmd) < 0)
176 return -errno;
177 return 0;
180 static int snd_timer_hw_continue(snd_timer_t *handle)
182 snd_timer_t *tmr;
183 unsigned int cmd;
185 tmr = handle;
186 if (!tmr)
187 return -EINVAL;
188 if (tmr->version < SNDRV_PROTOCOL_VERSION(2, 0, 4))
189 cmd = SNDRV_TIMER_IOCTL_CONTINUE_OLD;
190 else
191 cmd = SNDRV_TIMER_IOCTL_CONTINUE;
192 if (ioctl(tmr->poll_fd, cmd) < 0)
193 return -errno;
194 return 0;
197 static ssize_t snd_timer_hw_read(snd_timer_t *handle, void *buffer, size_t size)
199 snd_timer_t *tmr;
200 ssize_t result;
202 tmr = handle;
203 if (!tmr || (!buffer && size > 0))
204 return -EINVAL;
205 result = read(tmr->poll_fd, buffer, size);
206 if (result < 0)
207 return -errno;
208 return result;
211 static const snd_timer_ops_t snd_timer_hw_ops = {
212 .close = snd_timer_hw_close,
213 .nonblock = snd_timer_hw_nonblock,
214 .async = snd_timer_hw_async,
215 .info = snd_timer_hw_info,
216 .params = snd_timer_hw_params,
217 .status = snd_timer_hw_status,
218 .rt_start = snd_timer_hw_start,
219 .rt_stop = snd_timer_hw_stop,
220 .rt_continue = snd_timer_hw_continue,
221 .read = snd_timer_hw_read,
224 int snd_timer_hw_open(snd_timer_t **handle, const char *name, int dev_class, int dev_sclass, int card, int device, int subdevice, int mode)
226 int fd, ver, tmode, ret;
227 snd_timer_t *tmr;
228 struct sndrv_timer_select sel;
230 *handle = NULL;
232 tmode = O_RDONLY;
233 if (mode & SND_TIMER_OPEN_NONBLOCK)
234 tmode |= O_NONBLOCK;
235 fd = snd_open_device(SNDRV_FILE_TIMER, tmode);
236 if (fd < 0)
237 return -errno;
238 if (ioctl(fd, SNDRV_TIMER_IOCTL_PVERSION, &ver) < 0) {
239 ret = -errno;
240 close(fd);
241 return ret;
243 if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_TIMER_VERSION_MAX)) {
244 close(fd);
245 return -SND_ERROR_INCOMPATIBLE_VERSION;
247 if (mode & SND_TIMER_OPEN_TREAD) {
248 int arg = 1;
249 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 3)) {
250 ret = -ENOTTY;
251 goto __no_tread;
253 if (ioctl(fd, SNDRV_TIMER_IOCTL_TREAD, &arg) < 0) {
254 ret = -errno;
255 __no_tread:
256 close(fd);
257 SNDMSG("extended read is not supported (SNDRV_TIMER_IOCTL_TREAD)");
258 return ret;
261 memset(&sel, 0, sizeof(sel));
262 sel.id.dev_class = dev_class;
263 sel.id.dev_sclass = dev_sclass;
264 sel.id.card = card;
265 sel.id.device = device;
266 sel.id.subdevice = subdevice;
267 if (ioctl(fd, SNDRV_TIMER_IOCTL_SELECT, &sel) < 0) {
268 ret = -errno;
269 close(fd);
270 return ret;
272 tmr = (snd_timer_t *) calloc(1, sizeof(snd_timer_t));
273 if (tmr == NULL) {
274 close(fd);
275 return -ENOMEM;
277 tmr->type = SND_TIMER_TYPE_HW;
278 tmr->version = ver;
279 tmr->mode = tmode;
280 tmr->name = strdup(name);
281 tmr->poll_fd = fd;
282 tmr->ops = &snd_timer_hw_ops;
283 INIT_LIST_HEAD(&tmr->async_handlers);
284 *handle = tmr;
285 return 0;
288 int _snd_timer_hw_open(snd_timer_t **timer, char *name,
289 snd_config_t *root ATTRIBUTE_UNUSED,
290 snd_config_t *conf, int mode)
292 snd_config_iterator_t i, next;
293 long dev_class = SND_TIMER_CLASS_GLOBAL, dev_sclass = SND_TIMER_SCLASS_NONE;
294 long card = 0, device = 0, subdevice = 0;
295 const char *str;
296 int err;
297 snd_config_for_each(i, next, conf) {
298 snd_config_t *n = snd_config_iterator_entry(i);
299 const char *id;
300 if (snd_config_get_id(n, &id) < 0)
301 continue;
302 if (strcmp(id, "comment") == 0)
303 continue;
304 if (strcmp(id, "type") == 0)
305 continue;
306 if (strcmp(id, "class") == 0) {
307 err = snd_config_get_integer(n, &dev_class);
308 if (err < 0)
309 return err;
310 continue;
312 if (strcmp(id, "sclass") == 0) {
313 err = snd_config_get_integer(n, &dev_sclass);
314 if (err < 0)
315 return err;
316 continue;
318 if (strcmp(id, "card") == 0) {
319 err = snd_config_get_integer(n, &card);
320 if (err < 0) {
321 err = snd_config_get_string(n, &str);
322 if (err < 0)
323 return -EINVAL;
324 card = snd_card_get_index(str);
325 if (card < 0)
326 return card;
328 continue;
330 if (strcmp(id, "device") == 0) {
331 err = snd_config_get_integer(n, &device);
332 if (err < 0)
333 return err;
334 continue;
336 if (strcmp(id, "subdevice") == 0) {
337 err = snd_config_get_integer(n, &subdevice);
338 if (err < 0)
339 return err;
340 continue;
342 SNDERR("Unexpected field %s", id);
343 return -EINVAL;
345 if (card < 0)
346 return -EINVAL;
347 return snd_timer_hw_open(timer, name, dev_class, dev_sclass, card, device, subdevice, mode);
349 SND_DLSYM_BUILD_VERSION(_snd_timer_hw_open, SND_TIMER_DLSYM_VERSION);