Bug Summary

File:src/lib/libsndio/sio.c
Warning:line 398, column 3
The right operand of '*' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name sio.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libsndio/obj -resource-dir /usr/local/lib/clang/13.0.0 -D DEBUG -D PIC -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libsndio/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libsndio/sio.c
1/* $OpenBSD: sio.c,v 1.26 2021/11/01 14:43:24 ratchov Exp $ */
2/*
3 * Copyright (c) 2008 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
18#include <sys/types.h>
19
20#include <errno(*__errno()).h>
21#include <fcntl.h>
22#include <poll.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <time.h>
27#include <unistd.h>
28
29#include "debug.h"
30#include "sio_priv.h"
31
32#define SIO_PAR_MAGIC0x83b905a4 0x83b905a4
33
34void
35sio_initpar(struct sio_par *par)
36{
37 memset(par, 0xff, sizeof(struct sio_par));
38 par->__magic = SIO_PAR_MAGIC0x83b905a4;
39}
40
41struct sio_hdl *
42sio_open(const char *str, unsigned int mode, int nbio)
43{
44 static char devany[] = SIO_DEVANY"default";
45 struct sio_hdl *hdl;
46
47#ifdef DEBUG1
48 _sndio_debug_init();
49#endif
50 if ((mode & (SIO_PLAY1 | SIO_REC2)) == 0)
51 return NULL((void *)0);
52 if (str == NULL((void *)0)) /* backward compat */
53 str = devany;
54 if (strcmp(str, devany) == 0 && !issetugid()) {
55 if ((mode & SIO_PLAY1) == 0)
56 str = getenv("AUDIORECDEVICE");
57 if ((mode & SIO_REC2) == 0)
58 str = getenv("AUDIOPLAYDEVICE");
59 if (mode == (SIO_PLAY1 | SIO_REC2) || str == NULL((void *)0))
60 str = getenv("AUDIODEVICE");
61 if (str == NULL((void *)0))
62 str = devany;
63 }
64 if (strcmp(str, devany) == 0) {
65 hdl = _sio_aucat_open("snd/default", mode, nbio);
66 if (hdl != NULL((void *)0))
67 return hdl;
68 return _sio_sun_open("rsnd/0", mode, nbio);
69 }
70 if (_sndio_parsetype(str, "snd"))
71 return _sio_aucat_open(str, mode, nbio);
72 if (_sndio_parsetype(str, "rsnd"))
73 return _sio_sun_open(str, mode, nbio);
74 DPRINTF("sio_open: %s: unknown device type\n", str)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_open: %s: unknown device type\n"
, str); } while(0)
;
75 return NULL((void *)0);
76}
77
78void
79_sio_create(struct sio_hdl *hdl, struct sio_ops *ops,
80 unsigned int mode, int nbio)
81{
82 hdl->ops = ops;
83 hdl->mode = mode;
84 hdl->nbio = nbio;
85 hdl->started = 0;
86 hdl->eof = 0;
87 hdl->move_cb = NULL((void *)0);
88 hdl->vol_cb = NULL((void *)0);
89}
90
91void
92sio_close(struct sio_hdl *hdl)
93{
94 hdl->ops->close(hdl);
95}
96
97int
98sio_start(struct sio_hdl *hdl)
99{
100#ifdef DEBUG1
101 struct timespec ts;
102#endif
103
104 if (hdl->eof) {
105 DPRINTF("sio_start: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_start: eof\n"
); } while(0)
;
106 return 0;
107 }
108 if (hdl->started) {
109 DPRINTF("sio_start: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_start: already started\n"
); } while(0)
;
110 hdl->eof = 1;
111 return 0;
112 }
113 hdl->cpos = 0;
114 hdl->rused = hdl->wused = 0;
115 if (!sio_getpar(hdl, &hdl->par))
116 return 0;
117#ifdef DEBUG1
118 hdl->pollcnt = 0;
119 clock_gettime(CLOCK_MONOTONIC3, &ts);
120 hdl->start_nsec = 1000000000LL * ts.tv_sec + ts.tv_nsec;
121#endif
122 hdl->rdrop = hdl->wsil = 0;
123 if (!hdl->ops->start(hdl))
124 return 0;
125 hdl->started = 1;
126 return 1;
127}
128
129int
130sio_stop(struct sio_hdl *hdl)
131{
132 if (hdl->eof) {
133 DPRINTF("sio_stop: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_stop: eof\n"
); } while(0)
;
134 return 0;
135 }
136 if (!hdl->started) {
137 DPRINTF("sio_stop: not started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_stop: not started\n"
); } while(0)
;
138 hdl->eof = 1;
139 return 0;
140 }
141 if (!hdl->ops->stop(hdl))
142 return 0;
143#ifdef DEBUG1
144 DPRINTFN(2, "libsndio: polls: %llu, samples = %llu\n",do { if (_sndio_debug >= (2)) fprintf((&__sF[2]), "libsndio: polls: %llu, samples = %llu\n"
, hdl->pollcnt, hdl->cpos); } while(0)
145 hdl->pollcnt, hdl->cpos)do { if (_sndio_debug >= (2)) fprintf((&__sF[2]), "libsndio: polls: %llu, samples = %llu\n"
, hdl->pollcnt, hdl->cpos); } while(0)
;
146#endif
147 hdl->started = 0;
148 return 1;
149}
150
151int
152sio_setpar(struct sio_hdl *hdl, struct sio_par *par)
153{
154 if (hdl->eof) {
155 DPRINTF("sio_setpar: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: eof\n"
); } while(0)
;
156 return 0;
157 }
158 if (par->__magic != SIO_PAR_MAGIC0x83b905a4) {
159 DPRINTF("sio_setpar: uninitialized sio_par structure\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: uninitialized sio_par structure\n"
); } while(0)
;
160 hdl->eof = 1;
161 return 0;
162 }
163 if (hdl->started) {
164 DPRINTF("sio_setpar: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: already started\n"
); } while(0)
;
165 hdl->eof = 1;
166 return 0;
167 }
168 if (par->bufsz != ~0U) {
169 DPRINTF("sio_setpar: setting bufsz is deprecated\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: setting bufsz is deprecated\n"
); } while(0)
;
170 par->appbufsz = par->bufsz;
171 par->bufsz = ~0U;
172 }
173 if (par->rate != ~0U && par->appbufsz == ~0U)
174 par->appbufsz = par->rate * 200 / 1000;
175 return hdl->ops->setpar(hdl, par);
176}
177
178int
179sio_getpar(struct sio_hdl *hdl, struct sio_par *par)
180{
181 if (hdl->eof) {
182 DPRINTF("sio_getpar: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getpar: eof\n"
); } while(0)
;
183 return 0;
184 }
185 if (hdl->started) {
186 DPRINTF("sio_getpar: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getpar: already started\n"
); } while(0)
;
187 hdl->eof = 1;
188 return 0;
189 }
190 if (!hdl->ops->getpar(hdl, par)) {
191 par->__magic = 0;
192 return 0;
193 }
194 par->__magic = 0;
195 return 1;
196}
197
198int
199sio_getcap(struct sio_hdl *hdl, struct sio_cap *cap)
200{
201 if (hdl->eof) {
202 DPRINTF("sio_getcap: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getcap: eof\n"
); } while(0)
;
203 return 0;
204 }
205 if (hdl->started) {
206 DPRINTF("sio_getcap: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getcap: already started\n"
); } while(0)
;
207 hdl->eof = 1;
208 return 0;
209 }
210 return hdl->ops->getcap(hdl, cap);
211}
212
213static int
214sio_psleep(struct sio_hdl *hdl, int event)
215{
216 struct pollfd pfd[SIO_MAXNFDS16];
217 int revents;
218 int nfds;
219
220 nfds = sio_nfds(hdl);
221 if (nfds > SIO_MAXNFDS16) {
23
Assuming 'nfds' is <= SIO_MAXNFDS
24
Taking false branch
222 DPRINTF("sio_psleep: %d: too many descriptors\n", nfds)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_psleep: %d: too many descriptors\n"
, nfds); } while(0)
;
223 hdl->eof = 1;
224 return 0;
225 }
226 for (;;) {
25
Loop condition is true. Entering loop body
227 nfds = sio_pollfd(hdl, pfd, event);
228 while (poll(pfd, nfds, -1) == -1) {
26
Assuming the condition is false
27
Loop condition is false. Execution continues on line 235
229 if (errno(*__errno()) == EINTR4)
230 continue;
231 DPERROR("sio_psleep: poll")do { if (_sndio_debug > 0) perror("sio_psleep: poll"); } while
(0)
;
232 hdl->eof = 1;
233 return 0;
234 }
235 revents = sio_revents(hdl, pfd);
28
Calling 'sio_revents'
236 if (revents & POLLHUP0x0010) {
237 DPRINTF("sio_psleep: hang-up\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_psleep: hang-up\n"
); } while(0)
;
238 return 0;
239 }
240 if (revents & event)
241 break;
242 }
243 return 1;
244}
245
246static int
247sio_rdrop(struct sio_hdl *hdl)
248{
249#define DROP_NMAX0x1000 0x1000
250 static char dummy[DROP_NMAX0x1000];
251 ssize_t n, todo;
252
253 while (hdl->rdrop > 0) {
254 todo = hdl->rdrop;
255 if (todo > DROP_NMAX0x1000)
256 todo = DROP_NMAX0x1000;
257 n = hdl->ops->read(hdl, dummy, todo);
258 if (n == 0)
259 return 0;
260 hdl->rdrop -= n;
261 DPRINTF("sio_rdrop: dropped %zu bytes\n", n)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_rdrop: dropped %zu bytes\n"
, n); } while(0)
;
262 }
263 return 1;
264}
265
266static int
267sio_wsil(struct sio_hdl *hdl)
268{
269#define ZERO_NMAX0x1000 0x1000
270 static char zero[ZERO_NMAX0x1000];
271 ssize_t n, todo;
272
273 while (hdl->wsil > 0) {
9
Assuming field 'wsil' is <= 0
10
Loop condition is false. Execution continues on line 283
274 todo = hdl->wsil;
275 if (todo > ZERO_NMAX0x1000)
276 todo = ZERO_NMAX0x1000;
277 n = hdl->ops->write(hdl, zero, todo);
278 if (n == 0)
279 return 0;
280 hdl->wsil -= n;
281 DPRINTF("sio_wsil: inserted %zu bytes\n", n)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_wsil: inserted %zu bytes\n"
, n); } while(0)
;
282 }
283 return 1;
11
Returning without writing to 'hdl->eof', which participates in a condition later
12
Returning without writing to 'hdl->started', which participates in a condition later
284}
285
286size_t
287sio_read(struct sio_hdl *hdl, void *buf, size_t len)
288{
289 unsigned int n;
290 char *data = buf;
291 size_t todo = len, maxread;
292
293 if (hdl->eof) {
294 DPRINTF("sio_read: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_read: eof\n"
); } while(0)
;
295 return 0;
296 }
297 if (!hdl->started || !(hdl->mode & SIO_REC2)) {
298 DPRINTF("sio_read: recording not started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_read: recording not started\n"
); } while(0)
;
299 hdl->eof = 1;
300 return 0;
301 }
302 while (todo > 0) {
303 if (!sio_rdrop(hdl))
304 return 0;
305 maxread = hdl->rused;
306 if (maxread > todo)
307 maxread = todo;
308 n = maxread > 0 ? hdl->ops->read(hdl, data, maxread) : 0;
309 if (n == 0) {
310 if (hdl->nbio || hdl->eof || todo < len)
311 break;
312 if (!sio_psleep(hdl, POLLIN0x0001))
313 break;
314 continue;
315 }
316 data += n;
317 todo -= n;
318 hdl->rused -= n;
319 }
320 return len - todo;
321}
322
323size_t
324sio_write(struct sio_hdl *hdl, const void *buf, size_t len)
325{
326 unsigned int n;
327 const unsigned char *data = buf;
328 size_t todo = len, maxwrite;
329
330 if (hdl->eof) {
1
Assuming field 'eof' is 0
2
Taking false branch
331 DPRINTF("sio_write: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_write: eof\n"
); } while(0)
;
332 return 0;
333 }
334 if (!hdl->started || !(hdl->mode & SIO_PLAY1)) {
3
Assuming field 'started' is not equal to 0
4
Assuming the condition is false
5
Taking false branch
335 DPRINTF("sio_write: playback not started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_write: playback not started\n"
); } while(0)
;
336 hdl->eof = 1;
337 return 0;
338 }
339 while (todo > 0) {
6
Assuming 'todo' is > 0
7
Loop condition is true. Entering loop body
340 if (!sio_wsil(hdl))
8
Calling 'sio_wsil'
13
Returning from 'sio_wsil'
14
Taking false branch
341 return 0;
342 maxwrite = hdl->par.bufsz * hdl->par.pchan * hdl->par.bps -
343 hdl->wused;
344 if (maxwrite > todo)
15
Assuming 'maxwrite' is <= 'todo'
16
Taking false branch
345 maxwrite = todo;
346 n = maxwrite > 0 ? hdl->ops->write(hdl, data, maxwrite) : 0;
17
Assuming 'maxwrite' is <= 0
18
'?' condition is false
347 if (n
18.1
'n' is equal to 0
== 0) {
19
Taking true branch
348 if (hdl->nbio || hdl->eof
20.1
Field 'eof' is 0
)
20
Assuming field 'nbio' is 0
21
Taking false branch
349 break;
350 if (!sio_psleep(hdl, POLLOUT0x0004))
22
Calling 'sio_psleep'
351 break;
352 continue;
353 }
354 data += n;
355 todo -= n;
356 hdl->wused += n;
357 }
358 return len - todo;
359}
360
361int
362sio_nfds(struct sio_hdl *hdl)
363{
364 return hdl->ops->nfds(hdl);
365}
366
367int
368sio_pollfd(struct sio_hdl *hdl, struct pollfd *pfd, int events)
369{
370 if (hdl->eof)
371 return 0;
372 if (!hdl->started)
373 events = 0;
374 return hdl->ops->pollfd(hdl, pfd, events);
375}
376
377int
378sio_revents(struct sio_hdl *hdl, struct pollfd *pfd)
379{
380 int revents;
381#ifdef DEBUG1
382 struct timespec ts0, ts1;
383
384 if (_sndio_debug >= 4)
29
Assuming '_sndio_debug' is < 4
30
Taking false branch
385 clock_gettime(CLOCK_MONOTONIC3, &ts0);
386#endif
387 if (hdl->eof)
31
Assuming field 'eof' is 0
32
Taking false branch
388 return POLLHUP0x0010;
389#ifdef DEBUG1
390 hdl->pollcnt++;
391#endif
392 revents = hdl->ops->revents(hdl, pfd);
393 if (!hdl->started)
33
Assuming field 'started' is not equal to 0
34
Taking false branch
394 return revents & POLLHUP0x0010;
395#ifdef DEBUG1
396 if (_sndio_debug >= 4) {
35
Assuming '_sndio_debug' is >= 4
36
Taking true branch
397 clock_gettime(CLOCK_MONOTONIC3, &ts1);
398 DPRINTF("%09lld: sio_revents: revents = 0x%x, took %lldns\n",do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n"
, 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec
, revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec
- ts0.tv_nsec); } while(0)
37
Taking true branch
38
The right operand of '*' is a garbage value
399 1000000000LL * ts0.tv_sec +do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n"
, 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec
, revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec
- ts0.tv_nsec); } while(0)
400 ts0.tv_nsec - hdl->start_nsec,do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n"
, 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec
, revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec
- ts0.tv_nsec); } while(0)
401 revents,do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n"
, 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec
, revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec
- ts0.tv_nsec); } while(0)
402 1000000000LL * (ts1.tv_sec - ts0.tv_sec) +do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n"
, 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec
, revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec
- ts0.tv_nsec); } while(0)
403 ts1.tv_nsec - ts0.tv_nsec)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n"
, 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec
, revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec
- ts0.tv_nsec); } while(0)
;
404 }
405#endif
406 if ((hdl->mode & SIO_PLAY1) && !sio_wsil(hdl))
407 revents &= ~POLLOUT0x0004;
408 if ((hdl->mode & SIO_REC2) && !sio_rdrop(hdl))
409 revents &= ~POLLIN0x0001;
410 return revents;
411}
412
413int
414sio_eof(struct sio_hdl *hdl)
415{
416 return hdl->eof;
417}
418
419void
420sio_onmove(struct sio_hdl *hdl, void (*cb)(void *, int), void *addr)
421{
422 if (hdl->started) {
423 DPRINTF("sio_onmove: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_onmove: already started\n"
); } while(0)
;
424 hdl->eof = 1;
425 return;
426 }
427 hdl->move_cb = cb;
428 hdl->move_addr = addr;
429}
430
431#ifdef DEBUG1
432void
433_sio_printpos(struct sio_hdl *hdl)
434{
435 struct timespec ts;
436 long long rpos, rdiff;
437 long long cpos, cdiff;
438 long long wpos, wdiff;
439 unsigned rbpf, wbpf, rround, wround;
440
441 clock_gettime(CLOCK_MONOTONIC3, &ts);
442 rbpf = (hdl->mode & SIO_REC2) ? hdl->par.bps * hdl->par.rchan : 1;
443 wbpf = (hdl->mode & SIO_PLAY1) ? hdl->par.bps * hdl->par.pchan : 1;
444 rround = hdl->par.round * rbpf;
445 wround = hdl->par.round * wbpf;
446
447 rpos = (hdl->mode & SIO_REC2) ?
448 hdl->cpos * rbpf - hdl->rused : 0;
449 wpos = (hdl->mode & SIO_PLAY1) ?
450 hdl->cpos * wbpf + hdl->wused : 0;
451
452 cdiff = hdl->cpos % hdl->par.round;
453 cpos = hdl->cpos / hdl->par.round;
454 if (cdiff > hdl->par.round / 2) {
455 cpos++;
456 cdiff = cdiff - hdl->par.round;
457 }
458 rdiff = rpos % rround;
459 rpos = rpos / rround;
460 if (rdiff > rround / 2) {
461 rpos++;
462 rdiff = rdiff - rround;
463 }
464 wdiff = wpos % wround;
465 wpos = wpos / wround;
466 if (wdiff > wround / 2) {
467 wpos++;
468 wdiff = wdiff - wround;
469 }
470 DPRINTF("%011lld: "do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: "
"clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL
* ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos
, wdiff, rpos, rdiff); } while(0)
471 "clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n",do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: "
"clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL
* ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos
, wdiff, rpos, rdiff); } while(0)
472 1000000000LL * ts.tv_sec + ts.tv_nsec - hdl->start_nsec,do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: "
"clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL
* ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos
, wdiff, rpos, rdiff); } while(0)
473 cpos, cdiff, wpos, wdiff, rpos, rdiff)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: "
"clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL
* ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos
, wdiff, rpos, rdiff); } while(0)
;
474}
475#endif
476
477void
478_sio_onmove_cb(struct sio_hdl *hdl, int delta)
479{
480 hdl->cpos += delta;
481 if (hdl->mode & SIO_REC2)
482 hdl->rused += delta * (hdl->par.bps * hdl->par.rchan);
483 if (hdl->mode & SIO_PLAY1)
484 hdl->wused -= delta * (hdl->par.bps * hdl->par.pchan);
485#ifdef DEBUG1
486 if (_sndio_debug >= 3)
487 _sio_printpos(hdl);
488 if ((hdl->mode & SIO_PLAY1) && hdl->wused < 0) {
489 DPRINTFN(1, "sndio: h/w failure: negative buffer usage\n")do { if (_sndio_debug >= (1)) fprintf((&__sF[2]), "sndio: h/w failure: negative buffer usage\n"
); } while(0)
;
490 hdl->eof = 1;
491 return;
492 }
493#endif
494 if (hdl->move_cb)
495 hdl->move_cb(hdl->move_addr, delta);
496}
497
498int
499sio_setvol(struct sio_hdl *hdl, unsigned int ctl)
500{
501 if (hdl->eof)
502 return 0;
503 if (!hdl->ops->setvol)
504 return 1;
505 if (!hdl->ops->setvol(hdl, ctl))
506 return 0;
507 hdl->ops->getvol(hdl);
508 return 1;
509}
510
511int
512sio_onvol(struct sio_hdl *hdl, void (*cb)(void *, unsigned int), void *addr)
513{
514 if (hdl->started) {
515 DPRINTF("sio_onvol: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_onvol: already started\n"
); } while(0)
;
516 hdl->eof = 1;
517 return 0;
518 }
519 if (!hdl->ops->setvol)
520 return 0;
521 hdl->vol_cb = cb;
522 hdl->vol_addr = addr;
523 hdl->ops->getvol(hdl);
524 return 1;
525}
526
527void
528_sio_onvol_cb(struct sio_hdl *hdl, unsigned int ctl)
529{
530 if (hdl->vol_cb)
531 hdl->vol_cb(hdl->vol_addr, ctl);
532}