From d02979784f340871870c49f916991251075eec75 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 13 Jul 2001 10:00:19 +0000 Subject: [PATCH] Recoded hwdep API to follow modern conf style. Added hwdep configuration to alsa.conf. Added documentation for hwdep interface. --- include/hwdep.h | 36 +++- src/conf/alsa.conf | 65 ++++++ src/hwdep/Makefile.am | 2 +- src/hwdep/hwdep.c | 439 +++++++++++++++++++++++++++++++++------- src/hwdep/hwdep_hw.c | 180 ++++++++++++++++ src/hwdep/hwdep_local.h | 45 ++++ src/hwdep/hwdep_m4.c | 84 -------- 7 files changed, 681 insertions(+), 170 deletions(-) create mode 100644 src/hwdep/hwdep_hw.c create mode 100644 src/hwdep/hwdep_local.h delete mode 100644 src/hwdep/hwdep_m4.c diff --git a/include/hwdep.h b/include/hwdep.h index 67389e08..3636edac 100644 --- a/include/hwdep.h +++ b/include/hwdep.h @@ -14,22 +14,37 @@ /** HwDep information container */ typedef struct _snd_hwdep_info snd_hwdep_info_t; +/** HwDep interface */ typedef enum _snd_hwdep_iface { - SND_HWDEP_IFACE_OPL2 = SNDRV_HWDEP_IFACE_OPL2, - SND_HWDEP_IFACE_OPL3 = SNDRV_HWDEP_IFACE_OPL3, - SND_HWDEP_IFACE_OPL4 = SNDRV_HWDEP_IFACE_OPL4, - SND_HWDEP_IFACE_SB16CSP = SNDRV_HWDEP_IFACE_SB16CSP, - SND_HWDEP_IFACE_EMU10K1 = SNDRV_HWDEP_IFACE_EMU10K1, - SND_HWDEP_IFACE_YSS225 = SNDRV_HWDEP_IFACE_YSS225, - SND_HWDEP_IFACE_ICS2115 = SNDRV_HWDEP_IFACE_ICS2115, - SND_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_LAST, + SND_HWDEP_IFACE_OPL2 = SNDRV_HWDEP_IFACE_OPL2, /**< OPL2 raw driver */ + SND_HWDEP_IFACE_OPL3 = SNDRV_HWDEP_IFACE_OPL3, /**< OPL3 raw driver */ + SND_HWDEP_IFACE_OPL4 = SNDRV_HWDEP_IFACE_OPL4, /**< OPL4 raw driver */ + SND_HWDEP_IFACE_SB16CSP = SNDRV_HWDEP_IFACE_SB16CSP, /**< SB16CSP driver */ + SND_HWDEP_IFACE_EMU10K1 = SNDRV_HWDEP_IFACE_EMU10K1, /**< EMU10K1 driver */ + SND_HWDEP_IFACE_YSS225 = SNDRV_HWDEP_IFACE_YSS225, /**< YSS225 driver */ + SND_HWDEP_IFACE_ICS2115 = SNDRV_HWDEP_IFACE_ICS2115, /**< ICS2115 driver */ + SND_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_LAST, /**< last know hwdep interface */ } snd_hwdep_iface_t; +/** open for reading */ #define SND_HWDEP_OPEN_READ (O_RDONLY) +/** open for writing */ #define SND_HWDEP_OPEN_WRITE (O_WRONLY) +/** open for reading and writing */ #define SND_HWDEP_OPEN_DUPLEX (O_RDWR) +/** flag: open in nonblock mode */ #define SND_HWDEP_OPEN_NONBLOCK (O_NONBLOCK) +/** HwDep handle type */ +typedef enum _snd_hwdep_type { + /** Kernel level HwDep */ + SND_HWDEP_TYPE_HW, + /** Shared memory client HwDep (not yet implemented) */ + SND_HWDEP_TYPE_SHM, + /** INET client HwDep (not yet implemented) */ + SND_HWDEP_TYPE_INET, +} snd_hwdep_type_t; + /** HwDep handle */ typedef struct _snd_hwdep snd_hwdep_t; @@ -37,16 +52,17 @@ typedef struct _snd_hwdep snd_hwdep_t; extern "C" { #endif -int snd_hwdep_open(snd_hwdep_t **hwdep, int card, int device, int mode); +int snd_hwdep_open(snd_hwdep_t **hwdep, const char *name, int mode); int snd_hwdep_close(snd_hwdep_t *hwdep); int snd_hwdep_poll_descriptors(snd_hwdep_t *hwdep, struct pollfd *pfds, unsigned int space); -int snd_hwdep_block_mode(snd_hwdep_t *hwdep, int enable); +int snd_hwdep_nonblock(snd_hwdep_t *hwdep, int nonblock); int snd_hwdep_info(snd_hwdep_t *hwdep, snd_hwdep_info_t * info); int snd_hwdep_ioctl(snd_hwdep_t *hwdep, unsigned int request, void * arg); ssize_t snd_hwdep_write(snd_hwdep_t *hwdep, const void *buffer, size_t size); ssize_t snd_hwdep_read(snd_hwdep_t *hwdep, void *buffer, size_t size); size_t snd_hwdep_info_sizeof(void); +/** allocate #snd_hwdep_info_t container on stack */ #define snd_hwdep_info_alloca(ptr) do { assert(ptr); *ptr = (snd_hwdep_info_t *) alloca(snd_hwdep_info_sizeof()); memset(*ptr, 0, snd_hwdep_info_sizeof()); } while (0) int snd_hwdep_info_malloc(snd_hwdep_info_t **ptr); void snd_hwdep_info_free(snd_hwdep_info_t *obj); diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf index 1e758c0b..b21d7671 100644 --- a/src/conf/alsa.conf +++ b/src/conf/alsa.conf @@ -66,6 +66,8 @@ defaults.pcm.iec958.device defaults.pcm.device defaults.rawmidi.card 0 defaults.rawmidi.device 0 defaults.rawmidi.subdevice -1 +defaults.hwdep.card 0 +defaults.hwdep.device 0 # # PCM interface @@ -391,3 +393,66 @@ seq.default { seq.hw { type hw } + +# +# HwDep interface +# + +hwdep.hw { + @args [ CARD DEV ] + @args.CARD { + type string + default { + @func getenv + vars [ + ALSA_RAWMIDI_CARD + ALSA_CARD + ] + default { + @func refer + name defaults.rawmidi.card + } + } + } + @args.DEV { + type integer + default { + @func igetenv + vars [ + ALSA_RAWMIDI_DEVICE + ] + default { + @func refer + name defaults.rawmidi.device + } + } + } + type hw + card $CARD + device $DEV +} + +hwdep.default { + type hw + card { + @func getenv + vars [ + ALSA_HWDEP_CARD + ALSA_CARD + ] + default { + @func refer + name defaults.hwdep.card + } + } + device { + @func igetenv + vars [ + ALSA_HWDEP_DEVICE + ] + default { + @func refer + name defaults.hwdep.device + } + } +} diff --git a/src/hwdep/Makefile.am b/src/hwdep/Makefile.am index 245891bc..cc507e91 100644 --- a/src/hwdep/Makefile.am +++ b/src/hwdep/Makefile.am @@ -1,6 +1,6 @@ EXTRA_LTLIBRARIES=libhwdep.la -libhwdep_la_SOURCES = hwdep.c hwdep_m4.c +libhwdep_la_SOURCES = hwdep.c hwdep_hw.c all: libhwdep.la diff --git a/src/hwdep/hwdep.c b/src/hwdep/hwdep.c index 21647f4e..c6627892 100644 --- a/src/hwdep/hwdep.c +++ b/src/hwdep/hwdep.c @@ -1,3 +1,11 @@ +/* + * \file hwdep/hwdep.c + * \author Jaroslav Kysela + * \date 2000-2001 + * + * HwDep (hardware dependent) Interface is designed for individual hardware + * access. This interface does not cover any API specification. + */ /* * Hardware dependent Interface - main file * Copyright (c) 2000 by Jaroslav Kysela @@ -24,123 +32,404 @@ #include #include #include +#include #include -#include "local.h" +#include "hwdep_local.h" -#define SNDRV_FILE_HWDEP "/dev/snd/hwC%iD%i" -#define SNDRV_HWDEP_VERSION_MAX SNDRV_PROTOCOL_VERSION(1, 0, 0) - -struct _snd_hwdep { - int card; - int device; - int fd; - int mode; -}; - -int snd_hwdep_open(snd_hwdep_t **handle, int card, int device, int mode) +static int snd_hwdep_open_conf(snd_hwdep_t **hwdep, + const char *name, snd_config_t *hwdep_root, + snd_config_t *hwdep_conf, int mode) { - int fd, ver; - char filename[32]; - snd_hwdep_t *hwdep; - assert(handle); - - *handle = NULL; - - if (card < 0 || card >= 32) + const char *str; + char buf[256]; + int err; + snd_config_t *conf, *type_conf; + snd_config_iterator_t i, next; + const char *lib = NULL, *open_name = NULL; + int (*open_func)(snd_hwdep_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL; + void *h; + if (snd_config_get_type(hwdep_conf) != SND_CONFIG_TYPE_COMPOUND) { + if (name) + SNDERR("Invalid type for HWDEP %s definition", name); + else + SNDERR("Invalid type for HWDEP definition"); return -EINVAL; - sprintf(filename, SNDRV_FILE_HWDEP, card, device); - if ((fd = open(filename, mode)) < 0) { - snd_card_load(card); - if ((fd = open(filename, mode)) < 0) - return -errno; } - if (ioctl(fd, SNDRV_HWDEP_IOCTL_PVERSION, &ver) < 0) { - close(fd); - return -errno; + err = snd_config_search(hwdep_conf, "type", &conf); + if (err < 0) { + SNDERR("type is not defined"); + return err; } - if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_HWDEP_VERSION_MAX)) { - close(fd); - return -SND_ERROR_INCOMPATIBLE_VERSION; + err = snd_config_get_string(conf, &str); + if (err < 0) { + SNDERR("Invalid type for %s", snd_config_get_id(conf)); + return err; } - hwdep = (snd_hwdep_t *) calloc(1, sizeof(snd_hwdep_t)); - if (hwdep == NULL) { - close(fd); - return -ENOMEM; + err = snd_config_search_definition(hwdep_root, "hwdep_type", str, &type_conf); + if (err >= 0) { + if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) { + SNDERR("Invalid type for HWDEP type %s definition", str); + goto _err; + } + snd_config_for_each(i, next, type_conf) { + snd_config_t *n = snd_config_iterator_entry(i); + const char *id = snd_config_get_id(n); + if (strcmp(id, "comment") == 0) + continue; + if (strcmp(id, "lib") == 0) { + err = snd_config_get_string(n, &lib); + if (err < 0) { + SNDERR("Invalid type for %s", id); + goto _err; + } + continue; + } + if (strcmp(id, "open") == 0) { + err = snd_config_get_string(n, &open_name); + if (err < 0) { + SNDERR("Invalid type for %s", id); + goto _err; + } + continue; + } + SNDERR("Unknown field %s", id); + err = -EINVAL; + goto _err; + } + } + if (!open_name) { + open_name = buf; + snprintf(buf, sizeof(buf), "_snd_hwdep_%s_open", str); + } + if (!lib) + lib = ALSA_LIB; + h = dlopen(lib, RTLD_NOW); + open_func = h ? dlsym(h, open_name) : NULL; + if (!h) { + SNDERR("Cannot open shared library %s", lib); + err = -ENOENT; + } else if (!open_func) { + SNDERR("symbol %s is not defined inside %s", open_name, lib); + dlclose(h); + err = -ENXIO; } - hwdep->card = card; - hwdep->device = device; - hwdep->fd = fd; - hwdep->mode = mode; - *handle = hwdep; + _err: + if (type_conf) + snd_config_delete(type_conf); + if (err >= 0) + err = open_func(hwdep, name, hwdep_root, hwdep_conf, mode); + if (err < 0) + return err; return 0; } +static int snd_hwdep_open_noupdate(snd_hwdep_t **hwdep, snd_config_t *root, const char *name, int mode) +{ + int err; + snd_config_t *hwdep_conf; + err = snd_config_search_definition(root, "hwdep", name, &hwdep_conf); + if (err < 0) { + SNDERR("Unknown HwDep %s", name); + return err; + } + err = snd_hwdep_open_conf(hwdep, name, root, hwdep_conf, mode); + snd_config_delete(hwdep_conf); + return err; +} + +/** + * \brief Opens a new connection to the HwDep interface. + * \param hwdep Returned handle (NULL if not wanted) + * \param name ASCII identifier of the RawMidi handle + * \param mode Open mode + * \return 0 on success otherwise a negative error code + * + * Opens a new connection to the RawMidi interface specified with + * an ASCII identifier and mode. + */ +int snd_hwdep_open(snd_hwdep_t **hwdep, const char *name, int mode) +{ + int err; + assert(hwdep && name); + err = snd_config_update(); + if (err < 0) + return err; + return snd_hwdep_open_noupdate(hwdep, snd_config, name, mode); +} + +/** + * \brief close RawMidi handle + * \param hwdep RawMidi handle + * \return 0 on success otherwise a negative error code + * + * Closes the specified RawMidi handle and frees all associated + * resources. + */ int snd_hwdep_close(snd_hwdep_t *hwdep) { - int res; - assert(hwdep); - res = close(hwdep->fd) < 0 ? -errno : 0; + int err; + assert(hwdep); + if ((err = hwdep->ops->close(hwdep)) < 0) + return err; + if (hwdep->name) + free(hwdep->name); free(hwdep); - return res; + return 0; +} + +/** + * \brief get identifier of HwDep handle + * \param hwdep a Hwdep handle + * \return ascii identifier of RawMidi handle + * + * Returns the ASCII identifier of given HwDep handle. It's the same + * identifier specified in snd_hwdep_open(). + */ +const char *snd_hwdep_name(snd_hwdep_t *hwdep) +{ + assert(hwdep); + return hwdep->name; +} + +/** + * \brief get type of HwDep handle + * \param hwdep a HwDep handle + * \return type of HwDep handle + * + * Returns the type #snd_hwdep_type_t of given HwDep handle. + */ +snd_hwdep_type_t snd_hwdep_type(snd_hwdep_t *hwdep) +{ + assert(hwdep); + return hwdep->type; +} + +/** + * \brief get count of poll descriptors for HwDep handle + * \param hwdep HwDep handle + * \return count of poll descriptors + */ +int snd_hwdep_poll_descriptors_count(snd_hwdep_t *hwdep) +{ + assert(hwdep); + return 1; } +/** + * \brief get poll descriptors + * \param hwdep HwDep handle + * \param pfds array of poll descriptors + * \param space space in the poll descriptor array + * \return count of filled descriptors + */ int snd_hwdep_poll_descriptors(snd_hwdep_t *hwdep, struct pollfd *pfds, unsigned int space) { assert(hwdep); if (space >= 1) { - pfds->fd = hwdep->fd; - pfds->events = POLLOUT | POLLIN; + pfds->fd = hwdep->poll_fd; + switch (hwdep->mode & O_ACCMODE) { + case O_WRONLY: + pfds->events = POLLOUT; + break; + case O_RDONLY: + pfds->events = POLLIN; + break; + case O_RDWR: + pfds->events = POLLOUT|POLLIN; + break; + default: + return -EIO; + } + return 1; } - return 1; + return 0; } -int snd_hwdep_block_mode(snd_hwdep_t *hwdep, int enable) +/** + * \brief set nonblock mode + * \param hwdep HwDep handle + * \param nonblock 0 = block, 1 = nonblock mode + * \return 0 on success otherwise a negative error code + */ +int snd_hwdep_nonblock(snd_hwdep_t *hwdep, int nonblock) { - long flags; + int err; assert(hwdep); - if ((flags = fcntl(hwdep->fd, F_GETFL)) < 0) - return -errno; - if (enable) - flags |= O_NONBLOCK; + if ((err = hwdep->ops->nonblock(hwdep, nonblock)) < 0) + return err; + if (nonblock) + hwdep->mode |= SND_HWDEP_OPEN_NONBLOCK; else - flags &= ~O_NONBLOCK; - if (fcntl(hwdep->fd, F_SETFL, flags) < 0) - return -errno; + hwdep->mode &= ~SND_HWDEP_OPEN_NONBLOCK; return 0; } -int snd_hwdep_info(snd_hwdep_t *hwdep, snd_hwdep_info_t *info) +/** + * \brief get size of the snd_hwdep_info_t structure in bytes + * \return size of the snd_hwdep_info_t structure in bytes + */ +size_t snd_hwdep_info_sizeof() { - assert(hwdep && info); - if (ioctl(hwdep->fd, SNDRV_HWDEP_IOCTL_INFO, info) < 0) - return -errno; + return sizeof(snd_hwdep_info_t); +} + +/** + * \brief allocate a new snd_hwdep_info_t structure + * \param ptr returned pointer + * \return 0 on success otherwise a negative error code if fails + * + * Allocates a new snd_hwdep_info_t structure using the standard + * malloc C library function. + */ +int snd_hwdep_info_malloc(snd_hwdep_info_t **info) +{ + assert(info); + *info = calloc(1, sizeof(snd_hwdep_info_t)); + if (!*info) + return -ENOMEM; return 0; } +/** + * \brief frees the snd_hwdep_info_t structure + * \param info pointer to the snd_hwdep_info_t structure to free + * + * Frees the given snd_hwdep_info_t structure using the standard + * free C library function. + */ +void snd_hwdep_info_free(snd_hwdep_info_t *info) +{ + assert(info); + free(info); +} + +/** + * \brief copy one snd_hwdep_info_t structure to another + * \param dst destination snd_hwdep_info_t structure + * \param src source snd_hwdep_info_t structure + */ +void snd_hwdep_info_copy(snd_hwdep_info_t *dst, const snd_hwdep_info_t *src) +{ + assert(dst && src); + *dst = *src; +} + +/** + * \brief get hwdep card number + * \param info pointer to a snd_hwdep_info_t structure + * \return hwdep card number + */ +int snd_hwdep_info_get_card(const snd_hwdep_info_t *obj) +{ + assert(obj); + return obj->card; +} + +/** + * \brief get hwdep device number + * \param info pointer to a snd_hwdep_info_t structure + * \return hwdep device number + */ +unsigned int snd_hwdep_info_get_device(const snd_hwdep_info_t *info) +{ + assert(info); + return info->device; +} + +/** + * \brief get hwdep driver identifier + * \param info pointer to a snd_hwdep_info_t structure + * \return hwdep driver identifier + */ +const char *snd_hwdep_info_get_id(const snd_hwdep_info_t *obj) +{ + assert(obj); + return obj->id; +} + +/** + * \brief get hwdep driver name + * \param info pointer to a snd_hwdep_info_t structure + * \return hwdep driver name + */ +const char *snd_hwdep_info_get_name(const snd_hwdep_info_t *obj) +{ + assert(obj); + return obj->name; +} + +/** + * \brief get hwdep protocol interface + * \param info pointer to a snd_hwdep_info_t structure + * \return hwdep protocol interface + */ +snd_hwdep_iface_t snd_hwdep_info_get_iface(const snd_hwdep_info_t *obj) +{ + assert(obj); + return obj->iface; +} + +/** + * \brief set hwdep device number + * \param info pointer to a snd_hwdep_info_t structure + * \param val hwdep device + */ +void snd_hwdep_info_set_device(snd_hwdep_info_t *obj, unsigned int val) +{ + assert(obj); + obj->device = val; +} + +/** + * \brief get information about HwDep handle + * \param hwdep HwDep handle + * \param info pointer to a snd_hwdep_info_t structure to be filled + * \return 0 on success otherwise a negative error code + */ +int snd_hwdep_info(snd_hwdep_t *hwdep, snd_hwdep_info_t * info) +{ + assert(hwdep); + assert(info); + return hwdep->ops->info(hwdep, info); +} + +/** + * \brief do hardware dependent ioctl + * \param hwdep HwDep handle + * \param request ioctl command + * \param arg ioctl argument + * \return 0 on success otherwise a negative error code + */ int snd_hwdep_ioctl(snd_hwdep_t *hwdep, unsigned int request, void * arg) { assert(hwdep); - if (ioctl(hwdep->fd, request, arg) < 0) - return -errno; - return 0; + return hwdep->ops->ioctl(hwdep, request, arg); } +/** + * \brief write bytes using HwDep handle + * \param hwdep HwDep handle + * \param buffer buffer containing bytes to write + * \param size output buffer size in bytes + */ ssize_t snd_hwdep_write(snd_hwdep_t *hwdep, const void *buffer, size_t size) { - ssize_t result; - assert(hwdep && (buffer || size == 0)); - result = write(hwdep->fd, buffer, size); - if (result < 0) - return -errno; - return result; + assert(hwdep); + assert(((hwdep->mode & O_ACCMODE) == O_WRONLY) || ((hwdep->mode & O_ACCMODE) == O_RDWR)); + assert(buffer || size == 0); + return hwdep->ops->write(hwdep, buffer, size); } +/** + * \brief read bytes using HwDep handle + * \param hwdep HwDep handle + * \param buffer buffer to store the input bytes + * \param size input buffer size in bytes + */ ssize_t snd_hwdep_read(snd_hwdep_t *hwdep, void *buffer, size_t size) { - ssize_t result; - assert(hwdep && (buffer || size == 0)); - result = read(hwdep->fd, buffer, size); - if (result < 0) - return -errno; - return result; + assert(hwdep); + assert(((hwdep->mode & O_ACCMODE) == O_RDONLY) || ((hwdep->mode & O_ACCMODE) == O_RDWR)); + assert(buffer || size == 0); + return hwdep->ops->read(hwdep, buffer, size); } diff --git a/src/hwdep/hwdep_hw.c b/src/hwdep/hwdep_hw.c new file mode 100644 index 00000000..16a58fac --- /dev/null +++ b/src/hwdep/hwdep_hw.c @@ -0,0 +1,180 @@ +/* + * Hardware dependent Interface - main file for hardware access + * Copyright (c) 2001 by Jaroslav Kysela + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include "hwdep_local.h" + +#define SNDRV_FILE_HWDEP "/dev/snd/hwC%iD%i" +#define SNDRV_HWDEP_VERSION_MAX SNDRV_PROTOCOL_VERSION(1, 0, 0) + +static int snd_hwdep_hw_close(snd_hwdep_t *hwdep) +{ + int res; + assert(hwdep); + res = close(hwdep->poll_fd) < 0 ? -errno : 0; + free(hwdep); + return res; +} + +static int snd_hwdep_hw_nonblock(snd_hwdep_t *hwdep, int nonblock) +{ + long flags; + assert(hwdep); + if ((flags = fcntl(hwdep->poll_fd, F_GETFL)) < 0) + return -errno; + if (nonblock) + flags |= O_NONBLOCK; + else + flags &= ~O_NONBLOCK; + if (fcntl(hwdep->poll_fd, F_SETFL, flags) < 0) + return -errno; + return 0; +} + +static int snd_hwdep_hw_info(snd_hwdep_t *hwdep, snd_hwdep_info_t *info) +{ + assert(hwdep && info); + if (ioctl(hwdep->poll_fd, SNDRV_HWDEP_IOCTL_INFO, info) < 0) + return -errno; + return 0; +} + +static int snd_hwdep_hw_ioctl(snd_hwdep_t *hwdep, unsigned int request, void * arg) +{ + assert(hwdep); + if (ioctl(hwdep->poll_fd, request, arg) < 0) + return -errno; + return 0; +} + +static ssize_t snd_hwdep_hw_write(snd_hwdep_t *hwdep, const void *buffer, size_t size) +{ + ssize_t result; + assert(hwdep && (buffer || size == 0)); + result = write(hwdep->poll_fd, buffer, size); + if (result < 0) + return -errno; + return result; +} + +static ssize_t snd_hwdep_hw_read(snd_hwdep_t *hwdep, void *buffer, size_t size) +{ + ssize_t result; + assert(hwdep && (buffer || size == 0)); + result = read(hwdep->poll_fd, buffer, size); + if (result < 0) + return -errno; + return result; +} + +static snd_hwdep_ops_t snd_hwdep_hw_ops = { + close: snd_hwdep_hw_close, + nonblock: snd_hwdep_hw_nonblock, + info: snd_hwdep_hw_info, + ioctl: snd_hwdep_hw_ioctl, + write: snd_hwdep_hw_write, + read: snd_hwdep_hw_read, +}; + +int snd_hwdep_hw_open(snd_hwdep_t **handle, const char *name, int card, int device, int mode) +{ + int fd, ver; + char filename[32]; + snd_hwdep_t *hwdep; + assert(handle); + + *handle = NULL; + + if (card < 0 || card >= 32) + return -EINVAL; + sprintf(filename, SNDRV_FILE_HWDEP, card, device); + if ((fd = open(filename, mode)) < 0) { + snd_card_load(card); + if ((fd = open(filename, mode)) < 0) + return -errno; + } + if (ioctl(fd, SNDRV_HWDEP_IOCTL_PVERSION, &ver) < 0) { + close(fd); + return -errno; + } + if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_HWDEP_VERSION_MAX)) { + close(fd); + return -SND_ERROR_INCOMPATIBLE_VERSION; + } + hwdep = (snd_hwdep_t *) calloc(1, sizeof(snd_hwdep_t)); + if (hwdep == NULL) { + close(fd); + return -ENOMEM; + } + hwdep->name = strdup(name); + hwdep->poll_fd = fd; + hwdep->mode = mode; + hwdep->type = SND_HWDEP_TYPE_HW; + hwdep->ops = &snd_hwdep_hw_ops; + *handle = hwdep; + return 0; +} + +int _snd_hwdep_hw_open(snd_hwdep_t **hwdep, char *name, + snd_config_t *root ATTRIBUTE_UNUSED, + snd_config_t *conf, int mode) +{ + snd_config_iterator_t i, next; + long card = -1, device = 0; + const char *str; + int err; + snd_config_for_each(i, next, conf) { + snd_config_t *n = snd_config_iterator_entry(i); + const char *id = snd_config_get_id(n); + if (strcmp(id, "comment") == 0) + continue; + if (strcmp(id, "type") == 0) + continue; + if (strcmp(id, "card") == 0) { + err = snd_config_get_integer(n, &card); + if (err < 0) { + err = snd_config_get_string(n, &str); + if (err < 0) + return -EINVAL; + card = snd_card_get_index(str); + if (card < 0) + return card; + } + continue; + } + if (strcmp(id, "device") == 0) { + err = snd_config_get_integer(n, &device); + if (err < 0) + return err; + continue; + } + SNDERR("Unexpected field %s", id); + return -EINVAL; + } + if (card < 0) + return -EINVAL; + return snd_hwdep_hw_open(hwdep, name, card, device, mode); +} diff --git a/src/hwdep/hwdep_local.h b/src/hwdep/hwdep_local.h new file mode 100644 index 00000000..4bdc154a --- /dev/null +++ b/src/hwdep/hwdep_local.h @@ -0,0 +1,45 @@ +/* + * HwDep interface - local header file + * Copyright (c) 2001 by Jaroslav Kysela + * + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include "local.h" + +typedef struct { + int (*close)(snd_hwdep_t *hwdep); + int (*nonblock)(snd_hwdep_t *hwdep, int nonblock); + int (*info)(snd_hwdep_t *hwdep, snd_hwdep_info_t *info); + int (*ioctl)(snd_hwdep_t *hwdep, unsigned int request, void * arg); + ssize_t (*write)(snd_hwdep_t *hwdep, const void *buffer, size_t size); + ssize_t (*read)(snd_hwdep_t *hwdep, void *buffer, size_t size); +} snd_hwdep_ops_t; + +struct _snd_hwdep { + char *name; + snd_hwdep_type_t type; + int mode; + int poll_fd; + snd_hwdep_ops_t *ops; + void *private_data; +}; + +int snd_hwdep_hw_open(snd_hwdep_t **handle, const char *name, int card, int device, int mode); diff --git a/src/hwdep/hwdep_m4.c b/src/hwdep/hwdep_m4.c deleted file mode 100644 index 8d390a43..00000000 --- a/src/hwdep/hwdep_m4.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Hwdep - Automatically generated functions - * Copyright (c) 2001 by Abramo Bagnara - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "local.h" - -size_t snd_hwdep_info_sizeof() -{ - return sizeof(snd_hwdep_info_t); -} - -int snd_hwdep_info_malloc(snd_hwdep_info_t **ptr) -{ - assert(ptr); - *ptr = calloc(1, sizeof(snd_hwdep_info_t)); - if (!*ptr) - return -ENOMEM; - return 0; -} - -void snd_hwdep_info_free(snd_hwdep_info_t *obj) -{ - free(obj); -} - -void snd_hwdep_info_copy(snd_hwdep_info_t *dst, const snd_hwdep_info_t *src) -{ - assert(dst && src); - *dst = *src; -} - -unsigned int snd_hwdep_info_get_device(const snd_hwdep_info_t *obj) -{ - assert(obj); - return obj->device; -} - -int snd_hwdep_info_get_card(const snd_hwdep_info_t *obj) -{ - assert(obj); - return obj->card; -} - -const char *snd_hwdep_info_get_id(const snd_hwdep_info_t *obj) -{ - assert(obj); - return obj->id; -} - -const char *snd_hwdep_info_get_name(const snd_hwdep_info_t *obj) -{ - assert(obj); - return obj->name; -} - -snd_hwdep_iface_t snd_hwdep_info_get_iface(const snd_hwdep_info_t *obj) -{ - assert(obj); - return obj->iface; -} - -void snd_hwdep_info_set_device(snd_hwdep_info_t *obj, unsigned int val) -{ - assert(obj); - obj->device = val; -} - -- 2.47.1