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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 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" 29 30#ifndef PIC 31/* entry for static linking */ 32const char *_snd_module_timer_query_hw = ""; 33#endif 34 35#define SNDRV_FILE_TIMER ALSA_DEVICE_DIRECTORY "timer" 36#define SNDRV_TIMER_VERSION_MAX SNDRV_PROTOCOL_VERSION(2, 0, 0) 37 38static int snd_timer_query_hw_close(snd_timer_query_t *handle) 39{ 40 int res; 41 42 if (!handle) 43 return -EINVAL; 44 res = close(handle->poll_fd) < 0 ? -errno : 0; 45 return res; 46} 47 48static int snd_timer_query_hw_next_device(snd_timer_query_t *handle, snd_timer_id_t * tid) 49{ 50 if (!handle || !tid) 51 return -EINVAL; 52 if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_NEXT_DEVICE, tid) < 0) 53 return -errno; 54 return 0; 55} 56 57static int snd_timer_query_hw_info(snd_timer_query_t *handle, snd_timer_ginfo_t *info) 58{ 59 if (!handle || !info) 60 return -EINVAL; 61 if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_GINFO, info) < 0) 62 return -errno; 63 return 0; 64} 65 66static int snd_timer_query_hw_params(snd_timer_query_t *handle, snd_timer_gparams_t *params) 67{ 68 if (!handle || !params) 69 return -EINVAL; 70 if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_GPARAMS, params) < 0) 71 return -errno; 72 return 0; 73} 74 75static int snd_timer_query_hw_status(snd_timer_query_t *handle, snd_timer_gstatus_t *status) 76{ 77 if (!handle || !status) 78 return -EINVAL; 79 if (ioctl(handle->poll_fd, SNDRV_TIMER_IOCTL_GSTATUS, status) < 0) 80 return -errno; 81 return 0; 82} 83 84static const snd_timer_query_ops_t snd_timer_query_hw_ops = { 85 .close = snd_timer_query_hw_close, 86 .next_device = snd_timer_query_hw_next_device, 87 .info = snd_timer_query_hw_info, 88 .params = snd_timer_query_hw_params, 89 .status = snd_timer_query_hw_status 90}; 91 92int snd_timer_query_hw_open(snd_timer_query_t **handle, const char *name, int mode) 93{ 94 int fd, ver, tmode; 95 snd_timer_query_t *tmr; 96 97 *handle = NULL; 98 99 tmode = O_RDONLY; 100 if (mode & SND_TIMER_OPEN_NONBLOCK) 101 tmode |= O_NONBLOCK; 102 fd = snd_open_device(SNDRV_FILE_TIMER, tmode); 103 if (fd < 0) 104 return -errno; 105 if (ioctl(fd, SNDRV_TIMER_IOCTL_PVERSION, &ver) < 0) { 106 close(fd); 107 return -errno; 108 } 109 if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_TIMER_VERSION_MAX)) { 110 close(fd); 111 return -SND_ERROR_INCOMPATIBLE_VERSION; 112 } 113 tmr = (snd_timer_query_t *) calloc(1, sizeof(snd_timer_t)); 114 if (tmr == NULL) { 115 close(fd); 116 return -ENOMEM; 117 } 118 tmr->type = SND_TIMER_TYPE_HW; 119 tmr->mode = tmode; 120 tmr->name = strdup(name); 121 tmr->poll_fd = fd; 122 tmr->ops = &snd_timer_query_hw_ops; 123 *handle = tmr; 124 return 0; 125} 126 127int _snd_timer_query_hw_open(snd_timer_query_t **timer, char *name, 128 snd_config_t *root ATTRIBUTE_UNUSED, 129 snd_config_t *conf, int mode) 130{ 131 snd_config_iterator_t i, next; 132 snd_config_for_each(i, next, conf) { 133 snd_config_t *n = snd_config_iterator_entry(i); 134 const char *id; 135 if (snd_config_get_id(n, &id) < 0) 136 continue; 137 if (strcmp(id, "comment") == 0) 138 continue; 139 if (strcmp(id, "type") == 0) 140 continue; 141 SNDERR("Unexpected field %s", id); 142 return -EINVAL; 143 } 144 return snd_timer_query_hw_open(timer, name, mode); 145} 146SND_DLSYM_BUILD_VERSION(_snd_timer_query_hw_open, SND_TIMER_QUERY_DLSYM_VERSION); 147