1d5ac70f0Sopenharmony_ci/* 2d5ac70f0Sopenharmony_ci * Hardware dependent Interface - main file for hardware access 3d5ac70f0Sopenharmony_ci * Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz> 4d5ac70f0Sopenharmony_ci * 5d5ac70f0Sopenharmony_ci * 6d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 7d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 8d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 9d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 10d5ac70f0Sopenharmony_ci * 11d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 12d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 15d5ac70f0Sopenharmony_ci * 16d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 18d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19d5ac70f0Sopenharmony_ci * 20d5ac70f0Sopenharmony_ci */ 21d5ac70f0Sopenharmony_ci 22d5ac70f0Sopenharmony_ci#include "hwdep_local.h" 23d5ac70f0Sopenharmony_ci#include <stdio.h> 24d5ac70f0Sopenharmony_ci#include <stdlib.h> 25d5ac70f0Sopenharmony_ci#include <unistd.h> 26d5ac70f0Sopenharmony_ci#include <string.h> 27d5ac70f0Sopenharmony_ci#include <fcntl.h> 28d5ac70f0Sopenharmony_ci#include <sys/ioctl.h> 29d5ac70f0Sopenharmony_ci 30d5ac70f0Sopenharmony_ci#ifndef PIC 31d5ac70f0Sopenharmony_ci/* entry for static linking */ 32d5ac70f0Sopenharmony_ciconst char *_snd_module_hwdep_hw = ""; 33d5ac70f0Sopenharmony_ci#endif 34d5ac70f0Sopenharmony_ci 35d5ac70f0Sopenharmony_ci#define SNDRV_FILE_HWDEP ALSA_DEVICE_DIRECTORY "hwC%iD%i" 36d5ac70f0Sopenharmony_ci#define SNDRV_HWDEP_VERSION_MAX SNDRV_PROTOCOL_VERSION(1, 0, 1) 37d5ac70f0Sopenharmony_ci 38d5ac70f0Sopenharmony_cistatic int snd_hwdep_hw_close(snd_hwdep_t *hwdep) 39d5ac70f0Sopenharmony_ci{ 40d5ac70f0Sopenharmony_ci int res; 41d5ac70f0Sopenharmony_ci assert(hwdep); 42d5ac70f0Sopenharmony_ci res = close(hwdep->poll_fd) < 0 ? -errno : 0; 43d5ac70f0Sopenharmony_ci return res; 44d5ac70f0Sopenharmony_ci} 45d5ac70f0Sopenharmony_ci 46d5ac70f0Sopenharmony_cistatic int snd_hwdep_hw_nonblock(snd_hwdep_t *hwdep, int nonblock) 47d5ac70f0Sopenharmony_ci{ 48d5ac70f0Sopenharmony_ci long flags; 49d5ac70f0Sopenharmony_ci assert(hwdep); 50d5ac70f0Sopenharmony_ci if ((flags = fcntl(hwdep->poll_fd, F_GETFL)) < 0) 51d5ac70f0Sopenharmony_ci return -errno; 52d5ac70f0Sopenharmony_ci if (nonblock) 53d5ac70f0Sopenharmony_ci flags |= O_NONBLOCK; 54d5ac70f0Sopenharmony_ci else 55d5ac70f0Sopenharmony_ci flags &= ~O_NONBLOCK; 56d5ac70f0Sopenharmony_ci if (fcntl(hwdep->poll_fd, F_SETFL, flags) < 0) 57d5ac70f0Sopenharmony_ci return -errno; 58d5ac70f0Sopenharmony_ci return 0; 59d5ac70f0Sopenharmony_ci} 60d5ac70f0Sopenharmony_ci 61d5ac70f0Sopenharmony_cistatic int snd_hwdep_hw_info(snd_hwdep_t *hwdep, snd_hwdep_info_t *info) 62d5ac70f0Sopenharmony_ci{ 63d5ac70f0Sopenharmony_ci assert(hwdep && info); 64d5ac70f0Sopenharmony_ci if (ioctl(hwdep->poll_fd, SNDRV_HWDEP_IOCTL_INFO, info) < 0) 65d5ac70f0Sopenharmony_ci return -errno; 66d5ac70f0Sopenharmony_ci return 0; 67d5ac70f0Sopenharmony_ci} 68d5ac70f0Sopenharmony_ci 69d5ac70f0Sopenharmony_cistatic int snd_hwdep_hw_ioctl(snd_hwdep_t *hwdep, unsigned int request, void * arg) 70d5ac70f0Sopenharmony_ci{ 71d5ac70f0Sopenharmony_ci assert(hwdep); 72d5ac70f0Sopenharmony_ci if (ioctl(hwdep->poll_fd, request, arg) < 0) 73d5ac70f0Sopenharmony_ci return -errno; 74d5ac70f0Sopenharmony_ci return 0; 75d5ac70f0Sopenharmony_ci} 76d5ac70f0Sopenharmony_ci 77d5ac70f0Sopenharmony_cistatic ssize_t snd_hwdep_hw_write(snd_hwdep_t *hwdep, const void *buffer, size_t size) 78d5ac70f0Sopenharmony_ci{ 79d5ac70f0Sopenharmony_ci ssize_t result; 80d5ac70f0Sopenharmony_ci assert(hwdep && (buffer || size == 0)); 81d5ac70f0Sopenharmony_ci result = write(hwdep->poll_fd, buffer, size); 82d5ac70f0Sopenharmony_ci if (result < 0) 83d5ac70f0Sopenharmony_ci return -errno; 84d5ac70f0Sopenharmony_ci return result; 85d5ac70f0Sopenharmony_ci} 86d5ac70f0Sopenharmony_ci 87d5ac70f0Sopenharmony_cistatic ssize_t snd_hwdep_hw_read(snd_hwdep_t *hwdep, void *buffer, size_t size) 88d5ac70f0Sopenharmony_ci{ 89d5ac70f0Sopenharmony_ci ssize_t result; 90d5ac70f0Sopenharmony_ci assert(hwdep && (buffer || size == 0)); 91d5ac70f0Sopenharmony_ci result = read(hwdep->poll_fd, buffer, size); 92d5ac70f0Sopenharmony_ci if (result < 0) 93d5ac70f0Sopenharmony_ci return -errno; 94d5ac70f0Sopenharmony_ci return result; 95d5ac70f0Sopenharmony_ci} 96d5ac70f0Sopenharmony_ci 97d5ac70f0Sopenharmony_cistatic const snd_hwdep_ops_t snd_hwdep_hw_ops = { 98d5ac70f0Sopenharmony_ci .close = snd_hwdep_hw_close, 99d5ac70f0Sopenharmony_ci .nonblock = snd_hwdep_hw_nonblock, 100d5ac70f0Sopenharmony_ci .info = snd_hwdep_hw_info, 101d5ac70f0Sopenharmony_ci .ioctl = snd_hwdep_hw_ioctl, 102d5ac70f0Sopenharmony_ci .write = snd_hwdep_hw_write, 103d5ac70f0Sopenharmony_ci .read = snd_hwdep_hw_read, 104d5ac70f0Sopenharmony_ci}; 105d5ac70f0Sopenharmony_ci 106d5ac70f0Sopenharmony_ciint snd_hwdep_hw_open(snd_hwdep_t **handle, const char *name, int card, int device, int mode) 107d5ac70f0Sopenharmony_ci{ 108d5ac70f0Sopenharmony_ci int fd, ver, ret; 109d5ac70f0Sopenharmony_ci char filename[sizeof(SNDRV_FILE_HWDEP) + 20]; 110d5ac70f0Sopenharmony_ci snd_hwdep_t *hwdep; 111d5ac70f0Sopenharmony_ci assert(handle); 112d5ac70f0Sopenharmony_ci 113d5ac70f0Sopenharmony_ci *handle = NULL; 114d5ac70f0Sopenharmony_ci 115d5ac70f0Sopenharmony_ci if (card < 0 || card >= SND_MAX_CARDS) 116d5ac70f0Sopenharmony_ci return -EINVAL; 117d5ac70f0Sopenharmony_ci sprintf(filename, SNDRV_FILE_HWDEP, card, device); 118d5ac70f0Sopenharmony_ci fd = snd_open_device(filename, mode); 119d5ac70f0Sopenharmony_ci if (fd < 0) { 120d5ac70f0Sopenharmony_ci snd_card_load(card); 121d5ac70f0Sopenharmony_ci fd = snd_open_device(filename, mode); 122d5ac70f0Sopenharmony_ci if (fd < 0) 123d5ac70f0Sopenharmony_ci return -errno; 124d5ac70f0Sopenharmony_ci } 125d5ac70f0Sopenharmony_ci if (ioctl(fd, SNDRV_HWDEP_IOCTL_PVERSION, &ver) < 0) { 126d5ac70f0Sopenharmony_ci ret = -errno; 127d5ac70f0Sopenharmony_ci close(fd); 128d5ac70f0Sopenharmony_ci return ret; 129d5ac70f0Sopenharmony_ci } 130d5ac70f0Sopenharmony_ci if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_HWDEP_VERSION_MAX)) { 131d5ac70f0Sopenharmony_ci close(fd); 132d5ac70f0Sopenharmony_ci return -SND_ERROR_INCOMPATIBLE_VERSION; 133d5ac70f0Sopenharmony_ci } 134d5ac70f0Sopenharmony_ci hwdep = (snd_hwdep_t *) calloc(1, sizeof(snd_hwdep_t)); 135d5ac70f0Sopenharmony_ci if (hwdep == NULL) { 136d5ac70f0Sopenharmony_ci close(fd); 137d5ac70f0Sopenharmony_ci return -ENOMEM; 138d5ac70f0Sopenharmony_ci } 139d5ac70f0Sopenharmony_ci hwdep->name = strdup(name); 140d5ac70f0Sopenharmony_ci hwdep->poll_fd = fd; 141d5ac70f0Sopenharmony_ci hwdep->mode = mode; 142d5ac70f0Sopenharmony_ci hwdep->type = SND_HWDEP_TYPE_HW; 143d5ac70f0Sopenharmony_ci hwdep->ops = &snd_hwdep_hw_ops; 144d5ac70f0Sopenharmony_ci *handle = hwdep; 145d5ac70f0Sopenharmony_ci return 0; 146d5ac70f0Sopenharmony_ci} 147d5ac70f0Sopenharmony_ci 148d5ac70f0Sopenharmony_ciint _snd_hwdep_hw_open(snd_hwdep_t **hwdep, char *name, 149d5ac70f0Sopenharmony_ci snd_config_t *root ATTRIBUTE_UNUSED, 150d5ac70f0Sopenharmony_ci snd_config_t *conf, int mode) 151d5ac70f0Sopenharmony_ci{ 152d5ac70f0Sopenharmony_ci snd_config_iterator_t i, next; 153d5ac70f0Sopenharmony_ci long card = -1, device = 0; 154d5ac70f0Sopenharmony_ci int err; 155d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, conf) { 156d5ac70f0Sopenharmony_ci snd_config_t *n = snd_config_iterator_entry(i); 157d5ac70f0Sopenharmony_ci const char *id; 158d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 159d5ac70f0Sopenharmony_ci continue; 160d5ac70f0Sopenharmony_ci if (_snd_conf_generic_id(id)) 161d5ac70f0Sopenharmony_ci continue; 162d5ac70f0Sopenharmony_ci if (strcmp(id, "card") == 0) { 163d5ac70f0Sopenharmony_ci err = snd_config_get_card(n); 164d5ac70f0Sopenharmony_ci if (err < 0) 165d5ac70f0Sopenharmony_ci return err; 166d5ac70f0Sopenharmony_ci card = err; 167d5ac70f0Sopenharmony_ci continue; 168d5ac70f0Sopenharmony_ci } 169d5ac70f0Sopenharmony_ci if (strcmp(id, "device") == 0) { 170d5ac70f0Sopenharmony_ci err = snd_config_get_integer(n, &device); 171d5ac70f0Sopenharmony_ci if (err < 0) 172d5ac70f0Sopenharmony_ci return err; 173d5ac70f0Sopenharmony_ci continue; 174d5ac70f0Sopenharmony_ci } 175d5ac70f0Sopenharmony_ci SNDERR("Unexpected field %s", id); 176d5ac70f0Sopenharmony_ci return -EINVAL; 177d5ac70f0Sopenharmony_ci } 178d5ac70f0Sopenharmony_ci if (card < 0) 179d5ac70f0Sopenharmony_ci return -EINVAL; 180d5ac70f0Sopenharmony_ci return snd_hwdep_hw_open(hwdep, name, card, device, mode); 181d5ac70f0Sopenharmony_ci} 182d5ac70f0Sopenharmony_ciSND_DLSYM_BUILD_VERSION(_snd_hwdep_hw_open, SND_HWDEP_DLSYM_VERSION); 183