Annotation of src/usr.bin/sndiod/dev_sioctl.c, Revision 1.8
1.8 ! ratchov 1: /* $OpenBSD: dev_sioctl.c,v 1.7 2021/03/03 10:00:27 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2014-2020 Alexandre Ratchov <alex@caoua.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <sys/time.h>
18: #include <sys/types.h>
19:
20: #include <poll.h>
21: #include <sndio.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #include "abuf.h"
26: #include "defs.h"
27: #include "dev.h"
28: #include "dsp.h"
29: #include "file.h"
30: #include "dev_sioctl.h"
31: #include "utils.h"
32:
33: void dev_sioctl_ondesc(void *, struct sioctl_desc *, int);
34: void dev_sioctl_onval(void *, unsigned int, unsigned int);
35: int dev_sioctl_pollfd(void *, struct pollfd *);
36: int dev_sioctl_revents(void *, struct pollfd *);
37: void dev_sioctl_in(void *);
38: void dev_sioctl_out(void *);
39: void dev_sioctl_hup(void *);
40:
41: struct fileops dev_sioctl_ops = {
42: "sioctl",
43: dev_sioctl_pollfd,
44: dev_sioctl_revents,
45: dev_sioctl_in,
46: dev_sioctl_out,
47: dev_sioctl_hup
48: };
49:
50: void
51: dev_sioctl_ondesc(void *arg, struct sioctl_desc *desc, int val)
52: {
53: struct dev *d = arg;
1.7 ratchov 54: char *group, group_buf[CTL_NAMEMAX];
1.1 ratchov 55:
1.2 ratchov 56: if (desc == NULL) {
57: dev_ctlsync(d);
1.1 ratchov 58: return;
1.2 ratchov 59: }
60:
1.7 ratchov 61: ctl_del(CTL_HW, d, &desc->addr);
1.1 ratchov 62:
1.7 ratchov 63: if (desc->group[0] == 0)
64: group = d->name;
65: else {
66: if (snprintf(group_buf, CTL_NAMEMAX, "%s/%s",
67: d->name, desc->group) >= CTL_NAMEMAX)
68: return;
1.1 ratchov 69: group = group_buf;
1.7 ratchov 70: }
1.1 ratchov 71:
1.7 ratchov 72: ctl_new(CTL_HW, d, &desc->addr,
73: desc->type, group,
1.1 ratchov 74: desc->node0.name, desc->node0.unit, desc->func,
75: desc->node1.name, desc->node1.unit, desc->maxval, val);
76: }
77:
78: void
79: dev_sioctl_onval(void *arg, unsigned int addr, unsigned int val)
80: {
81: struct dev *d = arg;
82: struct ctl *c;
83:
1.8 ! ratchov 84: if (log_level >= 2) {
! 85: dev_log(d);
! 86: log_puts(": onctl: addr = ");
! 87: log_putu(addr);
! 88: log_puts(", val = ");
! 89: log_putu(val);
! 90: log_puts("\n");
! 91: }
1.1 ratchov 92:
1.7 ratchov 93: for (c = ctl_list; c != NULL; c = c->next) {
94: if (c->scope != CTL_HW || c->u.hw.addr != addr)
1.1 ratchov 95: continue;
1.8 ! ratchov 96:
! 97: if (log_level >= 2) {
! 98: ctl_log(c);
! 99: log_puts(": new value -> ");
! 100: log_putu(val);
! 101: log_puts("\n");
! 102: }
! 103:
1.1 ratchov 104: c->val_mask = ~0U;
105: c->curval = val;
106: }
107: }
108:
109: /*
110: * open the control device.
111: */
112: void
113: dev_sioctl_open(struct dev *d)
114: {
1.3 ratchov 115: if (d->sioctl.hdl == NULL) {
116: /*
117: * At this point there are clients, for instance if we're
118: * called by dev_reopen() but the control device couldn't
119: * be opened. In this case controls have changed (thoseof
120: * old device are just removed) so we need to notify clients.
121: */
122: dev_ctlsync(d);
1.1 ratchov 123: return;
1.3 ratchov 124: }
1.1 ratchov 125: sioctl_ondesc(d->sioctl.hdl, dev_sioctl_ondesc, d);
126: sioctl_onval(d->sioctl.hdl, dev_sioctl_onval, d);
127: }
128:
129: /*
130: * close the control device.
131: */
132: void
133: dev_sioctl_close(struct dev *d)
134: {
1.5 ratchov 135: struct ctl *c, **pc;
136:
137: /* remove controls */
1.7 ratchov 138: pc = &ctl_list;
1.5 ratchov 139: while ((c = *pc) != NULL) {
1.7 ratchov 140: if (c->scope == CTL_HW && c->u.hw.dev == d) {
1.5 ratchov 141: c->refs_mask &= ~CTL_DEVMASK;
142: if (c->refs_mask == 0) {
143: *pc = c->next;
144: xfree(c);
145: continue;
146: }
147: c->type = CTL_NONE;
148: c->desc_mask = ~0;
149: }
150: pc = &c->next;
151: }
152: dev_ctlsync(d);
1.1 ratchov 153: }
154:
155: int
156: dev_sioctl_pollfd(void *arg, struct pollfd *pfd)
157: {
158: struct dev *d = arg;
159: struct ctl *c;
160: int events = 0;
161:
1.7 ratchov 162: for (c = ctl_list; c != NULL; c = c->next) {
163: if (c->scope == CTL_HW && c->u.hw.dev == d && c->dirty)
1.1 ratchov 164: events |= POLLOUT;
165: }
166: return sioctl_pollfd(d->sioctl.hdl, pfd, events);
167: }
168:
169: int
170: dev_sioctl_revents(void *arg, struct pollfd *pfd)
171: {
172: struct dev *d = arg;
173:
174: return sioctl_revents(d->sioctl.hdl, pfd);
175: }
176:
177: void
178: dev_sioctl_in(void *arg)
179: {
180: }
181:
182: void
183: dev_sioctl_out(void *arg)
184: {
185: struct dev *d = arg;
186: struct ctl *c;
187: int cnt;
188:
189: /*
190: * for each dirty ctl, call sioctl_setval() and dev_unref(). As
191: * dev_unref() may destroy the ctl_list, we must call it after
192: * we've finished iterating on it.
193: */
194: cnt = 0;
1.7 ratchov 195: for (c = ctl_list; c != NULL; c = c->next) {
196: if (c->scope != CTL_HW || c->u.hw.dev != d || !c->dirty)
1.1 ratchov 197: continue;
1.7 ratchov 198: if (!sioctl_setval(d->sioctl.hdl, c->u.hw.addr, c->curval)) {
1.1 ratchov 199: ctl_log(c);
200: log_puts(": set failed\n");
201: break;
202: }
203: if (log_level >= 2) {
204: ctl_log(c);
205: log_puts(": changed\n");
206: }
207: c->dirty = 0;
208: cnt++;
209: }
210: while (cnt-- > 0)
211: dev_unref(d);
212: }
213:
214: void
215: dev_sioctl_hup(void *arg)
216: {
217: struct dev *d = arg;
218:
219: dev_sioctl_close(d);
1.5 ratchov 220: file_del(d->sioctl.file);
221: sioctl_close(d->sioctl.hdl);
222: d->sioctl.hdl = NULL;
1.1 ratchov 223: }