1/* 2 * PCM - Direct Stream Mixing 3 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz> 4 * 5 * 6 * This library is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as 8 * published by the Free Software Foundation; either version 2.1 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * 20 */ 21 22#include "pcm_local.h" 23#include <stdio.h> 24#include <stdlib.h> 25#include <stddef.h> 26#include <unistd.h> 27#include <signal.h> 28#include <string.h> 29#include <fcntl.h> 30#include <ctype.h> 31#include <grp.h> 32#include <sys/ioctl.h> 33#include <sys/mman.h> 34#include <poll.h> 35#include <sys/shm.h> 36#include <sys/sem.h> 37#include <sys/wait.h> 38#include <sys/socket.h> 39#include <sys/stat.h> 40#include <sys/un.h> 41#include <sys/mman.h> 42#include "pcm_direct.h" 43 44/* 45 * 46 */ 47 48#if !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__ANDROID__) 49union semun { 50 int val; /* Value for SETVAL */ 51 struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ 52 unsigned short *array; /* Array for GETALL, SETALL */ 53#if defined(__linux__) 54 struct seminfo *__buf; /* Buffer for IPC_INFO (Linux specific) */ 55#endif 56}; 57#endif 58 59/* 60 * FIXME: 61 * add possibility to use futexes here 62 */ 63 64int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix) 65{ 66 union semun s; 67 struct semid_ds buf; 68 int i; 69 70 dmix->semid = semget(dmix->ipc_key, DIRECT_IPC_SEMS, 71 IPC_CREAT | dmix->ipc_perm); 72 if (dmix->semid < 0) 73 return -errno; 74 if (dmix->ipc_gid < 0) 75 return 0; 76 for (i = 0; i < DIRECT_IPC_SEMS; i++) { 77 s.buf = &buf; 78 if (semctl(dmix->semid, i, IPC_STAT, s) < 0) { 79 int err = -errno; 80 snd_pcm_direct_semaphore_discard(dmix); 81 return err; 82 } 83 buf.sem_perm.gid = dmix->ipc_gid; 84 s.buf = &buf; 85 semctl(dmix->semid, i, IPC_SET, s); 86 } 87 return 0; 88} 89 90static unsigned int snd_pcm_direct_magic(snd_pcm_direct_t *dmix) 91{ 92 if (!dmix->direct_memory_access) 93 return 0xa15ad300 + sizeof(snd_pcm_direct_share_t); 94 else 95 return 0xb15ad300 + sizeof(snd_pcm_direct_share_t); 96} 97 98/* 99 * global shared memory area 100 */ 101 102int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix) 103{ 104 struct shmid_ds buf; 105 int tmpid, err, first_instance = 0; 106 107retryget: 108 dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t), 109 dmix->ipc_perm); 110 if (dmix->shmid < 0 && errno == ENOENT) { 111 if ((dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t), 112 IPC_CREAT | IPC_EXCL | dmix->ipc_perm)) != -1) 113 first_instance = 1; 114 else if (errno == EEXIST) 115 goto retryget; 116 } 117 err = -errno; 118 if (dmix->shmid < 0) { 119 if (errno == EINVAL) 120 if ((tmpid = shmget(dmix->ipc_key, 0, dmix->ipc_perm)) != -1) 121 if (!shmctl(tmpid, IPC_STAT, &buf)) 122 if (!buf.shm_nattch) 123 /* no users so destroy the segment */ 124 if (!shmctl(tmpid, IPC_RMID, NULL)) 125 goto retryget; 126 return err; 127 } 128 dmix->shmptr = shmat(dmix->shmid, 0, 0); 129 if (dmix->shmptr == (void *) -1) { 130 err = -errno; 131 snd_pcm_direct_shm_discard(dmix); 132 return err; 133 } 134 mlock(dmix->shmptr, sizeof(snd_pcm_direct_share_t)); 135 if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) { 136 err = -errno; 137 snd_pcm_direct_shm_discard(dmix); 138 return err; 139 } 140 if (first_instance) { /* we're the first user, clear the segment */ 141 memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t)); 142 if (dmix->ipc_gid >= 0) { 143 buf.shm_perm.gid = dmix->ipc_gid; 144 shmctl(dmix->shmid, IPC_SET, &buf); 145 } 146 dmix->shmptr->magic = snd_pcm_direct_magic(dmix); 147 return 1; 148 } else { 149 if (dmix->shmptr->magic != snd_pcm_direct_magic(dmix)) { 150 snd_pcm_direct_shm_discard(dmix); 151 return -EINVAL; 152 } 153 } 154 return 0; 155} 156 157/* discard shared memory */ 158/* 159 * Define snd_* functions to be used in server. 160 * Since objects referred in a plugin can be released dynamically, a forked 161 * server should have statically linked functions. 162 * (e.g. Novell bugzilla #105772) 163 */ 164static int _snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix) 165{ 166 struct shmid_ds buf; 167 int ret = 0; 168 169 if (dmix->shmid < 0) 170 return -EINVAL; 171 if (dmix->shmptr != (void *) -1 && shmdt(dmix->shmptr) < 0) 172 return -errno; 173 dmix->shmptr = (void *) -1; 174 if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) 175 return -errno; 176 if (buf.shm_nattch == 0) { /* we're the last user, destroy the segment */ 177 if (shmctl(dmix->shmid, IPC_RMID, NULL) < 0) 178 return -errno; 179 ret = 1; 180 } 181 dmix->shmid = -1; 182 return ret; 183} 184 185/* ... and an exported version */ 186int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix) 187{ 188 return _snd_pcm_direct_shm_discard(dmix); 189} 190 191/* 192 * server side 193 */ 194 195static int get_tmp_name(char *filename, size_t size) 196{ 197 struct timeval tv; 198 199 gettimeofday(&tv, NULL); 200 snprintf(filename, size, TMPDIR "/alsa-dmix-%i-%li-%li", (int)getpid(), (long)tv.tv_sec, (long)tv.tv_usec); 201 filename[size-1] = '\0'; 202 return 0; 203} 204 205static int make_local_socket(const char *filename, int server, mode_t ipc_perm, int ipc_gid) 206{ 207 size_t l = strlen(filename); 208 size_t size = offsetof(struct sockaddr_un, sun_path) + l; 209 struct sockaddr_un *addr = alloca(size); 210 int sock; 211 212 sock = socket(PF_LOCAL, SOCK_STREAM, 0); 213 if (sock < 0) { 214 int result = -errno; 215 SYSERR("socket failed"); 216 return result; 217 } 218 219 if (server) 220 unlink(filename); 221 memset(addr, 0, size); /* make valgrind happy */ 222 addr->sun_family = AF_LOCAL; 223 memcpy(addr->sun_path, filename, l); 224 225 if (server) { 226 if (bind(sock, (struct sockaddr *) addr, size) < 0) { 227 int result = -errno; 228 SYSERR("bind failed: %s", filename); 229 close(sock); 230 return result; 231 } else { 232 if (chmod(filename, ipc_perm) < 0) { 233 int result = -errno; 234 SYSERR("chmod failed: %s", filename); 235 close(sock); 236 unlink(filename); 237 return result; 238 } 239 if (chown(filename, -1, ipc_gid) < 0) { 240#if 0 /* it's not fatal */ 241 int result = -errno; 242 SYSERR("chown failed: %s", filename); 243 close(sock); 244 unlink(filename); 245 return result; 246#endif 247 } 248 } 249 } else { 250 if (connect(sock, (struct sockaddr *) addr, size) < 0) { 251 int result = -errno; 252 SYSERR("connect failed: %s", filename); 253 close(sock); 254 return result; 255 } 256 } 257 return sock; 258} 259 260#if 0 261#define SERVER_JOB_DEBUG 262#define server_printf(fmt, args...) printf(fmt, ##args) 263#else 264#undef SERVER_JOB_DEBUG 265#define server_printf(fmt, args...) /* nothing */ 266#endif 267 268static snd_pcm_direct_t *server_job_dmix; 269 270static void server_cleanup(snd_pcm_direct_t *dmix) 271{ 272 close(dmix->server_fd); 273 close(dmix->hw_fd); 274 if (dmix->server_free) 275 dmix->server_free(dmix); 276 unlink(dmix->shmptr->socket_name); 277 _snd_pcm_direct_shm_discard(dmix); 278 snd_pcm_direct_semaphore_discard(dmix); 279} 280 281static void server_job_signal(int sig ATTRIBUTE_UNUSED) 282{ 283 snd_pcm_direct_semaphore_down(server_job_dmix, DIRECT_IPC_SEM_CLIENT); 284 server_cleanup(server_job_dmix); 285 server_printf("DIRECT SERVER EXIT - SIGNAL\n"); 286 _exit(EXIT_SUCCESS); 287} 288 289/* This is a copy from ../socket.c, provided here only for a server job 290 * (see the comment above) 291 */ 292static int _snd_send_fd(int sock, void *data, size_t len, int fd) 293{ 294 int ret; 295 size_t cmsg_len = CMSG_LEN(sizeof(int)); 296 struct cmsghdr *cmsg = alloca(cmsg_len); 297 int *fds = (int *) CMSG_DATA(cmsg); 298 struct msghdr msghdr; 299 struct iovec vec; 300 301 vec.iov_base = (void *)&data; 302 vec.iov_len = len; 303 304 cmsg->cmsg_len = cmsg_len; 305 cmsg->cmsg_level = SOL_SOCKET; 306 cmsg->cmsg_type = SCM_RIGHTS; 307 *fds = fd; 308 309 msghdr.msg_name = NULL; 310 msghdr.msg_namelen = 0; 311 msghdr.msg_iov = &vec; 312 msghdr.msg_iovlen = 1; 313 msghdr.msg_control = cmsg; 314 msghdr.msg_controllen = cmsg_len; 315 msghdr.msg_flags = 0; 316 317 ret = sendmsg(sock, &msghdr, 0 ); 318 if (ret < 0) 319 return -errno; 320 return ret; 321} 322 323static void server_job(snd_pcm_direct_t *dmix) 324{ 325 int ret, sck, i; 326 int max = 128, current = 0; 327 struct pollfd pfds[max + 1]; 328 329 server_job_dmix = dmix; 330 /* don't allow to be killed */ 331 signal(SIGHUP, server_job_signal); 332 signal(SIGQUIT, server_job_signal); 333 signal(SIGTERM, server_job_signal); 334 signal(SIGKILL, server_job_signal); 335 /* close all files to free resources */ 336 i = sysconf(_SC_OPEN_MAX); 337#ifdef SERVER_JOB_DEBUG 338 while (--i >= 3) { 339#else 340 while (--i >= 0) { 341#endif 342 if (i != dmix->server_fd && i != dmix->hw_fd) 343 close(i); 344 } 345 346 /* detach from parent */ 347 setsid(); 348 349 pfds[0].fd = dmix->server_fd; 350 pfds[0].events = POLLIN | POLLERR | POLLHUP; 351 352 server_printf("DIRECT SERVER STARTED\n"); 353 while (1) { 354 ret = poll(pfds, current + 1, 500); 355 server_printf("DIRECT SERVER: poll ret = %i, revents[0] = 0x%x, errno = %i\n", ret, pfds[0].revents, errno); 356 if (ret < 0) { 357 if (errno == EINTR) 358 continue; 359 /* some error */ 360 break; 361 } 362 if (ret == 0 || (pfds[0].revents & (POLLERR | POLLHUP))) { /* timeout or error? */ 363 struct shmid_ds buf; 364 snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); 365 if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) { 366 _snd_pcm_direct_shm_discard(dmix); 367 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); 368 continue; 369 } 370 server_printf("DIRECT SERVER: nattch = %i\n", (int)buf.shm_nattch); 371 if (buf.shm_nattch == 1) /* server is the last user, exit */ 372 break; 373 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); 374 continue; 375 } 376 if (pfds[0].revents & POLLIN) { 377 ret--; 378 sck = accept(dmix->server_fd, 0, 0); 379 if (sck >= 0) { 380 server_printf("DIRECT SERVER: new connection %i\n", sck); 381 if (current == max) { 382 close(sck); 383 } else { 384 unsigned char buf = 'A'; 385 pfds[current+1].fd = sck; 386 pfds[current+1].events = POLLIN | POLLERR | POLLHUP; 387 _snd_send_fd(sck, &buf, 1, dmix->hw_fd); 388 server_printf("DIRECT SERVER: fd sent ok\n"); 389 current++; 390 } 391 } 392 } 393 for (i = 0; i < current && ret > 0; i++) { 394 struct pollfd *pfd = &pfds[i+1]; 395 unsigned char cmd; 396 server_printf("client %i revents = 0x%x\n", pfd->fd, pfd->revents); 397 if (pfd->revents & (POLLERR | POLLHUP)) { 398 ret--; 399 close(pfd->fd); 400 pfd->fd = -1; 401 continue; 402 } 403 if (!(pfd->revents & POLLIN)) 404 continue; 405 ret--; 406 if (read(pfd->fd, &cmd, 1) == 1) 407 cmd = 0 /*process command */; 408 } 409 for (i = 0; i < current; i++) { 410 if (pfds[i+1].fd < 0) { 411 if (i + 1 != max) 412 memcpy(&pfds[i+1], &pfds[i+2], sizeof(struct pollfd) * (max - i - 1)); 413 current--; 414 } 415 } 416 } 417 server_cleanup(dmix); 418 server_printf("DIRECT SERVER EXIT\n"); 419#ifdef SERVER_JOB_DEBUG 420 close(0); close(1); close(2); 421#endif 422 _exit(EXIT_SUCCESS); 423} 424 425int snd_pcm_direct_server_create(snd_pcm_direct_t *dmix) 426{ 427 int ret; 428 429 dmix->server_fd = -1; 430 431 ret = get_tmp_name(dmix->shmptr->socket_name, sizeof(dmix->shmptr->socket_name)); 432 if (ret < 0) 433 return ret; 434 435 ret = make_local_socket(dmix->shmptr->socket_name, 1, dmix->ipc_perm, dmix->ipc_gid); 436 if (ret < 0) 437 return ret; 438 dmix->server_fd = ret; 439 440 ret = listen(dmix->server_fd, 4); 441 if (ret < 0) { 442 close(dmix->server_fd); 443 return ret; 444 } 445 446 ret = fork(); 447 if (ret < 0) { 448 close(dmix->server_fd); 449 return ret; 450 } else if (ret == 0) { 451 ret = fork(); 452 if (ret == 0) 453 server_job(dmix); 454 _exit(EXIT_SUCCESS); 455 } else { 456 waitpid(ret, NULL, 0); 457 } 458 dmix->server_pid = ret; 459 dmix->server = 1; 460 return 0; 461} 462 463int snd_pcm_direct_server_discard(snd_pcm_direct_t *dmix) 464{ 465 if (dmix->server) { 466 //kill(dmix->server_pid, SIGTERM); 467 //waitpid(dmix->server_pid, NULL, 0); 468 dmix->server_pid = (pid_t)-1; 469 } 470 if (dmix->server_fd > 0) { 471 close(dmix->server_fd); 472 dmix->server_fd = -1; 473 } 474 dmix->server = 0; 475 return 0; 476} 477 478/* 479 * client side 480 */ 481 482int snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix) 483{ 484 int ret; 485 unsigned char buf; 486 487 ret = make_local_socket(dmix->shmptr->socket_name, 0, -1, -1); 488 if (ret < 0) 489 return ret; 490 dmix->comm_fd = ret; 491 492 ret = snd_receive_fd(dmix->comm_fd, &buf, 1, &dmix->hw_fd); 493 if (ret < 1 || buf != 'A') { 494 close(dmix->comm_fd); 495 dmix->comm_fd = -1; 496 return ret; 497 } 498 499 dmix->client = 1; 500 return 0; 501} 502 503int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix) 504{ 505 if (dmix->client) { 506 close(dmix->comm_fd); 507 dmix->comm_fd = -1; 508 } 509 return 0; 510} 511 512/* 513 * plugin helpers 514 */ 515 516int snd_pcm_direct_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) 517{ 518 /* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */ 519 return 0; 520} 521 522int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid) 523{ 524 snd_pcm_direct_t *dmix = pcm->private_data; 525 return snd_timer_async(dmix->timer, sig, pid); 526} 527 528/* empty the timer read queue */ 529int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix) 530{ 531 int changed = 0; 532 if (dmix->timer_need_poll) { 533 while (poll(&dmix->timer_fd, 1, 0) > 0) { 534 changed++; 535 /* we don't need the value */ 536 if (dmix->tread) { 537 snd_timer_tread_t rbuf[4]; 538 snd_timer_read(dmix->timer, rbuf, sizeof(rbuf)); 539 } else { 540 snd_timer_read_t rbuf; 541 snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)); 542 } 543 } 544 } else { 545 if (dmix->tread) { 546 snd_timer_tread_t rbuf[4]; 547 int len; 548 while ((len = snd_timer_read(dmix->timer, rbuf, 549 sizeof(rbuf))) > 0 550 && (++changed) && 551 len != sizeof(rbuf[0])) 552 ; 553 } else { 554 snd_timer_read_t rbuf; 555 while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0) 556 changed++; 557 } 558 } 559 return changed; 560} 561 562int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix) 563{ 564 snd_timer_stop(dmix->timer); 565 return 0; 566} 567 568#define RECOVERIES_FLAG_SUSPENDED (1U << 31) 569#define RECOVERIES_MASK ((1U << 31) - 1) 570 571/* 572 * Recover slave on XRUN or SUSPENDED. 573 * Even if direct plugins disable xrun detection, there might be an xrun 574 * raised directly by some drivers. 575 * The first client recovers slave pcm. 576 * Each client needs to execute sw xrun handling afterwards 577 */ 578int snd_pcm_direct_slave_recover(snd_pcm_direct_t *direct) 579{ 580 unsigned int recoveries; 581 int state; 582 int ret; 583 int semerr; 584 585 semerr = snd_pcm_direct_semaphore_down(direct, 586 DIRECT_IPC_SEM_CLIENT); 587 if (semerr < 0) { 588 SNDERR("SEMDOWN FAILED with err %d", semerr); 589 return semerr; 590 } 591 592 state = snd_pcm_state(direct->spcm); 593 if (state != SND_PCM_STATE_XRUN && state != SND_PCM_STATE_SUSPENDED) { 594 /* ignore... someone else already did recovery */ 595 semerr = snd_pcm_direct_semaphore_up(direct, 596 DIRECT_IPC_SEM_CLIENT); 597 if (semerr < 0) { 598 SNDERR("SEMUP FAILED with err %d", semerr); 599 return semerr; 600 } 601 return 0; 602 } 603 604 recoveries = direct->shmptr->s.recoveries; 605 recoveries = (recoveries + 1) & RECOVERIES_MASK; 606 if (state == SND_PCM_STATE_SUSPENDED) 607 recoveries |= RECOVERIES_FLAG_SUSPENDED; 608 direct->shmptr->s.recoveries = recoveries; 609 610 /* some buggy drivers require the device resumed before prepared; 611 * when a device has RESUME flag and is in SUSPENDED state, resume 612 * here but immediately drop to bring it to a sane active state. 613 */ 614 if (state == SND_PCM_STATE_SUSPENDED && 615 (direct->spcm->info & SND_PCM_INFO_RESUME)) { 616 snd_pcm_resume(direct->spcm); 617 snd_pcm_drop(direct->spcm); 618 snd_pcm_direct_timer_stop(direct); 619 snd_pcm_direct_clear_timer_queue(direct); 620 } 621 622 ret = snd_pcm_prepare(direct->spcm); 623 if (ret < 0) { 624 SNDERR("recover: unable to prepare slave"); 625 semerr = snd_pcm_direct_semaphore_up(direct, 626 DIRECT_IPC_SEM_CLIENT); 627 if (semerr < 0) { 628 SNDERR("SEMUP FAILED with err %d", semerr); 629 return semerr; 630 } 631 return ret; 632 } 633 634 if (direct->type == SND_PCM_TYPE_DSHARE) { 635 const snd_pcm_channel_area_t *dst_areas; 636 dst_areas = snd_pcm_mmap_areas(direct->spcm); 637 snd_pcm_areas_silence(dst_areas, 0, direct->spcm->channels, 638 direct->spcm->buffer_size, 639 direct->spcm->format); 640 } 641 642 ret = snd_pcm_start(direct->spcm); 643 if (ret < 0) { 644 SNDERR("recover: unable to start slave"); 645 semerr = snd_pcm_direct_semaphore_up(direct, 646 DIRECT_IPC_SEM_CLIENT); 647 if (semerr < 0) { 648 SNDERR("SEMUP FAILED with err %d", semerr); 649 return semerr; 650 } 651 return ret; 652 } 653 semerr = snd_pcm_direct_semaphore_up(direct, 654 DIRECT_IPC_SEM_CLIENT); 655 if (semerr < 0) { 656 SNDERR("SEMUP FAILED with err %d", semerr); 657 return semerr; 658 } 659 return 0; 660} 661 662/* 663 * enter xrun or suspended state, if slave xrun occurred or suspended 664 * @return: 0 for no xrun/suspend or a negative error code for xrun/suspend 665 */ 666int snd_pcm_direct_check_xrun(snd_pcm_direct_t *direct, snd_pcm_t *pcm) 667{ 668 int err; 669 670 switch (snd_pcm_state(direct->spcm)) { 671 case SND_PCM_STATE_DISCONNECTED: 672 direct->state = SNDRV_PCM_STATE_DISCONNECTED; 673 return -ENODEV; 674 case SND_PCM_STATE_XRUN: 675 case SND_PCM_STATE_SUSPENDED: 676 if ((err = snd_pcm_direct_slave_recover(direct)) < 0) 677 return err; 678 break; 679 default: 680 break; 681 } 682 683 if (direct->state == SND_PCM_STATE_XRUN) 684 return -EPIPE; 685 else if (direct->state == SND_PCM_STATE_SUSPENDED) 686 return -ESTRPIPE; 687 if (direct->shmptr->s.recoveries != direct->recoveries) { 688 /* no matter how many xruns we missed - 689 * so don't increment but just update to actual counter 690 */ 691 direct->recoveries = direct->shmptr->s.recoveries; 692 pcm->fast_ops->drop(pcm->fast_op_arg); 693 /* trigger_tstamp update is missing in drop callbacks */ 694 gettimestamp(&direct->trigger_tstamp, pcm->tstamp_type); 695 /* no timer clear: 696 * if slave already entered xrun again the event is lost. 697 * snd_pcm_direct_clear_timer_queue(direct); 698 */ 699 if (direct->recoveries & RECOVERIES_FLAG_SUSPENDED) { 700 direct->state = SND_PCM_STATE_SUSPENDED; 701 return -ESTRPIPE; 702 } else { 703 direct->state = SND_PCM_STATE_XRUN; 704 return -EPIPE; 705 } 706 } 707 return 0; 708} 709 710/* 711 * This is the only operation guaranteed to be called before entering poll(). 712 * Direct plugins use fd of snd_timer to poll on, these timers do NOT check 713 * state of substream in kernel by intention. 714 * Only the enter to xrun might be notified once (SND_TIMER_EVENT_MSTOP). 715 * If xrun event was not correctly handled or was ignored it will never be 716 * evaluated again afterwards. 717 * This will result in snd_pcm_wait() always returning timeout. 718 * In contrast poll() on pcm hardware checks ALSA state and will immediately 719 * return POLLERR on XRUN. 720 * 721 * To prevent timeout and applications endlessly spinning without xrun 722 * detected we add a state check here which may trigger the xrun sequence. 723 * 724 * return count of filled descriptors or negative error code 725 */ 726int snd_pcm_direct_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, 727 unsigned int space) 728{ 729 if (pcm->poll_fd < 0) { 730 SNDMSG("poll_fd < 0"); 731 return -EIO; 732 } 733 if (space >= 1 && pfds) { 734 pfds->fd = pcm->poll_fd; 735 pfds->events = pcm->poll_events | POLLERR | POLLNVAL; 736 } else { 737 return 0; 738 } 739 740 /* this will also evaluate slave state and enter xrun if necessary */ 741 /* using __snd_pcm_state() since this function is called inside lock */ 742 switch (__snd_pcm_state(pcm)) { 743 case SND_PCM_STATE_XRUN: 744 return -EPIPE; 745 default: 746 break; 747 } 748 return 1; 749} 750 751int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) 752{ 753 snd_pcm_direct_t *dmix = pcm->private_data; 754 unsigned short events; 755 int empty = 0; 756 757 assert(pfds && nfds == 1 && revents); 758 759timer_changed: 760 events = pfds[0].revents; 761 if (events & POLLIN) { 762 snd_pcm_uframes_t avail; 763 __snd_pcm_avail_update(pcm); 764 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { 765 events |= POLLOUT; 766 events &= ~POLLIN; 767 avail = snd_pcm_mmap_playback_avail(pcm); 768 } else { 769 avail = snd_pcm_mmap_capture_avail(pcm); 770 } 771 empty = avail < pcm->avail_min; 772 } 773 774 if (snd_pcm_direct_check_xrun(dmix, pcm) < 0 || 775 snd_pcm_state(dmix->spcm) == SND_PCM_STATE_SETUP) { 776 events |= POLLERR; 777 } else { 778 if (empty) { 779 /* here we have a race condition: 780 * if period event arrived after the avail_update call 781 * above we might clear this event with the following 782 * clear_timer_queue. 783 * There is no way to do this in atomic manner, so we 784 * need to recheck avail_update if we successfully 785 * cleared a poll event. 786 */ 787 if (snd_pcm_direct_clear_timer_queue(dmix)) 788 goto timer_changed; 789 events &= ~(POLLOUT|POLLIN); 790 /* additional check */ 791 switch (__snd_pcm_state(pcm)) { 792 case SND_PCM_STATE_XRUN: 793 case SND_PCM_STATE_SUSPENDED: 794 case SND_PCM_STATE_SETUP: 795 events |= POLLERR; 796 break; 797 default: 798 break; 799 } 800 } 801 } 802 *revents = events; 803 return 0; 804} 805 806int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info) 807{ 808 snd_pcm_direct_t *dmix = pcm->private_data; 809 810 if (dmix->spcm && !dmix->shmptr->use_server) 811 return snd_pcm_info(dmix->spcm, info); 812 813 memset(info, 0, sizeof(*info)); 814 info->stream = pcm->stream; 815 info->card = -1; 816 /* FIXME: fill this with something more useful: we know the hardware name */ 817 if (pcm->name) { 818 snd_strlcpy((char *)info->id, pcm->name, sizeof(info->id)); 819 snd_strlcpy((char *)info->name, pcm->name, sizeof(info->name)); 820 snd_strlcpy((char *)info->subname, pcm->name, sizeof(info->subname)); 821 } 822 info->subdevices_count = 1; 823 return 0; 824} 825 826static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params, 827 snd_pcm_hw_param_t var) 828{ 829 return ¶ms->masks[var - SND_PCM_HW_PARAM_FIRST_MASK]; 830} 831 832static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params, 833 snd_pcm_hw_param_t var) 834{ 835 return ¶ms->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL]; 836} 837 838static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params, 839 snd_pcm_hw_param_t var, 840 snd_interval_t *src) 841{ 842 snd_interval_t *i; 843 844 if (!(params->rmask & (1<<var))) /* nothing to do? */ 845 return 0; 846 i = hw_param_interval(params, var); 847 if (snd_interval_empty(i)) { 848 SNDERR("dshare interval %i empty?", (int)var); 849 return -EINVAL; 850 } 851 if (snd_interval_refine(i, src)) 852 params->cmask |= 1<<var; 853 return 0; 854} 855 856static int hw_param_interval_refine_minmax(snd_pcm_hw_params_t *params, 857 snd_pcm_hw_param_t var, 858 unsigned int imin, 859 unsigned int imax) 860{ 861 snd_interval_t t; 862 863 memset(&t, 0, sizeof(t)); 864 snd_interval_set_minmax(&t, imin, imax); 865 t.integer = 1; 866 return hw_param_interval_refine_one(params, var, &t); 867} 868 869/* this code is used 'as-is' from the alsa kernel code */ 870static int snd_interval_step(struct snd_interval *i, unsigned int min, 871 unsigned int step) 872{ 873 unsigned int n; 874 int changed = 0; 875 n = (i->min - min) % step; 876 if (n != 0 || i->openmin) { 877 i->min += step - n; 878 changed = 1; 879 } 880 n = (i->max - min) % step; 881 if (n != 0 || i->openmax) { 882 i->max -= n; 883 changed = 1; 884 } 885 if (snd_interval_checkempty(i)) { 886 i->empty = 1; 887 return -EINVAL; 888 } 889 return changed; 890} 891 892#undef REFINE_DEBUG 893 894int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) 895{ 896 snd_pcm_direct_t *dshare = pcm->private_data; 897 static const snd_mask_t access = { .bits = { 898 (1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) | 899 (1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) | 900 (1<<SNDRV_PCM_ACCESS_RW_INTERLEAVED) | 901 (1<<SNDRV_PCM_ACCESS_RW_NONINTERLEAVED), 902 0, 0, 0 } }; 903 int err; 904 905#ifdef REFINE_DEBUG 906 snd_output_t *log; 907 snd_output_stdio_attach(&log, stderr, 0); 908 snd_output_puts(log, "DMIX REFINE (begin):\n"); 909 snd_pcm_hw_params_dump(params, log); 910#endif 911 if (params->rmask & (1<<SND_PCM_HW_PARAM_ACCESS)) { 912 if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS))) { 913 SNDERR("dshare access mask empty?"); 914 return -EINVAL; 915 } 916 if (snd_mask_refine(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS), &access)) 917 params->cmask |= 1<<SND_PCM_HW_PARAM_ACCESS; 918 } 919 if (params->rmask & (1<<SND_PCM_HW_PARAM_FORMAT)) { 920 if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT))) { 921 SNDERR("dshare format mask empty?"); 922 return -EINVAL; 923 } 924 if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT), 925 dshare->shmptr->hw.format)) 926 params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT; 927 } 928 //snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT)); 929 if (params->rmask & (1<<SND_PCM_HW_PARAM_CHANNELS)) { 930 if (snd_interval_empty(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS))) { 931 SNDERR("dshare channels mask empty?"); 932 return -EINVAL; 933 } 934 err = snd_interval_refine_set(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS), dshare->channels); 935 if (err < 0) 936 return err; 937 } 938 err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE, 939 &dshare->shmptr->hw.rate); 940 if (err < 0) 941 return err; 942 943 if (dshare->max_periods < 0) { 944 err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, 945 &dshare->shmptr->hw.period_size); 946 if (err < 0) 947 return err; 948 err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME, 949 &dshare->shmptr->hw.period_time); 950 if (err < 0) 951 return err; 952 err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE, 953 &dshare->shmptr->hw.buffer_size); 954 if (err < 0) 955 return err; 956 err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME, 957 &dshare->shmptr->hw.buffer_time); 958 if (err < 0) 959 return err; 960 } else if (params->rmask & ((1<<SND_PCM_HW_PARAM_PERIODS)| 961 (1<<SND_PCM_HW_PARAM_BUFFER_BYTES)| 962 (1<<SND_PCM_HW_PARAM_BUFFER_SIZE)| 963 (1<<SND_PCM_HW_PARAM_BUFFER_TIME)| 964 (1<<SND_PCM_HW_PARAM_PERIOD_TIME)| 965 (1<<SND_PCM_HW_PARAM_PERIOD_SIZE)| 966 (1<<SND_PCM_HW_PARAM_PERIOD_BYTES))) { 967 snd_interval_t period_size = dshare->shmptr->hw.period_size; 968 snd_interval_t period_time = dshare->shmptr->hw.period_time; 969 int changed; 970 unsigned int max_periods = dshare->max_periods; 971 if (max_periods < 2) 972 max_periods = dshare->slave_buffer_size / dshare->slave_period_size; 973 974 /* make sure buffer size does not exceed slave buffer size */ 975 err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_BUFFER_SIZE, 976 2 * dshare->slave_period_size, dshare->slave_buffer_size); 977 if (err < 0) 978 return err; 979 if (dshare->var_periodsize) { 980 /* more tolerant settings... */ 981 if (dshare->shmptr->hw.buffer_size.max / 2 > period_size.max) { 982 period_size.max = dshare->shmptr->hw.buffer_size.max / 2; 983 period_size.openmax = dshare->shmptr->hw.buffer_size.openmax; 984 } 985 if (dshare->shmptr->hw.buffer_time.max / 2 > period_time.max) { 986 period_time.max = dshare->shmptr->hw.buffer_time.max / 2; 987 period_time.openmax = dshare->shmptr->hw.buffer_time.openmax; 988 } 989 } 990 991 err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE, 992 &period_size); 993 if (err < 0) 994 return err; 995 err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME, 996 &period_time); 997 if (err < 0) 998 return err; 999 do { 1000 changed = 0; 1001 err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS, 1002 2, max_periods); 1003 if (err < 0) 1004 return err; 1005 changed |= err; 1006 err = snd_pcm_hw_refine_soft(pcm, params); 1007 if (err < 0) 1008 return err; 1009 changed |= err; 1010 err = snd_interval_step(hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE), 1011 0, dshare->slave_period_size); 1012 if (err < 0) 1013 return err; 1014 changed |= err; 1015 if (err) 1016 params->rmask |= (1 << SND_PCM_HW_PARAM_PERIOD_SIZE); 1017 } while (changed); 1018 } 1019 dshare->timer_ticks = hw_param_interval(params, SND_PCM_HW_PARAM_PERIOD_SIZE)->max / dshare->slave_period_size; 1020 params->info = dshare->shmptr->s.info; 1021#ifdef REFINE_DEBUG 1022 snd_output_puts(log, "DMIX REFINE (end):\n"); 1023 snd_pcm_hw_params_dump(params, log); 1024 snd_output_close(log); 1025#endif 1026 return 0; 1027} 1028 1029int snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) 1030{ 1031 snd_pcm_direct_t *dmix = pcm->private_data; 1032 1033 params->info = dmix->shmptr->s.info; 1034 params->rate_num = dmix->shmptr->s.rate; 1035 params->rate_den = 1; 1036 params->fifo_size = 0; 1037 params->msbits = dmix->shmptr->s.msbits; 1038 return 0; 1039} 1040 1041int snd_pcm_direct_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 1042{ 1043 /* values are cached in the pcm structure */ 1044 return 0; 1045} 1046 1047int snd_pcm_direct_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) 1048{ 1049 if (params->tstamp_type != pcm->tstamp_type) 1050 return -EINVAL; 1051 1052 /* values are cached in the pcm structure */ 1053 return 0; 1054} 1055 1056int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) 1057{ 1058 return snd_pcm_channel_info_shm(pcm, info, -1); 1059} 1060 1061int snd_pcm_direct_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 1062{ 1063 return 0; 1064} 1065 1066int snd_pcm_direct_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 1067{ 1068 return 0; 1069} 1070 1071snd_pcm_chmap_query_t **snd_pcm_direct_query_chmaps(snd_pcm_t *pcm) 1072{ 1073 snd_pcm_direct_t *dmix = pcm->private_data; 1074 snd_pcm_chmap_query_t **smaps, **maps; 1075 unsigned int i, j; 1076 1077 if (dmix->bindings == NULL) 1078 return snd_pcm_query_chmaps(dmix->spcm); 1079 1080 maps = calloc(2, sizeof(*maps)); 1081 if (!maps) 1082 return NULL; 1083 maps[0] = calloc(dmix->channels + 2, sizeof(int *)); 1084 if (!maps[0]) { 1085 free(maps); 1086 return NULL; 1087 } 1088 smaps = snd_pcm_query_chmaps(dmix->spcm); 1089 if (smaps == NULL) { 1090 snd_pcm_free_chmaps(maps); 1091 return NULL; 1092 } 1093 maps[0]->type = SND_CHMAP_TYPE_FIXED; 1094 maps[0]->map.channels = dmix->channels; 1095 for (i = 0; i < dmix->channels; i++) { 1096 j = dmix->bindings[i]; 1097 if (j == UINT_MAX || smaps[0]->map.channels < j) 1098 continue; 1099 maps[0]->map.pos[i] = smaps[0]->map.pos[j]; 1100 } 1101 return maps; 1102} 1103 1104snd_pcm_chmap_t *snd_pcm_direct_get_chmap(snd_pcm_t *pcm) 1105{ 1106 snd_pcm_direct_t *dmix = pcm->private_data; 1107 return snd_pcm_get_chmap(dmix->spcm); 1108} 1109 1110int snd_pcm_direct_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map) 1111{ 1112 snd_pcm_direct_t *dmix = pcm->private_data; 1113 return snd_pcm_set_chmap(dmix->spcm, map); 1114} 1115 1116int snd_pcm_direct_prepare(snd_pcm_t *pcm) 1117{ 1118 snd_pcm_direct_t *dmix = pcm->private_data; 1119 int err; 1120 1121 switch (snd_pcm_state(dmix->spcm)) { 1122 case SND_PCM_STATE_SETUP: 1123 case SND_PCM_STATE_XRUN: 1124 case SND_PCM_STATE_SUSPENDED: 1125 err = snd_pcm_prepare(dmix->spcm); 1126 if (err < 0) 1127 return err; 1128 snd_pcm_start(dmix->spcm); 1129 break; 1130 case SND_PCM_STATE_OPEN: 1131 case SND_PCM_STATE_DISCONNECTED: 1132 return -EBADFD; 1133 default: 1134 break; 1135 } 1136 snd_pcm_direct_check_interleave(dmix, pcm); 1137 dmix->state = SND_PCM_STATE_PREPARED; 1138 dmix->appl_ptr = dmix->last_appl_ptr = 0; 1139 dmix->hw_ptr = 0; 1140 return snd_pcm_direct_set_timer_params(dmix); 1141} 1142 1143int snd_pcm_direct_resume(snd_pcm_t *pcm) 1144{ 1145 snd_pcm_direct_t *dmix = pcm->private_data; 1146 int err; 1147 1148 err = snd_pcm_direct_slave_recover(dmix); 1149 return err < 0 ? err : -ENOSYS; 1150} 1151 1152#define COPY_SLAVE(field) (dmix->shmptr->s.field = spcm->field) 1153 1154/* copy the slave setting */ 1155static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) 1156{ 1157 spcm->info &= ~SND_PCM_INFO_PAUSE; 1158 1159 COPY_SLAVE(access); 1160 COPY_SLAVE(format); 1161 COPY_SLAVE(subformat); 1162 COPY_SLAVE(channels); 1163 COPY_SLAVE(rate); 1164 COPY_SLAVE(period_size); 1165 COPY_SLAVE(period_time); 1166 COPY_SLAVE(periods); 1167 COPY_SLAVE(tstamp_mode); 1168 COPY_SLAVE(tstamp_type); 1169 COPY_SLAVE(period_step); 1170 COPY_SLAVE(avail_min); 1171 COPY_SLAVE(start_threshold); 1172 COPY_SLAVE(stop_threshold); 1173 COPY_SLAVE(silence_threshold); 1174 COPY_SLAVE(silence_size); 1175 COPY_SLAVE(boundary); 1176 COPY_SLAVE(info); 1177 COPY_SLAVE(msbits); 1178 COPY_SLAVE(rate_num); 1179 COPY_SLAVE(rate_den); 1180 COPY_SLAVE(hw_flags); 1181 COPY_SLAVE(fifo_size); 1182 COPY_SLAVE(buffer_size); 1183 COPY_SLAVE(buffer_time); 1184 COPY_SLAVE(sample_bits); 1185 COPY_SLAVE(frame_bits); 1186 1187 dmix->shmptr->s.info &= ~SND_PCM_INFO_RESUME; 1188} 1189 1190#undef COPY_SLAVE 1191 1192/* 1193 * this function initializes hardware and starts playback operation with 1194 * no stop threshold (it operates all time without xrun checking) 1195 * also, the driver silences the unused ring buffer areas for us 1196 */ 1197int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params) 1198{ 1199 snd_pcm_hw_params_t hw_params = {0}; 1200 snd_pcm_sw_params_t sw_params = {0}; 1201 int ret, buffer_is_not_initialized; 1202 snd_pcm_uframes_t boundary; 1203 struct pollfd fd; 1204 int loops = 10; 1205 1206 __again: 1207 if (loops-- <= 0) { 1208 SNDERR("unable to find a valid configuration for slave"); 1209 return -EINVAL; 1210 } 1211 ret = snd_pcm_hw_params_any(spcm, &hw_params); 1212 if (ret < 0) { 1213 SNDERR("snd_pcm_hw_params_any failed"); 1214 return ret; 1215 } 1216 ret = snd_pcm_hw_params_set_access(spcm, &hw_params, 1217 SND_PCM_ACCESS_MMAP_INTERLEAVED); 1218 if (ret < 0) { 1219 ret = snd_pcm_hw_params_set_access(spcm, &hw_params, 1220 SND_PCM_ACCESS_MMAP_NONINTERLEAVED); 1221 if (ret < 0) { 1222 SNDERR("slave plugin does not support mmap interleaved or mmap noninterleaved access"); 1223 return ret; 1224 } 1225 } 1226 if (params->format == SND_PCM_FORMAT_UNKNOWN) 1227 ret = -EINVAL; 1228 else 1229 ret = snd_pcm_hw_params_set_format(spcm, &hw_params, 1230 params->format); 1231 if (ret < 0) { 1232 static const snd_pcm_format_t dmix_formats[] = { 1233 SND_PCM_FORMAT_S32, 1234 SND_PCM_FORMAT_S32 ^ SND_PCM_FORMAT_S32_LE ^ 1235 SND_PCM_FORMAT_S32_BE, 1236 SND_PCM_FORMAT_S16, 1237 SND_PCM_FORMAT_S16 ^ SND_PCM_FORMAT_S16_LE ^ 1238 SND_PCM_FORMAT_S16_BE, 1239 SND_PCM_FORMAT_S24_LE, 1240 SND_PCM_FORMAT_S24_3LE, 1241 SND_PCM_FORMAT_U8, 1242 }; 1243 snd_pcm_format_t format; 1244 unsigned int i; 1245 1246 for (i = 0; i < ARRAY_SIZE(dmix_formats); ++i) { 1247 format = dmix_formats[i]; 1248 ret = snd_pcm_hw_params_set_format(spcm, &hw_params, 1249 format); 1250 if (ret >= 0) 1251 break; 1252 } 1253 if (ret < 0 && dmix->type != SND_PCM_TYPE_DMIX) { 1254 /* TODO: try to choose a good format */ 1255 ret = INTERNAL(snd_pcm_hw_params_set_format_first)(spcm, 1256 &hw_params, &format); 1257 } 1258 if (ret < 0) { 1259 SNDERR("requested or auto-format is not available"); 1260 return ret; 1261 } 1262 params->format = format; 1263 } 1264 ret = INTERNAL(snd_pcm_hw_params_set_channels_near)(spcm, &hw_params, 1265 (unsigned int *)¶ms->channels); 1266 if (ret < 0) { 1267 SNDERR("requested count of channels is not available"); 1268 return ret; 1269 } 1270 ret = INTERNAL(snd_pcm_hw_params_set_rate_near)(spcm, &hw_params, 1271 (unsigned int *)¶ms->rate, 0); 1272 if (ret < 0) { 1273 SNDERR("requested rate is not available"); 1274 return ret; 1275 } 1276 1277 buffer_is_not_initialized = 0; 1278 if (params->buffer_time > 0) { 1279 ret = INTERNAL(snd_pcm_hw_params_set_buffer_time_near)(spcm, 1280 &hw_params, (unsigned int *)¶ms->buffer_time, 0); 1281 if (ret < 0) { 1282 SNDERR("unable to set buffer time"); 1283 return ret; 1284 } 1285 } else if (params->buffer_size > 0) { 1286 ret = INTERNAL(snd_pcm_hw_params_set_buffer_size_near)(spcm, 1287 &hw_params, (snd_pcm_uframes_t *)¶ms->buffer_size); 1288 if (ret < 0) { 1289 SNDERR("unable to set buffer size"); 1290 return ret; 1291 } 1292 } else { 1293 buffer_is_not_initialized = 1; 1294 } 1295 1296 if (params->period_time > 0) { 1297 ret = INTERNAL(snd_pcm_hw_params_set_period_time_near)(spcm, 1298 &hw_params, (unsigned int *)¶ms->period_time, 0); 1299 if (ret < 0) { 1300 SNDERR("unable to set period_time"); 1301 return ret; 1302 } 1303 } else if (params->period_size > 0) { 1304 ret = INTERNAL(snd_pcm_hw_params_set_period_size_near)(spcm, 1305 &hw_params, (snd_pcm_uframes_t *)¶ms->period_size, 1306 0); 1307 if (ret < 0) { 1308 SNDERR("unable to set period_size"); 1309 return ret; 1310 } 1311 } 1312 1313 if (buffer_is_not_initialized && params->periods > 0) { 1314 unsigned int periods = params->periods; 1315 ret = INTERNAL(snd_pcm_hw_params_set_periods_near)(spcm, 1316 &hw_params, ¶ms->periods, 0); 1317 if (ret < 0) { 1318 SNDERR("unable to set requested periods"); 1319 return ret; 1320 } 1321 if (params->periods == 1) { 1322 params->periods = periods; 1323 if (params->period_time > 0) { 1324 params->period_time /= 2; 1325 goto __again; 1326 } else if (params->period_size > 0) { 1327 params->period_size /= 2; 1328 goto __again; 1329 } 1330 SNDERR("unable to use stream with periods == 1"); 1331 return ret; 1332 } 1333 } 1334 1335 ret = snd_pcm_hw_params(spcm, &hw_params); 1336 if (ret < 0) { 1337 SNDERR("unable to install hw params"); 1338 return ret; 1339 } 1340 1341 /* store some hw_params values to shared info */ 1342 dmix->shmptr->hw.format = 1343 snd_mask_value(hw_param_mask(&hw_params, 1344 SND_PCM_HW_PARAM_FORMAT)); 1345 dmix->shmptr->hw.rate = 1346 *hw_param_interval(&hw_params, SND_PCM_HW_PARAM_RATE); 1347 dmix->shmptr->hw.buffer_size = 1348 *hw_param_interval(&hw_params, SND_PCM_HW_PARAM_BUFFER_SIZE); 1349 dmix->shmptr->hw.buffer_time = 1350 *hw_param_interval(&hw_params, SND_PCM_HW_PARAM_BUFFER_TIME); 1351 dmix->shmptr->hw.period_size = 1352 *hw_param_interval(&hw_params, SND_PCM_HW_PARAM_PERIOD_SIZE); 1353 dmix->shmptr->hw.period_time = 1354 *hw_param_interval(&hw_params, SND_PCM_HW_PARAM_PERIOD_TIME); 1355 dmix->shmptr->hw.periods = 1356 *hw_param_interval(&hw_params, SND_PCM_HW_PARAM_PERIODS); 1357 1358 1359 ret = snd_pcm_sw_params_current(spcm, &sw_params); 1360 if (ret < 0) { 1361 SNDERR("unable to get current sw_params"); 1362 return ret; 1363 } 1364 1365 ret = snd_pcm_sw_params_get_boundary(&sw_params, &boundary); 1366 if (ret < 0) { 1367 SNDERR("unable to get boundary"); 1368 return ret; 1369 } 1370 ret = snd_pcm_sw_params_set_stop_threshold(spcm, &sw_params, boundary); 1371 if (ret < 0) { 1372 SNDERR("unable to set stop threshold"); 1373 return ret; 1374 } 1375 1376 /* set timestamp mode to MMAP 1377 * the slave timestamp is copied appropriately in dsnoop/dmix/dshare 1378 * based on the tstamp_mode of each client 1379 */ 1380 ret = snd_pcm_sw_params_set_tstamp_mode(spcm, &sw_params, 1381 SND_PCM_TSTAMP_ENABLE); 1382 if (ret < 0) { 1383 SNDERR("unable to tstamp mode MMAP"); 1384 return ret; 1385 } 1386 1387 if (dmix->tstamp_type != -1) { 1388 ret = snd_pcm_sw_params_set_tstamp_type(spcm, &sw_params, 1389 dmix->tstamp_type); 1390 if (ret < 0) { 1391 SNDERR("unable to set tstamp type"); 1392 return ret; 1393 } 1394 } 1395 1396 if (dmix->type != SND_PCM_TYPE_DMIX && 1397 dmix->type != SND_PCM_TYPE_DSHARE) 1398 goto __skip_silencing; 1399 1400 ret = snd_pcm_sw_params_set_silence_threshold(spcm, &sw_params, 0); 1401 if (ret < 0) { 1402 SNDERR("unable to set silence threshold"); 1403 return ret; 1404 } 1405 ret = snd_pcm_sw_params_set_silence_size(spcm, &sw_params, boundary); 1406 if (ret < 0) { 1407 SNDERR("unable to set silence threshold (please upgrade to 0.9.0rc8+ driver)"); 1408 return ret; 1409 } 1410 1411 __skip_silencing: 1412 1413 ret = snd_pcm_sw_params(spcm, &sw_params); 1414 if (ret < 0) { 1415 SNDERR("unable to install sw params (please upgrade to 0.9.0rc8+ driver)"); 1416 return ret; 1417 } 1418 1419 if (dmix->type == SND_PCM_TYPE_DSHARE) { 1420 const snd_pcm_channel_area_t *dst_areas; 1421 dst_areas = snd_pcm_mmap_areas(spcm); 1422 snd_pcm_areas_silence(dst_areas, 0, spcm->channels, 1423 spcm->buffer_size, spcm->format); 1424 } 1425 1426 ret = snd_pcm_start(spcm); 1427 if (ret < 0) { 1428 SNDERR("unable to start PCM stream"); 1429 return ret; 1430 } 1431 1432 if (snd_pcm_poll_descriptors_count(spcm) != 1) { 1433 SNDERR("unable to use hardware pcm with fd more than one!!!"); 1434 return ret; 1435 } 1436 snd_pcm_poll_descriptors(spcm, &fd, 1); 1437 dmix->hw_fd = fd.fd; 1438 1439 save_slave_setting(dmix, spcm); 1440 1441 /* Currently, we assume that each dmix client has the same 1442 * hw_params setting. 1443 * If the arbitrary hw_parmas is supported in future, 1444 * boundary has to be taken from the slave config but 1445 * recalculated for the native boundary size (for 32bit 1446 * emulation on 64bit arch). 1447 */ 1448 dmix->slave_buffer_size = spcm->buffer_size; 1449 dmix->slave_period_size = spcm->period_size; 1450 dmix->slave_boundary = spcm->boundary; 1451 1452 spcm->donot_close = 1; 1453 1454 { 1455 int ver = 0; 1456 ioctl(spcm->poll_fd, SNDRV_PCM_IOCTL_PVERSION, &ver); 1457 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 8)) 1458 dmix->shmptr->use_server = 1; 1459 } 1460 1461 return 0; 1462} 1463 1464/* 1465 * the trick is used here; we cannot use effectively the hardware handle because 1466 * we cannot drive multiple accesses to appl_ptr; so we use slave timer of given 1467 * PCM hardware handle; it's not this easy and cheap? 1468 */ 1469int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix) 1470{ 1471 int ret; 1472 snd_pcm_info_t info = {0}; 1473 char name[128]; 1474 int capture = dmix->type == SND_PCM_TYPE_DSNOOP ? 1 : 0; 1475 1476 dmix->tread = 1; 1477 dmix->timer_need_poll = 0; 1478 dmix->timer_ticks = 1; 1479 ret = snd_pcm_info(dmix->spcm, &info); 1480 if (ret < 0) { 1481 SNDERR("unable to info for slave pcm"); 1482 return ret; 1483 } 1484 sprintf(name, "hw:CLASS=%i,SCLASS=0,CARD=%i,DEV=%i,SUBDEV=%i", 1485 (int)SND_TIMER_CLASS_PCM, 1486 snd_pcm_info_get_card(&info), 1487 snd_pcm_info_get_device(&info), 1488 snd_pcm_info_get_subdevice(&info) * 2 + capture); 1489 ret = snd_timer_open(&dmix->timer, name, 1490 SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD); 1491 if (ret < 0) { 1492 dmix->tread = 0; 1493 ret = snd_timer_open(&dmix->timer, name, 1494 SND_TIMER_OPEN_NONBLOCK); 1495 if (ret < 0) { 1496 SNDERR("unable to open timer '%s'", name); 1497 return ret; 1498 } 1499 } 1500 1501 if (snd_timer_poll_descriptors_count(dmix->timer) != 1) { 1502 SNDERR("unable to use timer '%s' with more than one fd!", name); 1503 return ret; 1504 } 1505 snd_timer_poll_descriptors(dmix->timer, &dmix->timer_fd, 1); 1506 dmix->poll_fd = dmix->timer_fd.fd; 1507 1508 dmix->timer_events = (1<<SND_TIMER_EVENT_MSUSPEND) | 1509 (1<<SND_TIMER_EVENT_MRESUME) | 1510 (1<<SND_TIMER_EVENT_MSTOP) | 1511 (1<<SND_TIMER_EVENT_STOP); 1512 1513 /* 1514 * Some hacks for older kernel drivers 1515 */ 1516 { 1517 int ver = 0; 1518 ioctl(dmix->poll_fd, SNDRV_TIMER_IOCTL_PVERSION, &ver); 1519 /* In older versions, check via poll before read() is needed 1520 * because of the confliction between TIMER_START and 1521 * FIONBIO ioctls. 1522 */ 1523 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 4)) 1524 dmix->timer_need_poll = 1; 1525 /* 1526 * In older versions, timer uses pause events instead 1527 * suspend/resume events. 1528 */ 1529 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 5)) { 1530 dmix->timer_events &= ~((1<<SND_TIMER_EVENT_MSUSPEND) | 1531 (1<<SND_TIMER_EVENT_MRESUME)); 1532 dmix->timer_events |= (1<<SND_TIMER_EVENT_MPAUSE) | 1533 (1<<SND_TIMER_EVENT_MCONTINUE); 1534 } 1535 /* In older versions, use SND_TIMER_EVENT_START too. 1536 */ 1537 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 6)) 1538 dmix->timer_events |= 1<<SND_TIMER_EVENT_START; 1539 } 1540 return 0; 1541} 1542 1543static snd_pcm_uframes_t recalc_boundary_size(unsigned long long bsize, snd_pcm_uframes_t buffer_size) 1544{ 1545 if (bsize > LONG_MAX) { 1546 bsize = buffer_size; 1547 while (bsize * 2 <= LONG_MAX - buffer_size) 1548 bsize *= 2; 1549 } 1550 return (snd_pcm_uframes_t)bsize; 1551} 1552 1553#define COPY_SLAVE(field) (spcm->field = dmix->shmptr->s.field) 1554 1555/* copy the slave setting */ 1556static void copy_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm) 1557{ 1558 COPY_SLAVE(access); 1559 COPY_SLAVE(format); 1560 COPY_SLAVE(subformat); 1561 COPY_SLAVE(channels); 1562 COPY_SLAVE(rate); 1563 COPY_SLAVE(period_size); 1564 COPY_SLAVE(period_time); 1565 COPY_SLAVE(periods); 1566 COPY_SLAVE(tstamp_mode); 1567 COPY_SLAVE(tstamp_type); 1568 COPY_SLAVE(period_step); 1569 COPY_SLAVE(avail_min); 1570 COPY_SLAVE(start_threshold); 1571 COPY_SLAVE(stop_threshold); 1572 COPY_SLAVE(silence_threshold); 1573 COPY_SLAVE(silence_size); 1574 COPY_SLAVE(boundary); 1575 COPY_SLAVE(info); 1576 COPY_SLAVE(msbits); 1577 COPY_SLAVE(rate_num); 1578 COPY_SLAVE(rate_den); 1579 COPY_SLAVE(hw_flags); 1580 COPY_SLAVE(fifo_size); 1581 COPY_SLAVE(buffer_size); 1582 COPY_SLAVE(buffer_time); 1583 COPY_SLAVE(sample_bits); 1584 COPY_SLAVE(frame_bits); 1585 1586 spcm->info &= ~SND_PCM_INFO_PAUSE; 1587 spcm->boundary = recalc_boundary_size(dmix->shmptr->s.boundary, spcm->buffer_size); 1588} 1589 1590#undef COPY_SLAVE 1591 1592 1593/* 1594 * open a slave PCM as secondary client (dup'ed fd) 1595 */ 1596int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name) 1597{ 1598 int ret; 1599 snd_pcm_t *spcm; 1600 1601 ret = snd_pcm_hw_open_fd(spcmp, client_name, dmix->hw_fd, 0); 1602 if (ret < 0) { 1603 SNDERR("unable to open hardware"); 1604 return ret; 1605 } 1606 1607 spcm = *spcmp; 1608 spcm->donot_close = 1; 1609 spcm->setup = 1; 1610 1611 copy_slave_setting(dmix, spcm); 1612 1613 /* Use the slave setting as SPCM, so far */ 1614 dmix->slave_buffer_size = spcm->buffer_size; 1615 dmix->slave_period_size = dmix->shmptr->s.period_size; 1616 dmix->slave_boundary = spcm->boundary; 1617 dmix->recoveries = dmix->shmptr->s.recoveries; 1618 1619 ret = snd_pcm_mmap(spcm); 1620 if (ret < 0) { 1621 SNDERR("unable to mmap channels"); 1622 return ret; 1623 } 1624 return 0; 1625} 1626 1627/* 1628 * open a slave PCM as secondary client (dup'ed fd) 1629 */ 1630int snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix, 1631 snd_pcm_t *spcm, 1632 struct slave_params *params ATTRIBUTE_UNUSED) 1633{ 1634 int ret; 1635 1636 spcm->donot_close = 1; 1637 spcm->setup = 1; 1638 1639 copy_slave_setting(dmix, spcm); 1640 1641 /* Use the slave setting as SPCM, so far */ 1642 dmix->slave_buffer_size = spcm->buffer_size; 1643 dmix->slave_period_size = dmix->shmptr->s.period_size; 1644 dmix->slave_boundary = spcm->boundary; 1645 1646 ret = snd_pcm_mmap(spcm); 1647 if (ret < 0) { 1648 SNDERR("unable to mmap channels"); 1649 return ret; 1650 } 1651 return 0; 1652} 1653 1654int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix) 1655{ 1656 snd_timer_params_t params = {0}; 1657 unsigned int filter; 1658 int ret; 1659 1660 snd_timer_params_set_auto_start(¶ms, 1); 1661 if (dmix->type != SND_PCM_TYPE_DSNOOP) 1662 snd_timer_params_set_early_event(¶ms, 1); 1663 snd_timer_params_set_ticks(¶ms, dmix->timer_ticks); 1664 if (dmix->tread) { 1665 filter = (1<<SND_TIMER_EVENT_TICK) | 1666 dmix->timer_events; 1667 INTERNAL(snd_timer_params_set_filter)(¶ms, filter); 1668 } 1669 ret = snd_timer_params(dmix->timer, ¶ms); 1670 if (ret < 0) { 1671 SNDERR("unable to set timer parameters"); 1672 return ret; 1673 } 1674 return 0; 1675} 1676 1677/* 1678 * ring buffer operation 1679 */ 1680int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm) 1681{ 1682 unsigned int chn, channels; 1683 int bits; 1684 const snd_pcm_channel_area_t *dst_areas; 1685 const snd_pcm_channel_area_t *src_areas; 1686 1687 bits = snd_pcm_format_physical_width(pcm->format); 1688 if ((bits % 8) != 0) 1689 goto __nointerleaved; 1690 channels = dmix->channels; 1691 if (channels != dmix->spcm->channels) 1692 goto __nointerleaved; 1693 dst_areas = snd_pcm_mmap_areas(dmix->spcm); 1694 src_areas = snd_pcm_mmap_areas(pcm); 1695 for (chn = 1; chn < channels; chn++) { 1696 if (dst_areas[chn-1].addr != dst_areas[chn].addr) 1697 goto __nointerleaved; 1698 if (src_areas[chn-1].addr != src_areas[chn].addr) 1699 goto __nointerleaved; 1700 } 1701 for (chn = 0; chn < channels; chn++) { 1702 if (dmix->bindings && dmix->bindings[chn] != chn) 1703 goto __nointerleaved; 1704 if (dst_areas[chn].first != chn * bits || 1705 dst_areas[chn].step != channels * bits) 1706 goto __nointerleaved; 1707 if (src_areas[chn].first != chn * bits || 1708 src_areas[chn].step != channels * bits) 1709 goto __nointerleaved; 1710 } 1711 return dmix->interleaved = 1; 1712__nointerleaved: 1713 return dmix->interleaved = 0; 1714} 1715 1716/* 1717 * parse the channel map 1718 * id == client channel 1719 * value == slave's channel 1720 */ 1721int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix, 1722 struct slave_params *params, 1723 snd_config_t *cfg) 1724{ 1725 snd_config_iterator_t i, next; 1726 unsigned int chn, chn1, count = 0; 1727 unsigned int *bindings; 1728 int err; 1729 1730 dmix->channels = UINT_MAX; 1731 if (cfg == NULL) 1732 return 0; 1733 if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { 1734 SNDERR("invalid type for bindings"); 1735 return -EINVAL; 1736 } 1737 snd_config_for_each(i, next, cfg) { 1738 snd_config_t *n = snd_config_iterator_entry(i); 1739 const char *id; 1740 long cchannel; 1741 if (snd_config_get_id(n, &id) < 0) 1742 continue; 1743 err = safe_strtol(id, &cchannel); 1744 if (err < 0 || cchannel < 0) { 1745 SNDERR("invalid client channel in binding: %s", id); 1746 return -EINVAL; 1747 } 1748 if ((unsigned)cchannel >= count) 1749 count = cchannel + 1; 1750 } 1751 if (count == 0) 1752 return 0; 1753 if (count > 1024) { 1754 SNDERR("client channel out of range"); 1755 return -EINVAL; 1756 } 1757 bindings = malloc(count * sizeof(unsigned int)); 1758 if (bindings == NULL) 1759 return -ENOMEM; 1760 for (chn = 0; chn < count; chn++) 1761 bindings[chn] = UINT_MAX; /* don't route */ 1762 snd_config_for_each(i, next, cfg) { 1763 snd_config_t *n = snd_config_iterator_entry(i); 1764 const char *id; 1765 long cchannel, schannel; 1766 if (snd_config_get_id(n, &id) < 0) 1767 continue; 1768 safe_strtol(id, &cchannel); 1769 if (snd_config_get_integer(n, &schannel) < 0) { 1770 SNDERR("unable to get slave channel (should be integer type) in binding: %s", id); 1771 free(bindings); 1772 return -EINVAL; 1773 } 1774 if (schannel < 0 || schannel >= params->channels) { 1775 SNDERR("invalid slave channel number %ld in binding to %ld", 1776 schannel, cchannel); 1777 free(bindings); 1778 return -EINVAL; 1779 } 1780 bindings[cchannel] = schannel; 1781 } 1782 if (dmix->type == SND_PCM_TYPE_DSNOOP || 1783 ! dmix->bindings) 1784 goto __skip_same_dst; 1785 for (chn = 0; chn < count; chn++) { 1786 for (chn1 = 0; chn1 < count; chn1++) { 1787 if (chn == chn1) 1788 continue; 1789 if (bindings[chn] == dmix->bindings[chn1]) { 1790 SNDERR("unable to route channels %d,%d to same destination %d", chn, chn1, bindings[chn]); 1791 free(bindings); 1792 return -EINVAL; 1793 } 1794 } 1795 } 1796 __skip_same_dst: 1797 dmix->bindings = bindings; 1798 dmix->channels = count; 1799 return 0; 1800} 1801 1802/* 1803 * parse slave config and calculate the ipc_key offset 1804 */ 1805 1806static int _snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root, 1807 snd_config_t *sconf, 1808 int direction, 1809 int hop) 1810{ 1811 snd_config_iterator_t i, next; 1812 snd_config_t *pcm_conf, *pcm_conf2; 1813 int err; 1814 long card = 0, device = 0, subdevice = 0; 1815 const char *str; 1816 1817 if (snd_config_get_string(sconf, &str) >= 0) { 1818 if (hop > SND_CONF_MAX_HOPS) { 1819 SNDERR("Too many definition levels (looped?)"); 1820 return -EINVAL; 1821 } 1822 err = snd_config_search_definition(root, "pcm", str, &pcm_conf); 1823 if (err < 0) { 1824 SNDERR("Unknown slave PCM %s", str); 1825 return err; 1826 } 1827 err = _snd_pcm_direct_get_slave_ipc_offset(root, pcm_conf, 1828 direction, 1829 hop + 1); 1830 snd_config_delete(pcm_conf); 1831 return err; 1832 } 1833 1834#if 0 /* for debug purposes */ 1835 { 1836 snd_output_t *out; 1837 snd_output_stdio_attach(&out, stderr, 0); 1838 snd_config_save(sconf, out); 1839 snd_output_close(out); 1840 } 1841#endif 1842 1843 if (snd_config_search(sconf, "slave", &pcm_conf) >= 0) { 1844 if (snd_config_search(pcm_conf, "pcm", &pcm_conf) >= 0) { 1845 return _snd_pcm_direct_get_slave_ipc_offset(root, 1846 pcm_conf, 1847 direction, 1848 hop + 1); 1849 } else { 1850 if (snd_config_get_string(pcm_conf, &str) >= 0 && 1851 snd_config_search_definition(root, "pcm_slave", 1852 str, &pcm_conf) >= 0) { 1853 if (snd_config_search(pcm_conf, "pcm", 1854 &pcm_conf2) >= 0) { 1855 err = 1856 _snd_pcm_direct_get_slave_ipc_offset( 1857 root, pcm_conf2, direction, hop + 1); 1858 snd_config_delete(pcm_conf); 1859 return err; 1860 } 1861 snd_config_delete(pcm_conf); 1862 } 1863 } 1864 } 1865 1866 snd_config_for_each(i, next, sconf) { 1867 snd_config_t *n = snd_config_iterator_entry(i); 1868 const char *id, *str; 1869 if (snd_config_get_id(n, &id) < 0) 1870 continue; 1871 if (strcmp(id, "type") == 0) { 1872 err = snd_config_get_string(n, &str); 1873 if (err < 0) { 1874 SNDERR("Invalid value for PCM type definition"); 1875 return -EINVAL; 1876 } 1877 if (strcmp(str, "hw")) { 1878 SNDERR("Invalid type '%s' for slave PCM", str); 1879 return -EINVAL; 1880 } 1881 continue; 1882 } 1883 if (strcmp(id, "card") == 0) { 1884 err = snd_config_get_card(n); 1885 if (err < 0) 1886 return err; 1887 card = err; 1888 continue; 1889 } 1890 if (strcmp(id, "device") == 0) { 1891 err = snd_config_get_integer(n, &device); 1892 if (err < 0) { 1893 SNDERR("Invalid type for %s", id); 1894 return err; 1895 } 1896 continue; 1897 } 1898 if (strcmp(id, "subdevice") == 0) { 1899 err = snd_config_get_integer(n, &subdevice); 1900 if (err < 0) { 1901 SNDERR("Invalid type for %s", id); 1902 return err; 1903 } 1904 continue; 1905 } 1906 } 1907 if (device < 0) 1908 device = 0; 1909 if (subdevice < 0) 1910 subdevice = 0; 1911 return (direction << 1) + (device << 2) + (subdevice << 8) + (card << 12); 1912} 1913 1914static int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root, 1915 snd_config_t *sconf, 1916 int direction) 1917{ 1918 return _snd_pcm_direct_get_slave_ipc_offset(root, sconf, direction, 0); 1919} 1920 1921int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf, 1922 int stream, struct snd_pcm_direct_open_conf *rec) 1923{ 1924 snd_config_iterator_t i, next; 1925 int ipc_key_add_uid = 0; 1926 snd_config_t *n; 1927 int err; 1928 1929 rec->slave = NULL; 1930 rec->bindings = NULL; 1931 rec->ipc_key = 0; 1932 rec->ipc_perm = 0600; 1933 rec->ipc_gid = -1; 1934 rec->slowptr = 1; 1935 rec->max_periods = 0; 1936 rec->var_periodsize = 0; 1937#ifdef LOCKLESS_DMIX_DEFAULT 1938 rec->direct_memory_access = 1; 1939#else 1940 rec->direct_memory_access = 0; 1941#endif 1942 rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO; 1943 rec->tstamp_type = -1; 1944 1945 /* read defaults */ 1946 if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) { 1947 long val; 1948 err = snd_config_get_integer(n, &val); 1949 if (err >= 0) 1950 rec->max_periods = val; 1951 } 1952 1953 snd_config_for_each(i, next, conf) { 1954 const char *id; 1955 n = snd_config_iterator_entry(i); 1956 if (snd_config_get_id(n, &id) < 0) 1957 continue; 1958 if (snd_pcm_conf_generic_id(id)) 1959 continue; 1960 if (strcmp(id, "ipc_key") == 0) { 1961 long key; 1962 err = snd_config_get_integer(n, &key); 1963 if (err < 0) { 1964 SNDERR("The field ipc_key must be an integer type"); 1965 1966 return err; 1967 } 1968 rec->ipc_key = key; 1969 continue; 1970 } 1971 if (strcmp(id, "ipc_perm") == 0) { 1972 long perm; 1973 err = snd_config_get_integer(n, &perm); 1974 if (err < 0) { 1975 SNDERR("Invalid type for %s", id); 1976 return err; 1977 } 1978 if ((perm & ~0777) != 0) { 1979 SNDERR("The field ipc_perm must be a valid file permission"); 1980 return -EINVAL; 1981 } 1982 rec->ipc_perm = perm; 1983 continue; 1984 } 1985 if (strcmp(id, "hw_ptr_alignment") == 0) { 1986 const char *str; 1987 err = snd_config_get_string(n, &str); 1988 if (err < 0) { 1989 SNDERR("Invalid type for %s", id); 1990 return -EINVAL; 1991 } 1992 if (strcmp(str, "no") == 0 || strcmp(str, "off") == 0) 1993 rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_NO; 1994 else if (strcmp(str, "roundup") == 0) 1995 rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP; 1996 else if (strcmp(str, "rounddown") == 0) 1997 rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_ROUNDDOWN; 1998 else if (strcmp(str, "auto") == 0) 1999 rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO; 2000 else { 2001 SNDERR("The field hw_ptr_alignment is invalid : %s", str); 2002 return -EINVAL; 2003 } 2004 2005 continue; 2006 } 2007 if (strcmp(id, "tstamp_type") == 0) { 2008 const char *str; 2009 err = snd_config_get_string(n, &str); 2010 if (err < 0) { 2011 SNDERR("Invalid type for %s", id); 2012 return -EINVAL; 2013 } 2014 if (strcmp(str, "default") == 0) 2015 rec->tstamp_type = -1; 2016 else if (strcmp(str, "gettimeofday") == 0) 2017 rec->tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY; 2018 else if (strcmp(str, "monotonic") == 0) 2019 rec->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC; 2020 else if (strcmp(str, "monotonic_raw") == 0) 2021 rec->tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW; 2022 else { 2023 SNDERR("The field tstamp_type is invalid : %s", str); 2024 return -EINVAL; 2025 } 2026 continue; 2027 } 2028 if (strcmp(id, "ipc_gid") == 0) { 2029 char *group; 2030 char *endp; 2031 err = snd_config_get_ascii(n, &group); 2032 if (err < 0) { 2033 SNDERR("The field ipc_gid must be a valid group"); 2034 return err; 2035 } 2036 if (! *group) { 2037 rec->ipc_gid = -1; 2038 free(group); 2039 continue; 2040 } 2041 if (isdigit(*group) == 0) { 2042 long clen = sysconf(_SC_GETGR_R_SIZE_MAX); 2043 size_t len = (clen == -1) ? 1024 : (size_t)clen; 2044 struct group grp, *pgrp; 2045 char *buffer = (char *)malloc(len); 2046 if (buffer == NULL) 2047 return -ENOMEM; 2048 int st = getgrnam_r(group, &grp, buffer, len, &pgrp); 2049 if (st != 0 || !pgrp) { 2050 SNDERR("The field ipc_gid must be a valid group (create group %s)", group); 2051 free(buffer); 2052 return -EINVAL; 2053 } 2054 rec->ipc_gid = pgrp->gr_gid; 2055 free(buffer); 2056 } else { 2057 rec->ipc_gid = strtol(group, &endp, 10); 2058 } 2059 free(group); 2060 continue; 2061 } 2062 if (strcmp(id, "ipc_key_add_uid") == 0) { 2063 if ((err = snd_config_get_bool(n)) < 0) { 2064 SNDERR("The field ipc_key_add_uid must be a boolean type"); 2065 return err; 2066 } 2067 ipc_key_add_uid = err; 2068 continue; 2069 } 2070 if (strcmp(id, "slave") == 0) { 2071 rec->slave = n; 2072 continue; 2073 } 2074 if (strcmp(id, "bindings") == 0) { 2075 rec->bindings = n; 2076 continue; 2077 } 2078 if (strcmp(id, "slowptr") == 0) { 2079 err = snd_config_get_bool(n); 2080 if (err < 0) 2081 return err; 2082 rec->slowptr = err; 2083 continue; 2084 } 2085 if (strcmp(id, "max_periods") == 0) { 2086 long val; 2087 err = snd_config_get_integer(n, &val); 2088 if (err < 0) 2089 return err; 2090 rec->max_periods = val; 2091 continue; 2092 } 2093 if (strcmp(id, "var_periodsize") == 0) { 2094 err = snd_config_get_bool(n); 2095 if (err < 0) 2096 return err; 2097 rec->var_periodsize = err; 2098 continue; 2099 } 2100 if (strcmp(id, "direct_memory_access") == 0) { 2101 err = snd_config_get_bool(n); 2102 if (err < 0) 2103 return err; 2104 rec->direct_memory_access = err; 2105 continue; 2106 } 2107 SNDERR("Unknown field %s", id); 2108 return -EINVAL; 2109 } 2110 if (!rec->slave) { 2111 SNDERR("slave is not defined"); 2112 return -EINVAL; 2113 } 2114 if (!rec->ipc_key) { 2115 SNDERR("Unique IPC key is not defined"); 2116 return -EINVAL; 2117 } 2118 if (ipc_key_add_uid) 2119 rec->ipc_key += getuid(); 2120 err = snd_pcm_direct_get_slave_ipc_offset(root, conf, stream); 2121 if (err < 0) 2122 return err; 2123 rec->ipc_key += err; 2124 2125 return 0; 2126} 2127 2128void snd_pcm_direct_reset_slave_ptr(snd_pcm_t *pcm, snd_pcm_direct_t *dmix, 2129 snd_pcm_uframes_t hw_ptr) 2130{ 2131 dmix->slave_appl_ptr = dmix->slave_hw_ptr = hw_ptr; 2132 if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDUP || 2133 (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && 2134 pcm->buffer_size <= pcm->period_size * 2)) 2135 dmix->slave_appl_ptr = 2136 ((dmix->slave_appl_ptr + dmix->slave_period_size - 1) / 2137 dmix->slave_period_size) * dmix->slave_period_size; 2138 else if (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_ROUNDDOWN || 2139 (dmix->hw_ptr_alignment == SND_PCM_HW_PTR_ALIGNMENT_AUTO && 2140 ((dmix->slave_period_size * SEC_TO_MS) / pcm->rate) < LOW_LATENCY_PERIOD_TIME)) 2141 dmix->slave_appl_ptr = dmix->slave_hw_ptr = 2142 ((dmix->slave_hw_ptr / dmix->slave_period_size) * 2143 dmix->slave_period_size); 2144} 2145 2146int _snd_pcm_direct_new(snd_pcm_t **pcmp, snd_pcm_direct_t **_dmix, int type, 2147 const char *name, struct snd_pcm_direct_open_conf *opts, 2148 struct slave_params *params, snd_pcm_stream_t stream, int mode) 2149{ 2150 snd_pcm_direct_t *dmix; 2151 int fail_sem_loop = 10; 2152 int ret; 2153 2154 dmix = calloc(1, sizeof(snd_pcm_direct_t)); 2155 if (!dmix) 2156 return -ENOMEM; 2157 2158 ret = snd_pcm_direct_parse_bindings(dmix, params, opts->bindings); 2159 if (ret < 0) { 2160 free(dmix); 2161 return ret; 2162 } 2163 2164 dmix->ipc_key = opts->ipc_key; 2165 dmix->ipc_perm = opts->ipc_perm; 2166 dmix->ipc_gid = opts->ipc_gid; 2167 dmix->tstamp_type = opts->tstamp_type; 2168 dmix->semid = -1; 2169 dmix->shmid = -1; 2170 dmix->shmptr = (void *) -1; 2171 dmix->type = type; 2172 2173 ret = snd_pcm_new(pcmp, type, name, stream, mode); 2174 if (ret < 0) 2175 goto _err_nosem; 2176 2177 while (1) { 2178 ret = snd_pcm_direct_semaphore_create_or_connect(dmix); 2179 if (ret < 0) { 2180 SNDERR("unable to create IPC semaphore"); 2181 goto _err_nosem_free; 2182 } 2183 ret = snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); 2184 if (ret < 0) { 2185 snd_pcm_direct_semaphore_discard(dmix); 2186 if (--fail_sem_loop <= 0) 2187 goto _err_nosem_free; 2188 continue; 2189 } 2190 break; 2191 } 2192 2193 ret = snd_pcm_direct_shm_create_or_connect(dmix); 2194 if (ret < 0) { 2195 SNDERR("unable to create IPC shm instance"); 2196 snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); 2197 goto _err_nosem_free; 2198 } else { 2199 *_dmix = dmix; 2200 } 2201 2202 return ret; 2203_err_nosem_free: 2204 snd_pcm_free(*pcmp); 2205 *pcmp = NULL; 2206_err_nosem: 2207 free(dmix->bindings); 2208 free(dmix); 2209 return ret; 2210} 2211