1 /* 2 * SPDX-License-Identifier: ISC 3 * 4 * Copyright (c) 2019 Alexandre Ratchov <alex@caoua.org> 5 */ 6 7 /* 8 * TODO : 9 * 10 * Use a single device and open it in full-duplex rather than 11 * opening it twice (once for playback once for recording). 12 * 13 * This is the only way to ensure that playback doesn't drift with respect 14 * to recording, which is what guest systems expect. 15 */ 16 17 #include <poll.h> 18 #include <sndio.h> 19 #include "qemu/osdep.h" 20 #include "qemu/main-loop.h" 21 #include "audio.h" 22 #include "trace.h" 23 24 #define AUDIO_CAP "sndio" 25 #include "audio_int.h" 26 27 /* default latency in microseconds if no option is set */ 28 #define SNDIO_LATENCY_US 50000 29 30 typedef struct SndioVoice { 31 union { 32 HWVoiceOut out; 33 HWVoiceIn in; 34 } hw; 35 struct sio_par par; 36 struct sio_hdl *hdl; 37 struct pollfd *pfds; 38 struct pollindex { 39 struct SndioVoice *self; 40 int index; 41 } *pindexes; 42 unsigned char *buf; 43 size_t buf_size; 44 size_t sndio_pos; 45 size_t qemu_pos; 46 unsigned int mode; 47 unsigned int nfds; 48 bool enabled; 49 } SndioVoice; 50 51 typedef struct SndioConf { 52 const char *devname; 53 unsigned int latency; 54 } SndioConf; 55 56 /* needed for forward reference */ 57 static void sndio_poll_in(void *arg); 58 static void sndio_poll_out(void *arg); 59 60 /* 61 * stop polling descriptors 62 */ 63 static void sndio_poll_clear(SndioVoice *self) 64 { 65 struct pollfd *pfd; 66 int i; 67 68 for (i = 0; i < self->nfds; i++) { 69 pfd = &self->pfds[i]; 70 qemu_set_fd_handler(pfd->fd, NULL, NULL, NULL); 71 } 72 73 self->nfds = 0; 74 } 75 76 /* 77 * write data to the device until it blocks or 78 * all of our buffered data is written 79 */ 80 static void sndio_write(SndioVoice *self) 81 { 82 size_t todo, n; 83 84 todo = self->qemu_pos - self->sndio_pos; 85 86 /* 87 * transfer data to device, until it blocks 88 */ 89 while (todo > 0) { 90 n = sio_write(self->hdl, self->buf + self->sndio_pos, todo); 91 if (n == 0) { 92 break; 93 } 94 self->sndio_pos += n; 95 todo -= n; 96 } 97 98 if (self->sndio_pos == self->buf_size) { 99 /* 100 * we complete the block 101 */ 102 self->sndio_pos = 0; 103 self->qemu_pos = 0; 104 } 105 } 106 107 /* 108 * read data from the device until it blocks or 109 * there no room any longer 110 */ 111 static void sndio_read(SndioVoice *self) 112 { 113 size_t todo, n; 114 115 todo = self->buf_size - self->sndio_pos; 116 117 /* 118 * transfer data from the device, until it blocks 119 */ 120 while (todo > 0) { 121 n = sio_read(self->hdl, self->buf + self->sndio_pos, todo); 122 if (n == 0) { 123 break; 124 } 125 self->sndio_pos += n; 126 todo -= n; 127 } 128 } 129 130 /* 131 * Set handlers for all descriptors libsndio needs to 132 * poll 133 */ 134 static void sndio_poll_wait(SndioVoice *self) 135 { 136 struct pollfd *pfd; 137 int events, i; 138 139 events = 0; 140 if (self->mode == SIO_PLAY) { 141 if (self->sndio_pos < self->qemu_pos) { 142 events |= POLLOUT; 143 } 144 } else { 145 if (self->sndio_pos < self->buf_size) { 146 events |= POLLIN; 147 } 148 } 149 150 /* 151 * fill the given array of descriptors with the events sndio 152 * wants, they are different from our 'event' variable because 153 * sndio may use descriptors internally. 154 */ 155 self->nfds = sio_pollfd(self->hdl, self->pfds, events); 156 157 for (i = 0; i < self->nfds; i++) { 158 pfd = &self->pfds[i]; 159 if (pfd->fd < 0) { 160 continue; 161 } 162 qemu_set_fd_handler(pfd->fd, 163 (pfd->events & POLLIN) ? sndio_poll_in : NULL, 164 (pfd->events & POLLOUT) ? sndio_poll_out : NULL, 165 &self->pindexes[i]); 166 pfd->revents = 0; 167 } 168 } 169 170 /* 171 * call-back called when one of the descriptors 172 * became readable or writable 173 */ 174 static void sndio_poll_event(SndioVoice *self, int index, int event) 175 { 176 int revents; 177 178 /* 179 * ensure we're not called twice this cycle 180 */ 181 sndio_poll_clear(self); 182 183 /* 184 * make self->pfds[] look as we're returning from poll syscal, 185 * this is how sio_revents expects events to be. 186 */ 187 self->pfds[index].revents = event; 188 189 /* 190 * tell sndio to handle events and return whether we can read or 191 * write without blocking. 192 */ 193 revents = sio_revents(self->hdl, self->pfds); 194 if (self->mode == SIO_PLAY) { 195 if (revents & POLLOUT) { 196 sndio_write(self); 197 } 198 199 if (self->qemu_pos < self->buf_size) { 200 audio_run(self->hw.out.s, "sndio_out"); 201 } 202 } else { 203 if (revents & POLLIN) { 204 sndio_read(self); 205 } 206 207 if (self->qemu_pos < self->sndio_pos) { 208 audio_run(self->hw.in.s, "sndio_in"); 209 } 210 } 211 212 /* 213 * audio_run() may have changed state 214 */ 215 if (self->enabled) { 216 sndio_poll_wait(self); 217 } 218 } 219 220 /* 221 * return the upper limit of the amount of free play buffer space 222 */ 223 static size_t sndio_buffer_get_free(HWVoiceOut *hw) 224 { 225 SndioVoice *self = (SndioVoice *) hw; 226 227 return self->buf_size - self->qemu_pos; 228 } 229 230 /* 231 * return a buffer where data to play can be stored, 232 * its size is stored in the location pointed by the size argument. 233 */ 234 static void *sndio_get_buffer_out(HWVoiceOut *hw, size_t *size) 235 { 236 SndioVoice *self = (SndioVoice *) hw; 237 238 *size = self->buf_size - self->qemu_pos; 239 return self->buf + self->qemu_pos; 240 } 241 242 /* 243 * put back to sndio back-end a buffer returned by sndio_get_buffer_out() 244 */ 245 static size_t sndio_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) 246 { 247 SndioVoice *self = (SndioVoice *) hw; 248 249 self->qemu_pos += size; 250 sndio_poll_wait(self); 251 return size; 252 } 253 254 /* 255 * return a buffer from where recorded data is available, 256 * its size is stored in the location pointed by the size argument. 257 * it may not exceed the initial value of "*size". 258 */ 259 static void *sndio_get_buffer_in(HWVoiceIn *hw, size_t *size) 260 { 261 SndioVoice *self = (SndioVoice *) hw; 262 size_t todo, max_todo; 263 264 /* 265 * unlike the get_buffer_out() method, get_buffer_in() 266 * must return a buffer of at most the given size, see audio.c 267 */ 268 max_todo = *size; 269 270 todo = self->sndio_pos - self->qemu_pos; 271 if (todo > max_todo) { 272 todo = max_todo; 273 } 274 275 *size = todo; 276 return self->buf + self->qemu_pos; 277 } 278 279 /* 280 * discard the given amount of recorded data 281 */ 282 static void sndio_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size) 283 { 284 SndioVoice *self = (SndioVoice *) hw; 285 286 self->qemu_pos += size; 287 if (self->qemu_pos == self->buf_size) { 288 self->qemu_pos = 0; 289 self->sndio_pos = 0; 290 } 291 sndio_poll_wait(self); 292 } 293 294 /* 295 * call-back called when one of our descriptors becomes writable 296 */ 297 static void sndio_poll_out(void *arg) 298 { 299 struct pollindex *pindex = (struct pollindex *) arg; 300 301 sndio_poll_event(pindex->self, pindex->index, POLLOUT); 302 } 303 304 /* 305 * call-back called when one of our descriptors becomes readable 306 */ 307 static void sndio_poll_in(void *arg) 308 { 309 struct pollindex *pindex = (struct pollindex *) arg; 310 311 sndio_poll_event(pindex->self, pindex->index, POLLIN); 312 } 313 314 static void sndio_fini(SndioVoice *self) 315 { 316 if (self->hdl) { 317 sio_close(self->hdl); 318 self->hdl = NULL; 319 } 320 321 g_free(self->pfds); 322 g_free(self->pindexes); 323 g_free(self->buf); 324 } 325 326 static int sndio_init(SndioVoice *self, 327 struct audsettings *as, int mode, Audiodev *dev) 328 { 329 AudiodevSndioOptions *opts = &dev->u.sndio; 330 unsigned long long latency; 331 const char *dev_name; 332 struct sio_par req; 333 unsigned int nch; 334 int i, nfds; 335 336 dev_name = opts->has_dev ? opts->dev : SIO_DEVANY; 337 latency = opts->has_latency ? opts->latency : SNDIO_LATENCY_US; 338 339 /* open the device in non-blocking mode */ 340 self->hdl = sio_open(dev_name, mode, 1); 341 if (self->hdl == NULL) { 342 dolog("failed to open device\n"); 343 return -1; 344 } 345 346 self->mode = mode; 347 348 sio_initpar(&req); 349 350 switch (as->fmt) { 351 case AUDIO_FORMAT_S8: 352 req.bits = 8; 353 req.sig = 1; 354 break; 355 case AUDIO_FORMAT_U8: 356 req.bits = 8; 357 req.sig = 0; 358 break; 359 case AUDIO_FORMAT_S16: 360 req.bits = 16; 361 req.sig = 1; 362 break; 363 case AUDIO_FORMAT_U16: 364 req.bits = 16; 365 req.sig = 0; 366 break; 367 case AUDIO_FORMAT_S32: 368 req.bits = 32; 369 req.sig = 1; 370 break; 371 case AUDIO_FORMAT_U32: 372 req.bits = 32; 373 req.sig = 0; 374 break; 375 default: 376 dolog("unknown audio sample format\n"); 377 return -1; 378 } 379 380 if (req.bits > 8) { 381 req.le = as->endianness ? 0 : 1; 382 } 383 384 req.rate = as->freq; 385 if (mode == SIO_PLAY) { 386 req.pchan = as->nchannels; 387 } else { 388 req.rchan = as->nchannels; 389 } 390 391 /* set on-device buffer size */ 392 req.appbufsz = req.rate * latency / 1000000; 393 394 if (!sio_setpar(self->hdl, &req)) { 395 dolog("failed set audio params\n"); 396 goto fail; 397 } 398 399 if (!sio_getpar(self->hdl, &self->par)) { 400 dolog("failed get audio params\n"); 401 goto fail; 402 } 403 404 nch = (mode == SIO_PLAY) ? self->par.pchan : self->par.rchan; 405 406 /* 407 * With the default setup, sndio supports any combination of parameters 408 * so these checks are mostly to catch configuration errors. 409 */ 410 if (self->par.bits != req.bits || self->par.bps != req.bits / 8 || 411 self->par.sig != req.sig || (req.bits > 8 && self->par.le != req.le) || 412 self->par.rate != as->freq || nch != as->nchannels) { 413 dolog("unsupported audio params\n"); 414 goto fail; 415 } 416 417 /* 418 * we use one block as buffer size; this is how 419 * transfers get well aligned 420 */ 421 self->buf_size = self->par.round * self->par.bps * nch; 422 423 self->buf = g_malloc(self->buf_size); 424 if (self->buf == NULL) { 425 dolog("failed to allocate audio buffer\n"); 426 goto fail; 427 } 428 429 nfds = sio_nfds(self->hdl); 430 431 self->pfds = g_malloc_n(nfds, sizeof(struct pollfd)); 432 if (self->pfds == NULL) { 433 dolog("failed to allocate pollfd structures\n"); 434 goto fail; 435 } 436 437 self->pindexes = g_malloc_n(nfds, sizeof(struct pollindex)); 438 if (self->pindexes == NULL) { 439 dolog("failed to allocate pollindex structures\n"); 440 goto fail; 441 } 442 443 for (i = 0; i < nfds; i++) { 444 self->pindexes[i].self = self; 445 self->pindexes[i].index = i; 446 } 447 448 return 0; 449 fail: 450 sndio_fini(self); 451 return -1; 452 } 453 454 static void sndio_enable(SndioVoice *self, bool enable) 455 { 456 if (enable) { 457 sio_start(self->hdl); 458 self->enabled = true; 459 sndio_poll_wait(self); 460 } else { 461 self->enabled = false; 462 sndio_poll_clear(self); 463 sio_stop(self->hdl); 464 } 465 } 466 467 static void sndio_enable_out(HWVoiceOut *hw, bool enable) 468 { 469 SndioVoice *self = (SndioVoice *) hw; 470 471 sndio_enable(self, enable); 472 } 473 474 static void sndio_enable_in(HWVoiceIn *hw, bool enable) 475 { 476 SndioVoice *self = (SndioVoice *) hw; 477 478 sndio_enable(self, enable); 479 } 480 481 static int sndio_init_out(HWVoiceOut *hw, struct audsettings *as, void *opaque) 482 { 483 SndioVoice *self = (SndioVoice *) hw; 484 485 if (sndio_init(self, as, SIO_PLAY, opaque) == -1) { 486 return -1; 487 } 488 489 audio_pcm_init_info(&hw->info, as); 490 hw->samples = self->par.round; 491 return 0; 492 } 493 494 static int sndio_init_in(HWVoiceIn *hw, struct audsettings *as, void *opaque) 495 { 496 SndioVoice *self = (SndioVoice *) hw; 497 498 if (sndio_init(self, as, SIO_REC, opaque) == -1) { 499 return -1; 500 } 501 502 audio_pcm_init_info(&hw->info, as); 503 hw->samples = self->par.round; 504 return 0; 505 } 506 507 static void sndio_fini_out(HWVoiceOut *hw) 508 { 509 SndioVoice *self = (SndioVoice *) hw; 510 511 sndio_fini(self); 512 } 513 514 static void sndio_fini_in(HWVoiceIn *hw) 515 { 516 SndioVoice *self = (SndioVoice *) hw; 517 518 sndio_fini(self); 519 } 520 521 static void *sndio_audio_init(Audiodev *dev) 522 { 523 assert(dev->driver == AUDIODEV_DRIVER_SNDIO); 524 return dev; 525 } 526 527 static void sndio_audio_fini(void *opaque) 528 { 529 } 530 531 static struct audio_pcm_ops sndio_pcm_ops = { 532 .init_out = sndio_init_out, 533 .fini_out = sndio_fini_out, 534 .enable_out = sndio_enable_out, 535 .write = audio_generic_write, 536 .buffer_get_free = sndio_buffer_get_free, 537 .get_buffer_out = sndio_get_buffer_out, 538 .put_buffer_out = sndio_put_buffer_out, 539 .init_in = sndio_init_in, 540 .fini_in = sndio_fini_in, 541 .read = audio_generic_read, 542 .enable_in = sndio_enable_in, 543 .get_buffer_in = sndio_get_buffer_in, 544 .put_buffer_in = sndio_put_buffer_in, 545 }; 546 547 static struct audio_driver sndio_audio_driver = { 548 .name = "sndio", 549 .descr = "sndio https://sndio.org", 550 .init = sndio_audio_init, 551 .fini = sndio_audio_fini, 552 .pcm_ops = &sndio_pcm_ops, 553 .can_be_default = 1, 554 .max_voices_out = INT_MAX, 555 .max_voices_in = INT_MAX, 556 .voice_size_out = sizeof(SndioVoice), 557 .voice_size_in = sizeof(SndioVoice) 558 }; 559 560 static void register_audio_sndio(void) 561 { 562 audio_driver_register(&sndio_audio_driver); 563 } 564 565 type_init(register_audio_sndio); 566