oss: use audio_pcm_hw_clip_out
[sdk/emulator/qemu.git] / audio / ossaudio.c
1 /*
2  * QEMU OSS audio driver
3  *
4  * Copyright (c) 2003-2005 Vassili Karpov (malc)
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include <stdlib.h>
25 #include <sys/mman.h>
26 #include <sys/types.h>
27 #include <sys/ioctl.h>
28 #ifdef __OpenBSD__
29 #include <soundcard.h>
30 #else
31 #include <sys/soundcard.h>
32 #endif
33 #include "qemu-common.h"
34 #include "host-utils.h"
35 #include "qemu-char.h"
36 #include "audio.h"
37
38 #define AUDIO_CAP "oss"
39 #include "audio_int.h"
40
41 typedef struct OSSVoiceOut {
42     HWVoiceOut hw;
43     void *pcm_buf;
44     int fd;
45     int wpos;
46     int nfrags;
47     int fragsize;
48     int mmapped;
49     int pending;
50 } OSSVoiceOut;
51
52 typedef struct OSSVoiceIn {
53     HWVoiceIn hw;
54     void *pcm_buf;
55     int fd;
56     int nfrags;
57     int fragsize;
58 } OSSVoiceIn;
59
60 static struct {
61     int try_mmap;
62     int nfrags;
63     int fragsize;
64     const char *devpath_out;
65     const char *devpath_in;
66     int debug;
67     int exclusive;
68     int policy;
69 } conf = {
70     .try_mmap = 0,
71     .nfrags = 4,
72     .fragsize = 4096,
73     .devpath_out = "/dev/dsp",
74     .devpath_in = "/dev/dsp",
75     .debug = 0,
76     .exclusive = 0,
77     .policy = 5
78 };
79
80 struct oss_params {
81     int freq;
82     audfmt_e fmt;
83     int nchannels;
84     int nfrags;
85     int fragsize;
86 };
87
88 static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
89 {
90     va_list ap;
91
92     va_start (ap, fmt);
93     AUD_vlog (AUDIO_CAP, fmt, ap);
94     va_end (ap);
95
96     AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
97 }
98
99 static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
100     int err,
101     const char *typ,
102     const char *fmt,
103     ...
104     )
105 {
106     va_list ap;
107
108     AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
109
110     va_start (ap, fmt);
111     AUD_vlog (AUDIO_CAP, fmt, ap);
112     va_end (ap);
113
114     AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
115 }
116
117 static void oss_anal_close (int *fdp)
118 {
119     int err;
120
121     qemu_set_fd_handler (*fdp, NULL, NULL, NULL);
122     err = close (*fdp);
123     if (err) {
124         oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp);
125     }
126     *fdp = -1;
127 }
128
129 static void oss_helper_poll_out (void *opaque)
130 {
131     (void) opaque;
132     audio_run ("oss_poll_out");
133 }
134
135 static void oss_helper_poll_in (void *opaque)
136 {
137     (void) opaque;
138     audio_run ("oss_poll_in");
139 }
140
141 static int oss_poll_out (HWVoiceOut *hw)
142 {
143     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
144
145     return qemu_set_fd_handler (oss->fd, NULL, oss_helper_poll_out, NULL);
146 }
147
148 static int oss_poll_in (HWVoiceIn *hw)
149 {
150     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
151
152     return qemu_set_fd_handler (oss->fd, oss_helper_poll_in, NULL, NULL);
153 }
154
155 static int oss_write (SWVoiceOut *sw, void *buf, int len)
156 {
157     return audio_pcm_sw_write (sw, buf, len);
158 }
159
160 static int aud_to_ossfmt (audfmt_e fmt)
161 {
162     switch (fmt) {
163     case AUD_FMT_S8:
164         return AFMT_S8;
165
166     case AUD_FMT_U8:
167         return AFMT_U8;
168
169     case AUD_FMT_S16:
170         return AFMT_S16_LE;
171
172     case AUD_FMT_U16:
173         return AFMT_U16_LE;
174
175     default:
176         dolog ("Internal logic error: Bad audio format %d\n", fmt);
177 #ifdef DEBUG_AUDIO
178         abort ();
179 #endif
180         return AFMT_U8;
181     }
182 }
183
184 static int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness)
185 {
186     switch (ossfmt) {
187     case AFMT_S8:
188         *endianness = 0;
189         *fmt = AUD_FMT_S8;
190         break;
191
192     case AFMT_U8:
193         *endianness = 0;
194         *fmt = AUD_FMT_U8;
195         break;
196
197     case AFMT_S16_LE:
198         *endianness = 0;
199         *fmt = AUD_FMT_S16;
200         break;
201
202     case AFMT_U16_LE:
203         *endianness = 0;
204         *fmt = AUD_FMT_U16;
205         break;
206
207     case AFMT_S16_BE:
208         *endianness = 1;
209         *fmt = AUD_FMT_S16;
210         break;
211
212     case AFMT_U16_BE:
213         *endianness = 1;
214         *fmt = AUD_FMT_U16;
215         break;
216
217     default:
218         dolog ("Unrecognized audio format %d\n", ossfmt);
219         return -1;
220     }
221
222     return 0;
223 }
224
225 #if defined DEBUG_MISMATCHES || defined DEBUG
226 static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
227 {
228     dolog ("parameter | requested value | obtained value\n");
229     dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
230     dolog ("channels  |      %10d |     %10d\n",
231            req->nchannels, obt->nchannels);
232     dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
233     dolog ("nfrags    |      %10d |     %10d\n", req->nfrags, obt->nfrags);
234     dolog ("fragsize  |      %10d |     %10d\n",
235            req->fragsize, obt->fragsize);
236 }
237 #endif
238
239 static int oss_open (int in, struct oss_params *req,
240                      struct oss_params *obt, int *pfd)
241 {
242     int fd;
243     int version;
244     int oflags = conf.exclusive ? O_EXCL : 0;
245     audio_buf_info abinfo;
246     int fmt, freq, nchannels;
247     const char *dspname = in ? conf.devpath_in : conf.devpath_out;
248     const char *typ = in ? "ADC" : "DAC";
249
250     /* Kludge needed to have working mmap on Linux */
251     oflags |= conf.try_mmap ? O_RDWR : (in ? O_RDONLY : O_WRONLY);
252
253     fd = open (dspname, oflags | O_NONBLOCK);
254     if (-1 == fd) {
255         oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname);
256         return -1;
257     }
258
259     freq = req->freq;
260     nchannels = req->nchannels;
261     fmt = req->fmt;
262
263     if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
264         oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt);
265         goto err;
266     }
267
268     if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
269         oss_logerr2 (errno, typ, "Failed to set number of channels %d\n",
270                      req->nchannels);
271         goto err;
272     }
273
274     if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
275         oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq);
276         goto err;
277     }
278
279     if (ioctl (fd, SNDCTL_DSP_NONBLOCK, NULL)) {
280         oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
281         goto err;
282     }
283
284     if (ioctl (fd, OSS_GETVERSION, &version)) {
285         oss_logerr2 (errno, typ, "Failed to get OSS version\n");
286         version = 0;
287     }
288
289     if (conf.debug) {
290         dolog ("OSS version = %#x\n", version);
291     }
292
293 #ifdef SNDCTL_DSP_POLICY
294     if (conf.policy >= 0 && version >= 0x040000) {
295         int policy = conf.policy;
296         if (ioctl (fd, SNDCTL_DSP_POLICY, &policy)) {
297             oss_logerr2 (errno, typ, "Failed to set timing policy to %d\n",
298                          conf.policy);
299             goto err;
300         }
301     }
302     else
303 #endif
304     {
305         int mmmmssss = (req->nfrags << 16) | ctz32 (req->fragsize);
306         if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
307             oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
308                          req->nfrags, req->fragsize);
309             goto err;
310         }
311     }
312
313     if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) {
314         oss_logerr2 (errno, typ, "Failed to get buffer length\n");
315         goto err;
316     }
317
318     if (!abinfo.fragstotal || !abinfo.fragsize) {
319         AUD_log (AUDIO_CAP, "Returned bogus buffer information(%d, %d) for %s\n",
320                  abinfo.fragstotal, abinfo.fragsize, typ);
321         goto err;
322     }
323
324     obt->fmt = fmt;
325     obt->nchannels = nchannels;
326     obt->freq = freq;
327     obt->nfrags = abinfo.fragstotal;
328     obt->fragsize = abinfo.fragsize;
329     *pfd = fd;
330
331 #ifdef DEBUG_MISMATCHES
332     if ((req->fmt != obt->fmt) ||
333         (req->nchannels != obt->nchannels) ||
334         (req->freq != obt->freq) ||
335         (req->fragsize != obt->fragsize) ||
336         (req->nfrags != obt->nfrags)) {
337         dolog ("Audio parameters mismatch\n");
338         oss_dump_info (req, obt);
339     }
340 #endif
341
342 #ifdef DEBUG
343     oss_dump_info (req, obt);
344 #endif
345     return 0;
346
347  err:
348     oss_anal_close (&fd);
349     return -1;
350 }
351
352 static void oss_write_pending (OSSVoiceOut *oss)
353 {
354     HWVoiceOut *hw = &oss->hw;
355
356     if (oss->mmapped) {
357         return;
358     }
359
360     while (oss->pending) {
361         int samples_written;
362         ssize_t bytes_written;
363         int samples_till_end = hw->samples - oss->wpos;
364         int samples_to_write = audio_MIN (oss->pending, samples_till_end);
365         int bytes_to_write = samples_to_write << hw->info.shift;
366         void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift);
367
368         bytes_written = write (oss->fd, pcm, bytes_to_write);
369         if (bytes_written < 0) {
370             if (errno != EAGAIN) {
371                 oss_logerr (errno, "failed to write %d bytes\n",
372                             bytes_to_write);
373             }
374             break;
375         }
376
377         if (bytes_written & hw->info.align) {
378             dolog ("misaligned write asked for %d, but got %zd\n",
379                    bytes_to_write, bytes_written);
380             return;
381         }
382
383         samples_written = bytes_written >> hw->info.shift;
384         oss->pending -= samples_written;
385         oss->wpos = (oss->wpos + samples_written) % hw->samples;
386         if (bytes_written - bytes_to_write) {
387             break;
388         }
389     }
390 }
391
392 static int oss_run_out (HWVoiceOut *hw)
393 {
394     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
395     int err, live, decr;
396     struct audio_buf_info abinfo;
397     struct count_info cntinfo;
398     int bufsize;
399
400     live = audio_pcm_hw_get_live_out (hw);
401     if (!live) {
402         return 0;
403     }
404
405     bufsize = hw->samples << hw->info.shift;
406
407     if (oss->mmapped) {
408         int bytes, pos;
409
410         err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
411         if (err < 0) {
412             oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
413             return 0;
414         }
415
416         pos = hw->rpos << hw->info.shift;
417         bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize);
418         decr = audio_MIN (bytes >> hw->info.shift, live);
419     }
420     else {
421         err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
422         if (err < 0) {
423             oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
424             return 0;
425         }
426
427         if (abinfo.bytes > bufsize) {
428             if (conf.debug) {
429                 dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
430                        "please report your OS/audio hw to malc@pulsesoft.com\n",
431                        abinfo.bytes, bufsize);
432             }
433             abinfo.bytes = bufsize;
434         }
435
436         if (abinfo.bytes < 0) {
437             if (conf.debug) {
438                 dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
439                        abinfo.bytes, bufsize);
440             }
441             return 0;
442         }
443
444         decr = audio_MIN (abinfo.bytes >> hw->info.shift, live);
445         if (!decr) {
446             return 0;
447         }
448     }
449
450     decr = audio_pcm_hw_clip_out (hw, oss->pcm_buf, decr, oss->pending);
451     oss->pending += decr;
452     oss_write_pending (oss);
453
454     return decr;
455 }
456
457 static void oss_fini_out (HWVoiceOut *hw)
458 {
459     int err;
460     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
461
462     ldebug ("oss_fini\n");
463     oss_anal_close (&oss->fd);
464
465     if (oss->pcm_buf) {
466         if (oss->mmapped) {
467             err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
468             if (err) {
469                 oss_logerr (errno, "Failed to unmap buffer %p, size %d\n",
470                             oss->pcm_buf, hw->samples << hw->info.shift);
471             }
472         }
473         else {
474             qemu_free (oss->pcm_buf);
475         }
476         oss->pcm_buf = NULL;
477     }
478 }
479
480 static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
481 {
482     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
483     struct oss_params req, obt;
484     int endianness;
485     int err;
486     int fd;
487     audfmt_e effective_fmt;
488     struct audsettings obt_as;
489
490     oss->fd = -1;
491
492     req.fmt = aud_to_ossfmt (as->fmt);
493     req.freq = as->freq;
494     req.nchannels = as->nchannels;
495     req.fragsize = conf.fragsize;
496     req.nfrags = conf.nfrags;
497
498     if (oss_open (0, &req, &obt, &fd)) {
499         return -1;
500     }
501
502     err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
503     if (err) {
504         oss_anal_close (&fd);
505         return -1;
506     }
507
508     obt_as.freq = obt.freq;
509     obt_as.nchannels = obt.nchannels;
510     obt_as.fmt = effective_fmt;
511     obt_as.endianness = endianness;
512
513     audio_pcm_init_info (&hw->info, &obt_as);
514     oss->nfrags = obt.nfrags;
515     oss->fragsize = obt.fragsize;
516
517     if (obt.nfrags * obt.fragsize & hw->info.align) {
518         dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n",
519                obt.nfrags * obt.fragsize, hw->info.align + 1);
520     }
521
522     hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
523
524     oss->mmapped = 0;
525     if (conf.try_mmap) {
526         oss->pcm_buf = mmap (
527             NULL,
528             hw->samples << hw->info.shift,
529             PROT_READ | PROT_WRITE,
530             MAP_SHARED,
531             fd,
532             0
533             );
534         if (oss->pcm_buf == MAP_FAILED) {
535             oss_logerr (errno, "Failed to map %d bytes of DAC\n",
536                         hw->samples << hw->info.shift);
537         }
538         else {
539             int err;
540             int trig = 0;
541             if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
542                 oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
543             }
544             else {
545                 trig = PCM_ENABLE_OUTPUT;
546                 if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
547                     oss_logerr (
548                         errno,
549                         "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
550                         );
551                 }
552                 else {
553                     oss->mmapped = 1;
554                 }
555             }
556
557             if (!oss->mmapped) {
558                 err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
559                 if (err) {
560                     oss_logerr (errno, "Failed to unmap buffer %p size %d\n",
561                                 oss->pcm_buf, hw->samples << hw->info.shift);
562                 }
563             }
564         }
565     }
566
567     if (!oss->mmapped) {
568         oss->pcm_buf = audio_calloc (
569             AUDIO_FUNC,
570             hw->samples,
571             1 << hw->info.shift
572             );
573         if (!oss->pcm_buf) {
574             dolog (
575                 "Could not allocate DAC buffer (%d samples, each %d bytes)\n",
576                 hw->samples,
577                 1 << hw->info.shift
578                 );
579             oss_anal_close (&fd);
580             return -1;
581         }
582     }
583
584     oss->fd = fd;
585     return 0;
586 }
587
588 static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
589 {
590     int trig;
591     va_list ap;
592     int poll_mode;
593     OSSVoiceOut *oss = (OSSVoiceOut *) hw;
594
595     va_start (ap, cmd);
596     poll_mode = va_arg (ap, int);
597     va_end (ap);
598
599     switch (cmd) {
600     case VOICE_ENABLE:
601         ldebug ("enabling voice\n");
602         if (poll_mode && oss_poll_out (hw)) {
603             poll_mode = 0;
604         }
605         hw->poll_mode = poll_mode;
606
607         if (!oss->mmapped) {
608             return 0;
609         }
610
611         audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples);
612         trig = PCM_ENABLE_OUTPUT;
613         if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
614             oss_logerr (
615                 errno,
616                 "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
617                 );
618             return -1;
619         }
620         break;
621
622     case VOICE_DISABLE:
623         if (hw->poll_mode) {
624             qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
625             hw->poll_mode = 0;
626         }
627
628         if (!oss->mmapped) {
629             return 0;
630         }
631
632         ldebug ("disabling voice\n");
633         trig = 0;
634         if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
635             oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
636             return -1;
637         }
638         break;
639     }
640     return 0;
641 }
642
643 static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
644 {
645     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
646     struct oss_params req, obt;
647     int endianness;
648     int err;
649     int fd;
650     audfmt_e effective_fmt;
651     struct audsettings obt_as;
652
653     oss->fd = -1;
654
655     req.fmt = aud_to_ossfmt (as->fmt);
656     req.freq = as->freq;
657     req.nchannels = as->nchannels;
658     req.fragsize = conf.fragsize;
659     req.nfrags = conf.nfrags;
660     if (oss_open (1, &req, &obt, &fd)) {
661         return -1;
662     }
663
664     err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
665     if (err) {
666         oss_anal_close (&fd);
667         return -1;
668     }
669
670     obt_as.freq = obt.freq;
671     obt_as.nchannels = obt.nchannels;
672     obt_as.fmt = effective_fmt;
673     obt_as.endianness = endianness;
674
675     audio_pcm_init_info (&hw->info, &obt_as);
676     oss->nfrags = obt.nfrags;
677     oss->fragsize = obt.fragsize;
678
679     if (obt.nfrags * obt.fragsize & hw->info.align) {
680         dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n",
681                obt.nfrags * obt.fragsize, hw->info.align + 1);
682     }
683
684     hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
685     oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
686     if (!oss->pcm_buf) {
687         dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
688                hw->samples, 1 << hw->info.shift);
689         oss_anal_close (&fd);
690         return -1;
691     }
692
693     oss->fd = fd;
694     return 0;
695 }
696
697 static void oss_fini_in (HWVoiceIn *hw)
698 {
699     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
700
701     oss_anal_close (&oss->fd);
702
703     if (oss->pcm_buf) {
704         qemu_free (oss->pcm_buf);
705         oss->pcm_buf = NULL;
706     }
707 }
708
709 static int oss_run_in (HWVoiceIn *hw)
710 {
711     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
712     int hwshift = hw->info.shift;
713     int i;
714     int live = audio_pcm_hw_get_live_in (hw);
715     int dead = hw->samples - live;
716     size_t read_samples = 0;
717     struct {
718         int add;
719         int len;
720     } bufs[2] = {
721         { .add = hw->wpos, .len = 0 },
722         { .add = 0,        .len = 0 }
723     };
724
725     if (!dead) {
726         return 0;
727     }
728
729     if (hw->wpos + dead > hw->samples) {
730         bufs[0].len = (hw->samples - hw->wpos) << hwshift;
731         bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;
732     }
733     else {
734         bufs[0].len = dead << hwshift;
735     }
736
737     for (i = 0; i < 2; ++i) {
738         ssize_t nread;
739
740         if (bufs[i].len) {
741             void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);
742             nread = read (oss->fd, p, bufs[i].len);
743
744             if (nread > 0) {
745                 if (nread & hw->info.align) {
746                     dolog ("warning: Misaligned read %zd (requested %d), "
747                            "alignment %d\n", nread, bufs[i].add << hwshift,
748                            hw->info.align + 1);
749                 }
750                 read_samples += nread >> hwshift;
751                 hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
752                           &nominal_volume);
753             }
754
755             if (bufs[i].len - nread) {
756                 if (nread == -1) {
757                     switch (errno) {
758                     case EINTR:
759                     case EAGAIN:
760                         break;
761                     default:
762                         oss_logerr (
763                             errno,
764                             "Failed to read %d bytes of audio (to %p)\n",
765                             bufs[i].len, p
766                             );
767                         break;
768                     }
769                 }
770                 break;
771             }
772         }
773     }
774
775     hw->wpos = (hw->wpos + read_samples) % hw->samples;
776     return read_samples;
777 }
778
779 static int oss_read (SWVoiceIn *sw, void *buf, int size)
780 {
781     return audio_pcm_sw_read (sw, buf, size);
782 }
783
784 static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
785 {
786     va_list ap;
787     int poll_mode;
788     OSSVoiceIn *oss = (OSSVoiceIn *) hw;
789
790     va_start (ap, cmd);
791     poll_mode = va_arg (ap, int);
792     va_end (ap);
793
794     switch (cmd) {
795     case VOICE_ENABLE:
796         if (poll_mode && oss_poll_in (hw)) {
797             poll_mode = 0;
798         }
799         hw->poll_mode = poll_mode;
800         break;
801
802     case VOICE_DISABLE:
803         if (hw->poll_mode) {
804             hw->poll_mode = 0;
805             qemu_set_fd_handler (oss->fd, NULL, NULL, NULL);
806         }
807         break;
808     }
809     return 0;
810 }
811
812 static void *oss_audio_init (void)
813 {
814     return &conf;
815 }
816
817 static void oss_audio_fini (void *opaque)
818 {
819     (void) opaque;
820 }
821
822 static struct audio_option oss_options[] = {
823     {
824         .name  = "FRAGSIZE",
825         .tag   = AUD_OPT_INT,
826         .valp  = &conf.fragsize,
827         .descr = "Fragment size in bytes"
828     },
829     {
830         .name  = "NFRAGS",
831         .tag   = AUD_OPT_INT,
832         .valp  = &conf.nfrags,
833         .descr = "Number of fragments"
834     },
835     {
836         .name  = "MMAP",
837         .tag   = AUD_OPT_BOOL,
838         .valp  = &conf.try_mmap,
839         .descr = "Try using memory mapped access"
840     },
841     {
842         .name  = "DAC_DEV",
843         .tag   = AUD_OPT_STR,
844         .valp  = &conf.devpath_out,
845         .descr = "Path to DAC device"
846     },
847     {
848         .name  = "ADC_DEV",
849         .tag   = AUD_OPT_STR,
850         .valp  = &conf.devpath_in,
851         .descr = "Path to ADC device"
852     },
853     {
854         .name  = "EXCLUSIVE",
855         .tag   = AUD_OPT_BOOL,
856         .valp  = &conf.exclusive,
857         .descr = "Open device in exclusive mode (vmix wont work)"
858     },
859 #ifdef SNDCTL_DSP_POLICY
860     {
861         .name  = "POLICY",
862         .tag   = AUD_OPT_INT,
863         .valp  = &conf.policy,
864         .descr = "Set the timing policy of the device, -1 to use fragment mode",
865     },
866 #endif
867     {
868         .name  = "DEBUG",
869         .tag   = AUD_OPT_BOOL,
870         .valp  = &conf.debug,
871         .descr = "Turn on some debugging messages"
872     },
873     { /* End of list */ }
874 };
875
876 static struct audio_pcm_ops oss_pcm_ops = {
877     .init_out = oss_init_out,
878     .fini_out = oss_fini_out,
879     .run_out  = oss_run_out,
880     .write    = oss_write,
881     .ctl_out  = oss_ctl_out,
882
883     .init_in  = oss_init_in,
884     .fini_in  = oss_fini_in,
885     .run_in   = oss_run_in,
886     .read     = oss_read,
887     .ctl_in   = oss_ctl_in
888 };
889
890 struct audio_driver oss_audio_driver = {
891     .name           = "oss",
892     .descr          = "OSS http://www.opensound.com",
893     .options        = oss_options,
894     .init           = oss_audio_init,
895     .fini           = oss_audio_fini,
896     .pcm_ops        = &oss_pcm_ops,
897     .can_be_default = 1,
898     .max_voices_out = INT_MAX,
899     .max_voices_in  = INT_MAX,
900     .voice_size_out = sizeof (OSSVoiceOut),
901     .voice_size_in  = sizeof (OSSVoiceIn)
902 };