remove mixer api files

This commit is contained in:
Alexandre Ratchov 2015-08-28 09:03:49 +02:00
parent 1e958d6853
commit a162cfd9e6
7 changed files with 0 additions and 1582 deletions

View File

@ -1,198 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "debug.h"
#include "siomix_priv.h"
#include "bsd-compat.h"
struct siomix_hdl *
siomix_open(const char *str, unsigned int mode, int nbio)
{
static char devany[] = SIOMIX_DEVANY;
struct siomix_hdl *hdl;
const char *p;
#ifdef DEBUG
_sndio_debug_init();
#endif
if (str == NULL) /* backward compat */
str = devany;
if (strcmp(str, devany) == 0 && !issetugid()) {
str = getenv("AUDIODEVICE");
if (str == NULL)
str = devany;
}
if (strcmp(str, devany) == 0) {
hdl = _siomix_aucat_open("/0", mode, nbio);
if (hdl != NULL)
return hdl;
#if defined(USE_SUN_MIXER)
return _siomix_sun_open("/0", mode, nbio);
#elif defined(USE_ALSA_MIXER)
return _siomix_alsa_open("/0", mode, nbio);
#else
return NULL;
#endif
}
if ((p = _sndio_parsetype(str, "snd")) != NULL)
return _siomix_aucat_open(p, mode, nbio);
#if defined(USE_ALSA_MIXER) || defined(USE_SUN_MIXER)
if ((p = _sndio_parsetype(str, "rsnd")) != NULL) {
#if defined(USE_SUN_MIXER)
return _siomix_sun_open(p, mode, nbio);
#elif defined(USE_ALSA_MIXER)
return _siomix_alsa_open(p, mode, nbio);
#endif
}
#endif
DPRINTF("siomix_open: %s: unknown device type\n", str);
return NULL;
}
void
_siomix_create(struct siomix_hdl *hdl, struct siomix_ops *ops,
unsigned int mode, int nbio)
{
hdl->ops = ops;
hdl->mode = mode;
hdl->nbio = nbio;
hdl->eof = 0;
hdl->ctl_cb = NULL;
}
int
_siomix_psleep(struct siomix_hdl *hdl, int event)
{
struct pollfd pfds[SIOMIX_MAXNFDS];
int revents, nfds;
for (;;) {
nfds = siomix_pollfd(hdl, pfds, event);
if (nfds == 0)
return 0;
while (poll(pfds, nfds, -1) < 0) {
if (errno == EINTR)
continue;
DPERROR("siomix_psleep: poll");
hdl->eof = 1;
return 0;
}
revents = siomix_revents(hdl, pfds);
if (revents & POLLHUP) {
DPRINTF("siomix_psleep: hang-up\n");
return 0;
}
if (event == 0 || (revents & event))
break;
}
return 1;
}
void
siomix_close(struct siomix_hdl *hdl)
{
hdl->ops->close(hdl);
}
int
siomix_nfds(struct siomix_hdl *hdl)
{
return hdl->ops->nfds(hdl);
}
int
siomix_pollfd(struct siomix_hdl *hdl, struct pollfd *pfd, int events)
{
if (hdl->eof)
return 0;
return hdl->ops->pollfd(hdl, pfd, events);
}
int
siomix_revents(struct siomix_hdl *hdl, struct pollfd *pfd)
{
if (hdl->eof)
return POLLHUP;
return hdl->ops->revents(hdl, pfd);
}
int
siomix_eof(struct siomix_hdl *hdl)
{
return hdl->eof;
}
int
siomix_ondesc(struct siomix_hdl *hdl,
void (*cb)(void *, struct siomix_desc *, int), void *arg)
{
hdl->desc_cb = cb;
hdl->desc_arg = arg;
return hdl->ops->ondesc(hdl);
}
int
siomix_onctl(struct siomix_hdl *hdl,
void (*cb)(void *, unsigned int, unsigned int), void *arg)
{
hdl->ctl_cb = cb;
hdl->ctl_arg = arg;
return hdl->ops->onctl(hdl);
}
void
_siomix_ondesc_cb(struct siomix_hdl *hdl,
struct siomix_desc *desc, unsigned int val)
{
if (desc) {
DPRINTF("%u -> %s[%s].%s=%s[%s]\n",
desc->addr,
desc->chan0.str, desc->chan0.opt,
desc->func,
desc->chan1.str, desc->chan1.opt);
}
if (hdl->desc_cb)
hdl->desc_cb(hdl->desc_arg, desc, val);
}
void
_siomix_onctl_cb(struct siomix_hdl *hdl, unsigned int addr, unsigned int val)
{
if (hdl->ctl_cb)
hdl->ctl_cb(hdl->ctl_arg, addr, val);
}
int
siomix_setctl(struct siomix_hdl *hdl, unsigned int addr, unsigned int val)
{
if (!(hdl->mode & SIOMIX_WRITE))
return 0;
return hdl->ops->setctl(hdl, addr, val);
}

View File

@ -1,258 +0,0 @@
/*
* Copyright (c) 2010-2011 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sndio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "debug.h"
#include "aucat.h"
#include "siomix_priv.h"
#include "bsd-compat.h"
struct siomix_aucat_hdl {
struct siomix_hdl siomix;
struct aucat aucat;
struct siomix_desc desc;
struct amsg_mix_desc *tmp;
int dump_wait;
};
static void siomix_aucat_close(struct siomix_hdl *);
static int siomix_aucat_nfds(struct siomix_hdl *);
static int siomix_aucat_pollfd(struct siomix_hdl *, struct pollfd *, int);
static int siomix_aucat_revents(struct siomix_hdl *, struct pollfd *);
static int siomix_aucat_setctl(struct siomix_hdl *, unsigned int, unsigned int);
static int siomix_aucat_onctl(struct siomix_hdl *);
static int siomix_aucat_ondesc(struct siomix_hdl *);
/*
* operations every device should support
*/
struct siomix_ops siomix_aucat_ops = {
siomix_aucat_close,
siomix_aucat_nfds,
siomix_aucat_pollfd,
siomix_aucat_revents,
siomix_aucat_setctl,
siomix_aucat_onctl,
siomix_aucat_ondesc
};
static int
siomix_aucat_rdata(struct siomix_aucat_hdl *hdl)
{
struct siomix_desc desc;
struct amsg_mix_desc *c;
int n, size;
size = ntohl(hdl->aucat.rmsg.u.data.size);
for (;;) {
n = _aucat_rdata(&hdl->aucat,
(unsigned char *)hdl->tmp + size - hdl->aucat.rtodo,
hdl->aucat.rtodo, &hdl->siomix.eof);
if (n == 0 || hdl->siomix.eof)
return 0;
if (hdl->aucat.rstate != RSTATE_DATA)
break;
}
c = hdl->tmp;
while (size >= sizeof(struct amsg_mix_desc)) {
strlcpy(desc.chan0.str, c->chan0.str, SIOMIX_NAMEMAX);
strlcpy(desc.chan0.opt, c->chan0.opt, SIOMIX_NAMEMAX);
strlcpy(desc.chan1.str, c->chan1.str, SIOMIX_NAMEMAX);
strlcpy(desc.chan1.opt, c->chan1.opt, SIOMIX_NAMEMAX);
strlcpy(desc.func, c->func, SIOMIX_NAMEMAX);
desc.type = c->type;
desc.addr = ntohs(c->addr);
_siomix_ondesc_cb(&hdl->siomix, &desc, ntohs(c->curval));
size -= sizeof(struct amsg_mix_desc);
c++;
}
free(hdl->tmp);
hdl->dump_wait = 0;
return 1;
}
/*
* execute the next message, return 0 if blocked
*/
static int
siomix_aucat_runmsg(struct siomix_aucat_hdl *hdl)
{
int size;
if (!_aucat_rmsg(&hdl->aucat, &hdl->siomix.eof))
return 0;
switch (ntohl(hdl->aucat.rmsg.cmd)) {
case AMSG_DATA:
size = ntohl(hdl->aucat.rmsg.u.data.size);
hdl->tmp = malloc(size);
if (hdl->tmp == NULL) {
DPRINTF("siomix_aucat_runmsg: malloc failed\n");
hdl->siomix.eof = 1;
return 0;
}
if (!siomix_aucat_rdata(hdl))
return 0;
break;
case AMSG_MIXSET:
DPRINTF("siomix_aucat_runmsg: got MIXSET\n");
_siomix_onctl_cb(&hdl->siomix,
ntohs(hdl->aucat.rmsg.u.mixset.addr),
ntohs(hdl->aucat.rmsg.u.mixset.val));
break;
default:
DPRINTF("sio_aucat_runmsg: unhandled message %u\n",
hdl->aucat.rmsg.cmd);
hdl->siomix.eof = 1;
return 0;
}
hdl->aucat.rstate = RSTATE_MSG;
hdl->aucat.rtodo = sizeof(struct amsg);
return 1;
}
struct siomix_hdl *
_siomix_aucat_open(const char *str, unsigned int mode, int nbio)
{
struct siomix_aucat_hdl *hdl;
hdl = malloc(sizeof(struct siomix_aucat_hdl));
if (hdl == NULL)
return NULL;
if (!_aucat_open(&hdl->aucat, str, mode, 0)) {
free(hdl);
return NULL;
}
_siomix_create(&hdl->siomix, &siomix_aucat_ops, mode, nbio);
hdl->tmp = NULL;
hdl->dump_wait = 0;
return (struct siomix_hdl *)hdl;
}
static void
siomix_aucat_close(struct siomix_hdl *addr)
{
struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr;
_aucat_close(&hdl->aucat, hdl->siomix.eof);
free(hdl);
}
static int
siomix_aucat_ondesc(struct siomix_hdl *addr)
{
struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr;
while (hdl->aucat.wstate != WSTATE_IDLE) {
if (!_siomix_psleep(&hdl->siomix, POLLOUT))
return 0;
}
AMSG_INIT(&hdl->aucat.wmsg);
hdl->aucat.wmsg.cmd = htonl(AMSG_MIXSUB);
hdl->aucat.wmsg.u.mixsub.desc = 1;
hdl->aucat.wmsg.u.mixsub.val = 0;
hdl->aucat.wtodo = sizeof(struct amsg);
if (!_aucat_wmsg(&hdl->aucat, &hdl->siomix.eof))
return 0;
hdl->dump_wait = 1;
while (hdl->dump_wait) {
DPRINTF("psleeping...\n");
if (!_siomix_psleep(&hdl->siomix, 0))
return 0;
DPRINTF("psleeping done\n");
}
DPRINTF("done\n");
return 1;
}
static int
siomix_aucat_onctl(struct siomix_hdl *addr)
{
struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr;
while (hdl->aucat.wstate != WSTATE_IDLE) {
if (!_siomix_psleep(&hdl->siomix, POLLOUT))
return 0;
}
AMSG_INIT(&hdl->aucat.wmsg);
hdl->aucat.wmsg.cmd = htonl(AMSG_MIXSUB);
hdl->aucat.wmsg.u.mixsub.desc = 1;
hdl->aucat.wmsg.u.mixsub.val = 1;
hdl->aucat.wtodo = sizeof(struct amsg);
if (!_aucat_wmsg(&hdl->aucat, &hdl->siomix.eof))
return 0;
return 1;
}
static int
siomix_aucat_setctl(struct siomix_hdl *addr, unsigned int a, unsigned int v)
{
struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr;
hdl->aucat.wstate = WSTATE_MSG;
hdl->aucat.wtodo = sizeof(struct amsg);
hdl->aucat.wmsg.cmd = htonl(AMSG_MIXSET);
hdl->aucat.wmsg.u.mixset.addr = htons(a);
hdl->aucat.wmsg.u.mixset.val = htons(v);
return _aucat_wmsg(&hdl->aucat, &hdl->siomix.eof);
}
static int
siomix_aucat_nfds(struct siomix_hdl *addr)
{
//struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr;
return 1;
}
static int
siomix_aucat_pollfd(struct siomix_hdl *addr, struct pollfd *pfd, int events)
{
struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr;
return _aucat_pollfd(&hdl->aucat, pfd, events | POLLIN);
}
static int
siomix_aucat_revents(struct siomix_hdl *addr, struct pollfd *pfd)
{
struct siomix_aucat_hdl *hdl = (struct siomix_aucat_hdl *)addr;
int revents;
revents = _aucat_revents(&hdl->aucat, pfd);
if (revents & POLLIN) {
do {
if (hdl->aucat.rstate == RSTATE_MSG) {
if (!siomix_aucat_runmsg(hdl))
break;
}
if (hdl->aucat.rstate == RSTATE_DATA) {
if (!siomix_aucat_rdata(hdl))
break;
}
} while (0);
revents &= ~POLLIN;
}
if (hdl->siomix.eof)
return POLLHUP;
DPRINTFN(3, "siomix_aucat_revents: revents = 0x%x\n", revents);
return revents;
}

View File

@ -1,261 +0,0 @@
.\" $OpenBSD$
.\"
.\" Copyright (c) 2011 Alexandre Ratchov <alex@caoua.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 29 2012 $
.Dt SIO_OPEN 3
.Os
.Sh NAME
.Nm siomix_open ,
.Nm siomix_close ,
.Nm siomix_ondesc ,
.Nm siomix_onctl ,
.Nm siomix_setctl ,
.Nm siomix_nfds ,
.Nm siomix_pollfd ,
.Nm siomix_eof
.Nd interface to audio mixer
.Sh SYNOPSIS
.Fd #include <sndio.h>
.Ft "struct siomix_hdl *"
.Fn "siomix_open" "const char *name" "unsigned int mode" "int nbio_flag"
.Ft "void"
.Fn "siomix_close" "struct siomix_hdl *hdl"
.Ft "int"
.Fn "siomix_ondesc" "struct siomix_hdl *hdl" "void (*cb)(void *arg, struct siomix_desc *desc, int val)" "void *arg"
.Ft "void"
.Fn "siomix_onctl" "struct siomix_hdl *hdl" "void (*cb)(void *arg, unsigned int addr, unsigned int val)" "void *arg"
.Ft "int"
.Fn "siomix_setctl" "struct siomix_hdl *hdl" "unsigned int addr" "unsigned int val"
.Ft "int"
.Fn "siomix_nfds" "struct siomix_hdl *hdl"
.Ft "int"
.Fn "siomix_pollfd" "struct siomix_hdl *hdl" "struct pollfd *pfd" "int events"
.Ft "int"
.Fn "siomix_revents" "struct siomix_hdl *hdl" "struct pollfd *pfd"
.Ft "int"
.Fn "siomix_eof" "struct siomix_hdl *hdl"
.Sh DESCRIPTION
The audio mixer of a sound device is the set of available controls,
e.g. the volume control.
Each control has an integer
.Em address
and an integer
.Em value .
Depending on the control type, its integer value represents either a
continuous quantity or a boolean.
Any control may be changed by submitting
a new value to its address.
When values change, asynchronous notifications are sent.
.Pp
Controls descriptions are available, allowing them to be grouped and
represented in a human usable form.
.Sh Opening and closing the mixer
First the application must call the
.Fn siomix_open
function to obtain a handle
that will be passed as the
.Ar hdl
argument to other functions.
.Pp
The
.Ar name
parameter gives the device string discussed in
.Xr sndio 7 .
In most cases it should be set to SIOMIX_DEVANY to allow
the user to select it using the
.Ev AUDIODEVICE
environment variable.
The
.Ar mode
parameter is a bitmap of the SIOMIX_READ and SIOMIX_WRITE constants
indicating whether control values can be read and
modified respectively.
.Pp
If the
.Ar nbio_flag
argument is 1, then the
.Fn siomix_setctl
function (see below) may fail instead of blocking and
the
.Fn siomix_ondesc
function doesn't block.
.Pp
The
.Fn siomix_close
function closes the mixer and frees any allocated resources
associated with the handle.
.Sh Mixer description
The
.Fn siomix_ondesc
function can be used to obtain the description of all available mixer controls
and their initial values.
It registers a call-back that is immediately invoked for all
controls.
It's called once with a NULL argument to indicate that the full
description was sent and that the caller has a consistent
representation of the mixer.
.Pp
Then, whenever a mixer control description changes (currently only
label strings may change, see below), the call-back is invoked with the
updated information followed by a call with a NULL argument.
.Pp
Controls are described by the
.Va siomix_ondesc
stucture as follows:
.Bd -literal
struct siomix_chan {
char str[SIOMIX_NAMEMAX]; /* stream name */
char opt[SIOMIX_NAMEMAX]; /* optional channel */
};
struct siomix_desc {
unsigned int addr; /* control's address */
#define SIOMIX_NUM 2 /* number in the 0..127 range */
#define SIOMIX_SW 3 /* on/off switch */
#define SIOMIX_VEC 4 /* element of array of numbers */
#define SIOMIX_LIST 5 /* element of array of switches */
#define SIOMIX_LABEL 6 /* string attached to chan0 */
unsigned int type; /* one of above */
char func[SIOMIX_NAMEMAX]; /* parameter group name */
struct siomix_chan chan0; /* affected channels */
struct siomix_chan chan1; /* dito for vec, and list */
};
.Ed
.Pp
The
.Va addr
attribute is the mixer control address, usable with
.Fn siomix_setval
to set its value.
.Pp
The
.Va type
attribute indicates what the structure describes.
Possible types are:
.Bl -tag -width "SIOMIX_LABEL"
.It SIOMIX_NUM
A continuous control in the 0..SIOMIX_INTMAX range.
For instance the volume of the speaker.
.It SIOMIX_SW
A on/off switch control.
For instance the switch to mute the speaker.
.It SIOMIX_VEC
Element of an array of continuous controls.
For instance the knob to control the amount of signal flowing
from the line input to the speaker.
.It SIOMIX_LIST
An element of an array of on/off switches.
For instance the line-in position of the
speaker source selector.
.It SIOMIX_LABEL
A label attached to the channel.
In mixers exposed by
.Xr sndiod 1 ,
they correspond to program names.
The label string is stored in the
.Va chan1
attribute and is not unique.
Labels may dynamically change, but their
.Va addr
attribute remains the same and can be used to figure out which
label is changing.
.El
.Pp
The
.Va func
attribute is the name of the parameter being controlled.
There may be no parameters of different types with the same name.
.Pp
The
.Va chan0
and
.Va chan1
attributes indicate the names of the affected streams, and
an optional channel sub-set.
.Va chan1
is meaningful for
.Va SIOMIX_VEC
and
.Va SIOMIX_LIST
only.
.Pp
Stream names in the
.Va chan0
and
.Va chan1
attributes and
.Va func
are static strings usable as unique identifiers.
.Sh Changing and reading control values
Controls are changed with the
.Fn siomix_setctl
function, by giving the index of the control and the new value.
The
.Fn siomix_onctl
function can be used to register a call-back which will be invoked whenever
a control changes.
Continuous values are in the 0..127 range.
.Sh "Interface to" Xr poll 2
The
.Fn siomix_pollfd
function fills the array
.Ar pfd
of
.Va pollfd
structures, used by
.Xr poll 2 ,
with
.Ar events ;
the latter is a bit-mask of
.Va POLLIN
and
.Va POLLOUT
constants.
.Fn siomix_pollfd
returns the number of
.Va pollfd
structures filled.
The
.Fn siomix_revents
function returns the bit-mask set by
.Xr poll 2
in the
.Va pfd
array of
.Va pollfd
structures.
If
.Va POLLOUT
is set,
.Fn siomix_setctl
can be called without blocking.
POLLHUP may be set if an error occurs, even if
it is not selected with
.Fn siomix_pollfd .
POLLIN is not used yet.
.Pp
The
.Fn siomix_nfds
function returns the number of
.Va pollfd
structures the caller must preallocate in order to be sure
that
.Fn siomix_pollfd
will never overrun.
.Sh SEE ALSO
.Xr sndioctl 1 ,
.Xr poll 2 ,
.Xr sndio 7

View File

@ -1,67 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SIOMIX_PRIV_H
#define SIOMIX_PRIV_H
#include <sndio.h>
#define SIOMIX_MAXNFDS 4
/*
* private ``handle'' structure
*/
struct siomix_hdl {
struct siomix_ops *ops;
void (*desc_cb)(void *, struct siomix_desc *, int);
void *desc_arg;
void (*ctl_cb)(void *, unsigned int, unsigned int);
void *ctl_arg;
unsigned int mode; /* SIOMIX_READ | SIOMIX_WRITE */
int nbio; /* true if non-blocking io */
int eof; /* true if error occured */
};
/*
* operations every device should support
*/
struct siomix_ops {
void (*close)(struct siomix_hdl *);
int (*nfds)(struct siomix_hdl *);
int (*pollfd)(struct siomix_hdl *, struct pollfd *, int);
int (*revents)(struct siomix_hdl *, struct pollfd *);
int (*setctl)(struct siomix_hdl *, unsigned int, unsigned int);
int (*onctl)(struct siomix_hdl *);
int (*ondesc)(struct siomix_hdl *);
};
struct siomix_hdl *_siomix_aucat_open(const char *, unsigned int, int);
struct siomix_hdl *_siomix_obsd_open(const char *, unsigned int, int);
struct siomix_hdl *_siomix_fake_open(const char *, unsigned int, int);
#ifdef USE_SUN_MIXER
struct siomix_hdl *_siomix_sun_open(const char *, unsigned int, int);
#endif
#ifdef USE_ALSA_MIXER
struct siomix_hdl *_siomix_alsa_open(const char *, unsigned int, int);
#endif
void _siomix_create(struct siomix_hdl *,
struct siomix_ops *, unsigned int, int);
void _siomix_ondesc_cb(struct siomix_hdl *,
struct siomix_desc *, unsigned int);
void _siomix_onctl_cb(struct siomix_hdl *, unsigned int, unsigned int);
int _siomix_psleep(struct siomix_hdl *, int);
#endif /* !defined(SIOMIX_PRIV_H) */

View File

@ -1,573 +0,0 @@
/*
* Copyright (c) 2010-2011 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
*
* TODO
* - fix ac97 based mixers
*
*/
#ifdef USE_SUN_MIXER
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/audioio.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <poll.h>
#include <sndio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "debug.h"
#include "siomix_priv.h"
struct siomix_sun_hdl {
struct siomix_hdl siomix;
struct mixer_devinfo *info;
struct mixer_ctrl *curval;
int fd, ninfo, events;
int iclass, oclass, rclass;
};
static void siomix_sun_close(struct siomix_hdl *);
static int siomix_sun_nfds(struct siomix_hdl *);
static int siomix_sun_pollfd(struct siomix_hdl *, struct pollfd *, int);
static int siomix_sun_revents(struct siomix_hdl *, struct pollfd *);
static int siomix_sun_setctl(struct siomix_hdl *, unsigned int, unsigned int);
static int siomix_sun_onctl(struct siomix_hdl *);
static int siomix_sun_ondesc(struct siomix_hdl *);
/*
* operations every device should support
*/
struct siomix_ops siomix_sun_ops = {
siomix_sun_close,
siomix_sun_nfds,
siomix_sun_pollfd,
siomix_sun_revents,
siomix_sun_setctl,
siomix_sun_onctl,
siomix_sun_ondesc
};
struct siomix_hdl *
_siomix_sun_open(const char *str, unsigned int mode, int nbio)
{
struct siomix_sun_hdl *hdl;
int i, fd, flags;
char path[PATH_MAX];
struct mixer_devinfo mi;
if (*str != '/') {
DPRINTF("siomix_sun_open: %s: '/<devnum>' expected\n", str);
return NULL;
}
str++;
hdl = malloc(sizeof(struct siomix_sun_hdl));
if (hdl == NULL)
return NULL;
_siomix_create(&hdl->siomix, &siomix_sun_ops, mode, nbio);
snprintf(path, sizeof(path), "/dev/mixer%s", str);
if (mode == (SIOMIX_READ | SIOMIX_WRITE))
flags = O_RDWR;
else
flags = (mode & SIOMIX_WRITE) ? O_WRONLY : O_RDONLY;
while ((fd = open(path, flags)) < 0) {
if (errno == EINTR)
continue;
DPERROR(path);
goto bad_free;
}
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
DPERROR("FD_CLOEXEC");
goto bad_close;
}
hdl->iclass = hdl->oclass = hdl->rclass = -1;
hdl->fd = fd;
/*
* count the number of mixer knobs, and fetch the full mixer
* description
*/
for (mi.index = 0; ; mi.index++) {
if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0)
break;
}
hdl->ninfo = mi.index;
hdl->info = malloc(hdl->ninfo * sizeof(struct mixer_devinfo));
if (hdl->info == NULL) {
DPERROR("malloc");
goto bad_close;
}
hdl->curval = malloc(hdl->ninfo * sizeof(struct mixer_ctrl));
if (hdl->curval == NULL) {
DPERROR("malloc");
goto bad_freeinfo;
}
for (i = 0; i < hdl->ninfo; i++) {
hdl->info[i].index = i;
if (ioctl(fd, AUDIO_MIXER_DEVINFO, &hdl->info[i]) < 0) {
DPERROR("AUDIO_MIXER_DEVINFO");
goto bad_freeval;
}
}
return (struct siomix_hdl *)hdl;
bad_freeval:
free(hdl->curval);
bad_freeinfo:
free(hdl->info);
bad_close:
close(fd);
bad_free:
free(hdl);
return NULL;
}
static void
siomix_sun_close(struct siomix_hdl *addr)
{
struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr;
close(hdl->fd);
free(hdl);
}
/*
* parse foo-4:5 and convert it to "foo", 4, 2
*/
static int
copy_ch(struct siomix_sun_hdl *hdl,
int icls, char *istr, char *ostr, int *rmin, int *rnum)
{
size_t len;
char *sep, *endp;
long cmin, cmax;
ostr[0] = 0;
sep = strchr(istr, '-');
if (sep) {
len = sep - istr;
if (len >= SIOMIX_NAMEMAX - 1)
return 0;
memcpy(ostr, istr, len);
ostr[len] = 0;
istr = sep + 1;
cmin = strtol(istr, &endp, 10);
if (endp != istr) {
/*
* this a "foo-0:3" style range
*/
istr = endp;
if (*endp == ':') {
istr++;
cmax = strtol(istr, &endp, 10);
if (endp == istr) {
DPRINTF("bad range\n");
return 0;
}
istr = endp;
} else if (*endp == 0) {
cmax = cmin;
} else {
DPRINTF("unknown range\n");
return 0;
}
*rmin = cmin;
*rnum = cmax - cmin + 1;
} else {
if (strcmp(ostr, "line") == 0) {
/* rename make "line-foo" to "foo" */
ostr[0] = 0;
} else {
/* append unknown suffix with '_' */
strlcat(ostr, "_", SIOMIX_NAMEMAX);
}
strlcat(ostr, istr, SIOMIX_NAMEMAX);
*rmin = 0;
*rnum = 0;
}
} else {
*rmin = 0;
*rnum = 0;
strlcpy(ostr, istr, SIOMIX_NAMEMAX);
}
if (icls == -1)
return 1;
/*
* append "_in" and "_out" suffixes, as nowadays
* most jacks are bidirectional
*/
if (strcmp(ostr, "mic") == 0 ||
strcmp(ostr, "spkr") == 0 ||
strcmp(ostr, "hp") == 0 ||
strcmp(ostr, "line") == 0) {
if (icls == hdl->iclass)
strlcat(ostr, "_in", SIOMIX_NAMEMAX);
if (icls == hdl->oclass)
strlcat(ostr, "_out", SIOMIX_NAMEMAX);
}
/*
* record class may conflict with input/output
*/
if (icls == hdl->rclass) {
if (strcmp(ostr, "volume") == 0)
strlcpy(ostr, "rec", SIOMIX_NAMEMAX);
}
return 1;
}
static void
make_opt(char *opt, int min, int num)
{
switch (num) {
case 0:
opt[0] = 0;
break;
case 1:
snprintf(opt, SIOMIX_NAMEMAX, "%u", min);
break;
default:
snprintf(opt, SIOMIX_NAMEMAX, "%u-%u", min, min + num - 1);
break;
}
}
static int
copyname_num(struct siomix_sun_hdl *hdl,
struct mixer_devinfo *info, struct siomix_desc *desc, int *rmin, int *rnum)
{
size_t len;
char *sep, *istr;
sep = strchr(info->label.name, '_');
if (sep) {
strlcpy(desc->func, "mix", SIOMIX_NAMEMAX);
desc->type = SIOMIX_VEC;
len = sep - info->label.name;
if (len >= SIOMIX_NAMEMAX - 1)
return 0;
memcpy(desc->chan0.str, info->label.name, len);
desc->chan0.str[len] = 0;
istr = sep + 1;
if (!copy_ch(hdl, info->mixer_class, istr,
desc->chan1.str, rmin, rnum))
return 0;
} else {
strlcpy(desc->func, "level", SIOMIX_NAMEMAX);
desc->type = SIOMIX_NUM;
istr = info->label.name;
if (!copy_ch(hdl, info->mixer_class, istr,
desc->chan0.str, rmin, rnum))
return 0;
desc->chan1.str[0] = '\0';
}
return 1;
}
static int
copyname_enum(struct siomix_sun_hdl *hdl,
struct mixer_devinfo *info, struct siomix_desc *desc, int *rmin, int *rnum)
{
char istr[SIOMIX_NAMEMAX], *sep;
size_t len;
sep = strrchr(info->label.name, '.');
if (sep == NULL)
sep = strrchr(info->label.name, '_');
if (sep == NULL) {
if (info->prev < 0) {
fprintf(stderr, "no separator\n");
return 0;
}
strlcpy(desc->func, info->label.name, SIOMIX_NAMEMAX);
while (info->prev >= 0)
info = hdl->info + info->prev;
if (!copy_ch(hdl, info->mixer_class, info->label.name,
desc->chan0.str, rmin, rnum))
return 0;
desc->chan1.str[0] = 0;
} else {
strlcpy(desc->func, sep + 1, SIOMIX_NAMEMAX);
len = sep - info->label.name;
if (len >= SIOMIX_NAMEMAX - 1)
return 0;
memcpy(istr, info->label.name, len);
istr[len] = '\0';
if (!copy_ch(hdl, info->mixer_class, istr,
desc->chan0.str, rmin, rnum))
return 0;
desc->chan1.str[0] = 0;
}
/*
* certain cards expose adc[0-1].source and adc[2-3].source
* as different types, which we forbid.
*/
if (strcmp(desc->func, "source") == 0) {
if (info->type == AUDIO_MIXER_SET)
strlcpy(desc->func, "sources", SIOMIX_NAMEMAX);
}
return 1;
}
static int
ord_to_num(struct mixer_devinfo *info, int ord)
{
int i;
for (i = 0; i < info->un.e.num_mem; i++) {
if (ord == info->un.e.member[i].ord)
return i;
}
DPRINTF("mixer bug: order not found\n");
return 0;
}
static int
mask_to_bit(struct mixer_devinfo *info, int index, int val)
{
int mask;
mask = info->un.s.member[index].mask;
if ((mask & val) == mask)
return 1;
else
return 0;
return 0;
}
static int
enum_to_sw(struct mixer_devinfo *info, struct siomix_desc *desc)
{
char *v0, *v1;
if (info->un.e.num_mem != 2)
return 0;
v0 = info->un.e.member[ord_to_num(info, 0)].label.name;
v1 = info->un.e.member[ord_to_num(info, 1)].label.name;
if (strcmp(v0, "off") == 0 && strcmp(v1, "on") == 0)
goto make_sw;
if (strcmp(v0, "unplugged") == 0 && strcmp(v1, "plugged") == 0) {
strlcpy(desc->func,
info->un.e.member[1].label.name,
SIOMIX_NAMEMAX);
goto make_sw;
}
return 0;
make_sw:
desc->chan1.str[0] = 0;
desc->chan1.opt[0] = 0;
desc->type = SIOMIX_SW;
return 1;
}
static int
siomix_sun_ondesc(struct siomix_hdl *addr)
{
struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr;
struct mixer_devinfo *info;
struct mixer_ctrl *ctrl;
struct siomix_desc desc;
char *ostr;
int i, j, v, cmin, cnum;
for (i = 0; i < hdl->ninfo; i++) {
info = hdl->info + i;
ctrl = hdl->curval + i;
ctrl->dev = i;
ctrl->type = info->type;
if (ctrl->type == AUDIO_MIXER_CLASS) {
if (strcmp(info->label.name, "inputs") == 0)
hdl->iclass = i;
if (strcmp(info->label.name, "outputs") == 0)
hdl->oclass = i;
if (strcmp(info->label.name, "record") == 0)
hdl->rclass = i;
continue;
}
if (ctrl->type == AUDIO_MIXER_VALUE)
ctrl->un.value.num_channels = info->un.v.num_channels;
if (ioctl(hdl->fd, AUDIO_MIXER_READ, ctrl) < 0) {
DPERROR("AUDIO_MIXER_READ");
hdl->siomix.eof = 1;
return 0;
}
}
info = hdl->info;
for (i = 0; i < hdl->ninfo; i++) {
DPRINTF("psarsing \"%s\"\n", info->label.name);
switch (info->type) {
case AUDIO_MIXER_VALUE:
desc.addr = i * 32;
if (!copyname_num(hdl, info, &desc, &cmin, &cnum))
return 0;
make_opt(desc.chan0.opt, cmin, cnum);
desc.chan1.opt[0] = 0;
for (j = 0; j < info->un.v.num_channels; j++) {
v = hdl->curval[i].un.value.level[j] *
127 / 255;
ostr = desc.type == SIOMIX_NUM ?
desc.chan0.opt : desc.chan1.opt;
if (info->un.v.num_channels > 1) {
make_opt(ostr, cmin + j, 1);
} else {
make_opt(ostr, cmin, cnum);
}
_siomix_ondesc_cb(&hdl->siomix, &desc, v);
desc.addr++;
}
break;
case AUDIO_MIXER_ENUM:
desc.addr = i * 32;
if (info->un.e.num_mem <= 1)
break;
if (!copyname_enum(hdl, info, &desc, &cmin, &cnum))
return 0;
if (enum_to_sw(info, &desc)) {
make_opt(desc.chan0.opt, cmin, cnum);
_siomix_ondesc_cb(&hdl->siomix, &desc,
ord_to_num(info, hdl->curval[i].un.ord));
break;
}
for (j = 0; j < info->un.e.num_mem; j++) {
if (!copyname_enum(hdl, info,
&desc, &cmin, &cnum))
return 0;
make_opt(desc.chan0.opt, cmin, cnum);
if (!copy_ch(hdl, info->mixer_class,
info->un.e.member[j].label.name,
desc.chan1.str, &cmin, &cnum))
return 0;
make_opt(desc.chan1.opt, cmin, cnum);
desc.type = SIOMIX_LIST;
v = (j == ord_to_num(info,
hdl->curval[i].un.ord)) ? 1 : 0;
_siomix_ondesc_cb(&hdl->siomix, &desc, v);
desc.addr++;
}
break;
case AUDIO_MIXER_SET:
desc.addr = i * 32;
if (info->un.s.num_mem == 0)
break;
if (!copyname_enum(hdl, info, &desc, &cmin, &cnum))
return 0;
make_opt(desc.chan0.opt, cmin, cnum);
desc.type = SIOMIX_LIST;
for (j = 0; j < info->un.s.num_mem; j++) {
if (!copy_ch(hdl, info->mixer_class,
info->un.s.member[j].label.name,
desc.chan1.str, &cmin, &cnum))
return 0;
make_opt(desc.chan1.opt, cmin, cnum);
_siomix_ondesc_cb(&hdl->siomix, &desc,
mask_to_bit(info, j,
hdl->curval[i].un.mask));
desc.addr++;
}
break;
}
info++;
}
_siomix_ondesc_cb(&hdl->siomix, NULL, 0);
return 1;
}
static int
siomix_sun_onctl(struct siomix_hdl *addr)
{
//struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr;
return 1;
}
static int
siomix_sun_setctl(struct siomix_hdl *arg, unsigned int addr, unsigned int val)
{
struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)arg;
struct mixer_ctrl *ctrl;
struct mixer_devinfo *info;
int base, offs, oldv;
DPRINTF("siomix_sun_setctl: %d set to %d\n", addr, val);
base = addr / 32;
offs = addr % 32;
ctrl = hdl->curval + base;
info = hdl->info + base;
switch (ctrl->type) {
case AUDIO_MIXER_VALUE:
oldv = ctrl->un.value.level[offs];
ctrl->un.value.level[offs] = (val * 255 + 63) / 127;
break;
case AUDIO_MIXER_ENUM:
if (val == 0)
return 1;
oldv = ord_to_num(info, ctrl->un.ord);
if (oldv == offs)
return 1;
_siomix_onctl_cb(&hdl->siomix, 32 * base + oldv, 0);
ctrl->un.ord = info->un.e.member[offs].ord;
break;
case AUDIO_MIXER_SET:
if (val)
ctrl->un.mask |= info->un.s.member[offs].mask;
else
ctrl->un.mask &= ~info->un.s.member[offs].mask;
break;
default:
DPRINTF("siomix_sun_setctl: wrong addr %d\n", addr);
hdl->siomix.eof = 1;
return 0;
}
if (ioctl(hdl->fd, AUDIO_MIXER_WRITE, ctrl) < 0) {
DPERROR("siomix_sun_setctl");
hdl->siomix.eof = 1;
return 0;
}
return 1;
}
static int
siomix_sun_nfds(struct siomix_hdl *addr)
{
return 0;
}
static int
siomix_sun_pollfd(struct siomix_hdl *addr, struct pollfd *pfd, int events)
{
struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr;
hdl->events = events;
return 0;
}
static int
siomix_sun_revents(struct siomix_hdl *addr, struct pollfd *pfd)
{
struct siomix_sun_hdl *hdl = (struct siomix_sun_hdl *)addr;
return hdl->events & POLLOUT;
}
#endif

View File

@ -1,193 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2014 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/time.h>
#include <sys/types.h>
#include <poll.h>
#include <sndio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "abuf.h"
#include "defs.h"
#include "dev.h"
#include "dsp.h"
#include "file.h"
#include "dev_siomix.h"
#include "utils.h"
#include "bsd-compat.h"
void dev_siomix_ondesc(void *, struct siomix_desc *, int);
void dev_siomix_onctl(void *, unsigned int, unsigned int);
int dev_siomix_pollfd(void *, struct pollfd *);
int dev_siomix_revents(void *, struct pollfd *);
void dev_siomix_in(void *);
void dev_siomix_out(void *);
void dev_siomix_hup(void *);
struct fileops dev_siomix_ops = {
"siomix",
dev_siomix_pollfd,
dev_siomix_revents,
dev_siomix_in,
dev_siomix_out,
dev_siomix_hup
};
void
dev_siomix_ondesc(void *arg, struct siomix_desc *desc, int val)
{
struct dev *d = arg;
struct ctl *c;
if (desc == NULL)
return;
for (c = d->ctl_list; c != NULL; c = c->next) {
if (c->addr != desc->addr)
continue;
if (c->type != SIOMIX_LABEL)
continue;
ctl_log(c);
log_puts(": label -> ");
log_puts(desc->chan0.str);
log_puts("\n");
strlcpy(c->chan0.str, desc->chan0.str, CTL_NAMEMAX);
c->desc_mask = ~0;
return;
}
c = dev_addctl(d, desc->type, desc->addr,
desc->chan0.str, desc->chan0.opt, desc->func,
desc->chan1.str, desc->chan1.opt);
c->curval = val;
#ifdef DEBUG
if (log_level >= 3) {
dev_log(d);
log_puts(": added: ");
ctl_log(c);
log_puts("\n");
}
#endif
}
void
dev_siomix_onctl(void *arg, unsigned int addr, unsigned int val)
{
struct dev *d = arg;
struct ctl *c;
dev_log(d);
log_puts(": onctl ");
log_putu(addr);
log_puts(", ");
log_putu(val);
log_puts("\n");
for (c = d->ctl_list; c != NULL; c = c->next) {
if (c->addr != addr)
continue;
ctl_log(c);
log_puts(": new value -> ");
log_putu(val);
log_puts("\n");
c->val_mask = ~0U;
c->curval = val;
}
}
/*
* open the mixer device.
*/
void
dev_siomix_open(struct dev *d)
{
d->siomix.hdl = siomix_open(d->path, SIOMIX_READ | SIOMIX_WRITE, 0);
if (d->siomix.hdl == NULL)
return;
siomix_ondesc(d->siomix.hdl, dev_siomix_ondesc, d);
siomix_onctl(d->siomix.hdl, dev_siomix_onctl, d);
d->siomix.file = file_new(&dev_siomix_ops, d, d->path,
siomix_nfds(d->siomix.hdl));
}
/*
* close the mixer device.
*/
void
dev_siomix_close(struct dev *d)
{
if (d->siomix.hdl == NULL)
return;
file_del(d->siomix.file);
siomix_close(d->siomix.hdl);
d->siomix.hdl = NULL;
}
int
dev_siomix_pollfd(void *arg, struct pollfd *pfd)
{
struct dev *d = arg;
struct ctl *c;
int events = 0;
for (c = d->ctl_list; c != NULL; c = c->next) {
if (c->dirty)
events |= POLLOUT;
}
return siomix_pollfd(d->siomix.hdl, pfd, events);
}
int
dev_siomix_revents(void *arg, struct pollfd *pfd)
{
struct dev *d = arg;
return siomix_revents(d->siomix.hdl, pfd);
}
void
dev_siomix_in(void *arg)
{
}
void
dev_siomix_out(void *arg)
{
struct dev *d = arg;
struct ctl *c;
for (c = d->ctl_list; c != NULL; c = c->next) {
if (!c->dirty)
continue;
if (!siomix_setctl(d->siomix.hdl, c->addr, c->curval))
break;
if (log_level >= 2) {
ctl_log(c);
log_puts(": changed\n");
}
c->dirty = 0;
dev_unref(d);
}
}
void
dev_siomix_hup(void *arg)
{
struct dev *d = arg;
dev_siomix_close(d);
}

View File

@ -1,32 +0,0 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2014 Alexandre Ratchov <alex@caoua.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef DEV_SIOMIX_H
#define DEV_SIOMIX_H
#include "file.h"
struct dev;
struct dev_siomix {
struct siomix_hdl *hdl;
struct file *file;
};
void dev_siomix_open(struct dev *);
void dev_siomix_close(struct dev *);
#endif /* !defined(DEV_SIOMIX_H) */