Home | History | Annotate | Download | only in pcm
      1 /*
      2  *  PCM - Direct Stream Mixing
      3  *  Copyright (c) 2003 by Jaroslav Kysela <perex (at) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
     19  *
     20  */
     21 
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <stddef.h>
     25 #include <unistd.h>
     26 #include <signal.h>
     27 #include <string.h>
     28 #include <fcntl.h>
     29 #include <ctype.h>
     30 #include <grp.h>
     31 #include <sys/ioctl.h>
     32 #include <sys/mman.h>
     33 #include <sys/poll.h>
     34 #include <sys/shm.h>
     35 #include <sys/sem.h>
     36 #include <sys/wait.h>
     37 #include <sys/socket.h>
     38 #include <sys/stat.h>
     39 #include <sys/un.h>
     40 #include <sys/mman.h>
     41 #include "pcm_direct.h"
     42 
     43 /*
     44  *
     45  */
     46 
     47 union semun {
     48 	int              val;    /* Value for SETVAL */
     49 	struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
     50 	unsigned short  *array;  /* Array for GETALL, SETALL */
     51 	struct seminfo  *__buf;  /* Buffer for IPC_INFO (Linux specific) */
     52 };
     53 
     54 /*
     55  * FIXME:
     56  *  add possibility to use futexes here
     57  */
     58 
     59 int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix)
     60 {
     61 	union semun s;
     62 	struct semid_ds buf;
     63 	int i;
     64 
     65 	dmix->semid = semget(dmix->ipc_key, DIRECT_IPC_SEMS,
     66 			     IPC_CREAT | dmix->ipc_perm);
     67 	if (dmix->semid < 0)
     68 		return -errno;
     69 	if (dmix->ipc_gid < 0)
     70 		return 0;
     71 	for (i = 0; i < DIRECT_IPC_SEMS; i++) {
     72 		s.buf = &buf;
     73 		if (semctl(dmix->semid, i, IPC_STAT, s) < 0) {
     74 			int err = -errno;
     75 			snd_pcm_direct_semaphore_discard(dmix);
     76 			return err;
     77 		}
     78 		buf.sem_perm.gid = dmix->ipc_gid;
     79 		s.buf = &buf;
     80 		semctl(dmix->semid, i, IPC_SET, s);
     81 	}
     82 	return 0;
     83 }
     84 
     85 #define SND_PCM_DIRECT_MAGIC	(0xa15ad300 + sizeof(snd_pcm_direct_share_t))
     86 
     87 /*
     88  *  global shared memory area
     89  */
     90 
     91 int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix)
     92 {
     93 	struct shmid_ds buf;
     94 	int tmpid, err;
     95 
     96 retryget:
     97 	dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t),
     98 			     IPC_CREAT | dmix->ipc_perm);
     99 	err = -errno;
    100 	if (dmix->shmid < 0){
    101 		if (errno == EINVAL)
    102 		if ((tmpid = shmget(dmix->ipc_key, 0, dmix->ipc_perm)) != -1)
    103 		if (!shmctl(tmpid, IPC_STAT, &buf))
    104 		if (!buf.shm_nattch)
    105 	    	/* no users so destroy the segment */
    106 		if (!shmctl(tmpid, IPC_RMID, NULL))
    107 		    goto retryget;
    108 		return err;
    109 	}
    110 	dmix->shmptr = shmat(dmix->shmid, 0, 0);
    111 	if (dmix->shmptr == (void *) -1) {
    112 		err = -errno;
    113 		snd_pcm_direct_shm_discard(dmix);
    114 		return err;
    115 	}
    116 	mlock(dmix->shmptr, sizeof(snd_pcm_direct_share_t));
    117 	if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
    118 		err = -errno;
    119 		snd_pcm_direct_shm_discard(dmix);
    120 		return err;
    121 	}
    122 	if (buf.shm_nattch == 1) {	/* we're the first user, clear the segment */
    123 		memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t));
    124 		if (dmix->ipc_gid >= 0) {
    125 			buf.shm_perm.gid = dmix->ipc_gid;
    126 			shmctl(dmix->shmid, IPC_SET, &buf);
    127 		}
    128 		dmix->shmptr->magic = SND_PCM_DIRECT_MAGIC;
    129 		return 1;
    130 	} else {
    131 		if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {
    132 			snd_pcm_direct_shm_discard(dmix);
    133 			return -EINVAL;
    134 		}
    135 	}
    136 	return 0;
    137 }
    138 
    139 /* discard shared memory */
    140 /*
    141  * Define snd_* functions to be used in server.
    142  * Since objects referred in a plugin can be released dynamically, a forked
    143  * server should have statically linked functions.
    144  * (e.g. Novell bugzilla #105772)
    145  */
    146 static int _snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix)
    147 {
    148 	struct shmid_ds buf;
    149 	int ret = 0;
    150 
    151 	if (dmix->shmid < 0)
    152 		return -EINVAL;
    153 	if (dmix->shmptr != (void *) -1 && shmdt(dmix->shmptr) < 0)
    154 		return -errno;
    155 	dmix->shmptr = (void *) -1;
    156 	if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0)
    157 		return -errno;
    158 	if (buf.shm_nattch == 0) {	/* we're the last user, destroy the segment */
    159 		if (shmctl(dmix->shmid, IPC_RMID, NULL) < 0)
    160 			return -errno;
    161 		ret = 1;
    162 	}
    163 	dmix->shmid = -1;
    164 	return ret;
    165 }
    166 
    167 /* ... and an exported version */
    168 int snd_pcm_direct_shm_discard(snd_pcm_direct_t *dmix)
    169 {
    170 	return _snd_pcm_direct_shm_discard(dmix);
    171 }
    172 
    173 /*
    174  *  server side
    175  */
    176 
    177 static int get_tmp_name(char *filename, size_t size)
    178 {
    179 	struct timeval tv;
    180 
    181 	gettimeofday(&tv, NULL);
    182 	snprintf(filename, size, TMPDIR "/alsa-dmix-%i-%li-%li", (int)getpid(), (long)tv.tv_sec, (long)tv.tv_usec);
    183 	filename[size-1] = '\0';
    184 	return 0;
    185 }
    186 
    187 static int make_local_socket(const char *filename, int server, mode_t ipc_perm, int ipc_gid)
    188 {
    189 	size_t l = strlen(filename);
    190 	size_t size = offsetof(struct sockaddr_un, sun_path) + l;
    191 	struct sockaddr_un *addr = alloca(size);
    192 	int sock;
    193 
    194 	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
    195 	if (sock < 0) {
    196 		int result = -errno;
    197 		SYSERR("socket failed");
    198 		return result;
    199 	}
    200 
    201 	if (server)
    202 		unlink(filename);
    203 	memset(addr, 0, size); /* make valgrind happy */
    204 	addr->sun_family = AF_LOCAL;
    205 	memcpy(addr->sun_path, filename, l);
    206 
    207 	if (server) {
    208 		if (bind(sock, (struct sockaddr *) addr, size) < 0) {
    209 			int result = -errno;
    210 			SYSERR("bind failed: %s", filename);
    211 			close(sock);
    212 			return result;
    213 		} else {
    214 			if (chmod(filename, ipc_perm) < 0) {
    215 				int result = -errno;
    216 				SYSERR("chmod failed: %s", filename);
    217 				close(sock);
    218 				unlink(filename);
    219 				return result;
    220 			}
    221 			if (chown(filename, -1, ipc_gid) < 0) {
    222 #if 0 /* it's not fatal */
    223 				int result = -errno;
    224 				SYSERR("chown failed: %s", filename);
    225 				close(sock);
    226 				unlink(filename);
    227 				return result;
    228 #endif
    229 			}
    230 		}
    231 	} else {
    232 		if (connect(sock, (struct sockaddr *) addr, size) < 0) {
    233 			int result = -errno;
    234 			SYSERR("connect failed: %s", filename);
    235 			close(sock);
    236 			return result;
    237 		}
    238 	}
    239 	return sock;
    240 }
    241 
    242 #if 0
    243 #define SERVER_JOB_DEBUG
    244 #define server_printf(fmt, args...) printf(fmt, ##args)
    245 #else
    246 #undef SERVER_JOB_DEBUG
    247 #define server_printf(fmt, args...) /* nothing */
    248 #endif
    249 
    250 static snd_pcm_direct_t *server_job_dmix;
    251 
    252 static void server_cleanup(snd_pcm_direct_t *dmix)
    253 {
    254 	close(dmix->server_fd);
    255 	close(dmix->hw_fd);
    256 	if (dmix->server_free)
    257 		dmix->server_free(dmix);
    258 	unlink(dmix->shmptr->socket_name);
    259 	_snd_pcm_direct_shm_discard(dmix);
    260 	snd_pcm_direct_semaphore_discard(dmix);
    261 }
    262 
    263 static void server_job_signal(int sig ATTRIBUTE_UNUSED)
    264 {
    265 	snd_pcm_direct_semaphore_down(server_job_dmix, DIRECT_IPC_SEM_CLIENT);
    266 	server_cleanup(server_job_dmix);
    267 	server_printf("DIRECT SERVER EXIT - SIGNAL\n");
    268 	_exit(EXIT_SUCCESS);
    269 }
    270 
    271 /* This is a copy from ../socket.c, provided here only for a server job
    272  * (see the comment above)
    273  */
    274 static int _snd_send_fd(int sock, void *data, size_t len, int fd)
    275 {
    276 	int ret;
    277 	size_t cmsg_len = CMSG_LEN(sizeof(int));
    278 	struct cmsghdr *cmsg = alloca(cmsg_len);
    279 	int *fds = (int *) CMSG_DATA(cmsg);
    280 	struct msghdr msghdr;
    281 	struct iovec vec;
    282 
    283 	vec.iov_base = (void *)&data;
    284 	vec.iov_len = len;
    285 
    286 	cmsg->cmsg_len = cmsg_len;
    287 	cmsg->cmsg_level = SOL_SOCKET;
    288 	cmsg->cmsg_type = SCM_RIGHTS;
    289 	*fds = fd;
    290 
    291 	msghdr.msg_name = NULL;
    292 	msghdr.msg_namelen = 0;
    293 	msghdr.msg_iov = &vec;
    294  	msghdr.msg_iovlen = 1;
    295 	msghdr.msg_control = cmsg;
    296 	msghdr.msg_controllen = cmsg_len;
    297 	msghdr.msg_flags = 0;
    298 
    299 	ret = sendmsg(sock, &msghdr, 0 );
    300 	if (ret < 0)
    301 		return -errno;
    302 	return ret;
    303 }
    304 
    305 static void server_job(snd_pcm_direct_t *dmix)
    306 {
    307 	int ret, sck, i;
    308 	int max = 128, current = 0;
    309 	struct pollfd pfds[max + 1];
    310 
    311 	server_job_dmix = dmix;
    312 	/* don't allow to be killed */
    313 	signal(SIGHUP, server_job_signal);
    314 	signal(SIGQUIT, server_job_signal);
    315 	signal(SIGTERM, server_job_signal);
    316 	signal(SIGKILL, server_job_signal);
    317 	/* close all files to free resources */
    318 	i = sysconf(_SC_OPEN_MAX);
    319 #ifdef SERVER_JOB_DEBUG
    320 	while (--i >= 3) {
    321 #else
    322 	while (--i >= 0) {
    323 #endif
    324 		if (i != dmix->server_fd && i != dmix->hw_fd)
    325 			close(i);
    326 	}
    327 
    328 	/* detach from parent */
    329 	setsid();
    330 
    331 	pfds[0].fd = dmix->server_fd;
    332 	pfds[0].events = POLLIN | POLLERR | POLLHUP;
    333 
    334 	server_printf("DIRECT SERVER STARTED\n");
    335 	while (1) {
    336 		ret = poll(pfds, current + 1, 500);
    337 		server_printf("DIRECT SERVER: poll ret = %i, revents[0] = 0x%x, errno = %i\n", ret, pfds[0].revents, errno);
    338 		if (ret < 0) {
    339 			if (errno == EINTR)
    340 				continue;
    341 			/* some error */
    342 			break;
    343 		}
    344 		if (ret == 0 || (pfds[0].revents & (POLLERR | POLLHUP))) {	/* timeout or error? */
    345 			struct shmid_ds buf;
    346 			snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
    347 			if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) {
    348 				_snd_pcm_direct_shm_discard(dmix);
    349 				snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
    350 				continue;
    351 			}
    352 			server_printf("DIRECT SERVER: nattch = %i\n", (int)buf.shm_nattch);
    353 			if (buf.shm_nattch == 1)	/* server is the last user, exit */
    354 				break;
    355 			snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
    356 			continue;
    357 		}
    358 		if (pfds[0].revents & POLLIN) {
    359 			ret--;
    360 			sck = accept(dmix->server_fd, 0, 0);
    361 			if (sck >= 0) {
    362 				server_printf("DIRECT SERVER: new connection %i\n", sck);
    363 				if (current == max) {
    364 					close(sck);
    365 				} else {
    366 					unsigned char buf = 'A';
    367 					pfds[current+1].fd = sck;
    368 					pfds[current+1].events = POLLIN | POLLERR | POLLHUP;
    369 					_snd_send_fd(sck, &buf, 1, dmix->hw_fd);
    370 					server_printf("DIRECT SERVER: fd sent ok\n");
    371 					current++;
    372 				}
    373 			}
    374 		}
    375 		for (i = 0; i < current && ret > 0; i++) {
    376 			struct pollfd *pfd = &pfds[i+1];
    377 			unsigned char cmd;
    378 			server_printf("client %i revents = 0x%x\n", pfd->fd, pfd->revents);
    379 			if (pfd->revents & (POLLERR | POLLHUP)) {
    380 				ret--;
    381 				close(pfd->fd);
    382 				pfd->fd = -1;
    383 				continue;
    384 			}
    385 			if (!(pfd->revents & POLLIN))
    386 				continue;
    387 			ret--;
    388 			if (read(pfd->fd, &cmd, 1) == 1)
    389 				cmd = 0 /*process command */;
    390 		}
    391 		for (i = 0; i < current; i++) {
    392 			if (pfds[i+1].fd < 0) {
    393 				if (i + 1 != max)
    394 					memcpy(&pfds[i+1], &pfds[i+2], sizeof(struct pollfd) * (max - i - 1));
    395 				current--;
    396 			}
    397 		}
    398 	}
    399 	server_cleanup(dmix);
    400 	server_printf("DIRECT SERVER EXIT\n");
    401 #ifdef SERVER_JOB_DEBUG
    402 	close(0); close(1); close(2);
    403 #endif
    404 	_exit(EXIT_SUCCESS);
    405 }
    406 
    407 int snd_pcm_direct_server_create(snd_pcm_direct_t *dmix)
    408 {
    409 	int ret;
    410 
    411 	dmix->server_fd = -1;
    412 
    413 	ret = get_tmp_name(dmix->shmptr->socket_name, sizeof(dmix->shmptr->socket_name));
    414 	if (ret < 0)
    415 		return ret;
    416 
    417 	ret = make_local_socket(dmix->shmptr->socket_name, 1, dmix->ipc_perm, dmix->ipc_gid);
    418 	if (ret < 0)
    419 		return ret;
    420 	dmix->server_fd = ret;
    421 
    422 	ret = listen(dmix->server_fd, 4);
    423 	if (ret < 0) {
    424 		close(dmix->server_fd);
    425 		return ret;
    426 	}
    427 
    428 	ret = fork();
    429 	if (ret < 0) {
    430 		close(dmix->server_fd);
    431 		return ret;
    432 	} else if (ret == 0) {
    433 		ret = fork();
    434 		if (ret == 0)
    435 			server_job(dmix);
    436 		_exit(EXIT_SUCCESS);
    437 	} else {
    438 		waitpid(ret, NULL, 0);
    439 	}
    440 	dmix->server_pid = ret;
    441 	dmix->server = 1;
    442 	return 0;
    443 }
    444 
    445 int snd_pcm_direct_server_discard(snd_pcm_direct_t *dmix)
    446 {
    447 	if (dmix->server) {
    448 		//kill(dmix->server_pid, SIGTERM);
    449 		//waitpid(dmix->server_pid, NULL, 0);
    450 		dmix->server_pid = (pid_t)-1;
    451 	}
    452 	if (dmix->server_fd > 0) {
    453 		close(dmix->server_fd);
    454 		dmix->server_fd = -1;
    455 	}
    456 	dmix->server = 0;
    457 	return 0;
    458 }
    459 
    460 /*
    461  *  client side
    462  */
    463 
    464 int snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix)
    465 {
    466 	int ret;
    467 	unsigned char buf;
    468 
    469 	ret = make_local_socket(dmix->shmptr->socket_name, 0, -1, -1);
    470 	if (ret < 0)
    471 		return ret;
    472 	dmix->comm_fd = ret;
    473 
    474 	ret = snd_receive_fd(dmix->comm_fd, &buf, 1, &dmix->hw_fd);
    475 	if (ret < 1 || buf != 'A') {
    476 		close(dmix->comm_fd);
    477 		dmix->comm_fd = -1;
    478 		return ret;
    479 	}
    480 
    481 	dmix->client = 1;
    482 	return 0;
    483 }
    484 
    485 int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix)
    486 {
    487 	if (dmix->client) {
    488 		close(dmix->comm_fd);
    489 		dmix->comm_fd = -1;
    490 	}
    491 	return 0;
    492 }
    493 
    494 /*
    495  *  plugin helpers
    496  */
    497 
    498 int snd_pcm_direct_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
    499 {
    500 	/* value is cached for us in pcm->mode (SND_PCM_NONBLOCK flag) */
    501 	return 0;
    502 }
    503 
    504 int snd_pcm_direct_async(snd_pcm_t *pcm, int sig, pid_t pid)
    505 {
    506 	snd_pcm_direct_t *dmix = pcm->private_data;
    507 	return snd_timer_async(dmix->timer, sig, pid);
    508 }
    509 
    510 /* empty the timer read queue */
    511 void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
    512 {
    513 	if (dmix->timer_need_poll) {
    514 		while (poll(&dmix->timer_fd, 1, 0) > 0) {
    515 			/* we don't need the value */
    516 			if (dmix->tread) {
    517 				snd_timer_tread_t rbuf[4];
    518 				snd_timer_read(dmix->timer, rbuf, sizeof(rbuf));
    519 			} else {
    520 				snd_timer_read_t rbuf;
    521 				snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf));
    522 			}
    523 		}
    524 	} else {
    525 		if (dmix->tread) {
    526 			snd_timer_tread_t rbuf[4];
    527 			int len;
    528 			while ((len = snd_timer_read(dmix->timer, rbuf,
    529 						     sizeof(rbuf))) > 0 &&
    530 			       len != sizeof(rbuf[0]))
    531 				;
    532 		} else {
    533 			snd_timer_read_t rbuf;
    534 			while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0)
    535 				;
    536 		}
    537 	}
    538 }
    539 
    540 int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
    541 {
    542 	snd_timer_stop(dmix->timer);
    543 	snd_pcm_direct_clear_timer_queue(dmix);
    544 	return 0;
    545 }
    546 
    547 int snd_pcm_direct_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
    548 {
    549 	snd_pcm_direct_t *dmix = pcm->private_data;
    550 	unsigned short events;
    551 	int empty = 0;
    552 
    553 	assert(pfds && nfds == 1 && revents);
    554 	events = pfds[0].revents;
    555 	if (events & POLLIN) {
    556 		snd_pcm_uframes_t avail;
    557 		snd_pcm_avail_update(pcm);
    558 		if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
    559 			events |= POLLOUT;
    560 			events &= ~POLLIN;
    561 			avail = snd_pcm_mmap_playback_avail(pcm);
    562 		} else {
    563 			avail = snd_pcm_mmap_capture_avail(pcm);
    564 		}
    565 		empty = avail < pcm->avail_min;
    566 	}
    567 	switch (snd_pcm_state(dmix->spcm)) {
    568 	case SND_PCM_STATE_XRUN:
    569 	case SND_PCM_STATE_SUSPENDED:
    570 		events |= POLLERR;
    571 		break;
    572 	default:
    573 		if (empty) {
    574 			snd_pcm_direct_clear_timer_queue(dmix);
    575 			events &= ~(POLLOUT|POLLIN);
    576 			/* additional check */
    577 			switch (snd_pcm_state(pcm)) {
    578 			case SND_PCM_STATE_XRUN:
    579 			case SND_PCM_STATE_SUSPENDED:
    580 				events |= POLLERR;
    581 				break;
    582 			default:
    583 				break;
    584 			}
    585 		}
    586 		break;
    587 	}
    588 	*revents = events;
    589 	return 0;
    590 }
    591 
    592 int snd_pcm_direct_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
    593 {
    594 	// snd_pcm_direct_t *dmix = pcm->private_data;
    595 
    596 	memset(info, 0, sizeof(*info));
    597 	info->stream = pcm->stream;
    598 	info->card = -1;
    599 	/* FIXME: fill this with something more useful: we know the hardware name */
    600 	if (pcm->name) {
    601 		strncpy((char *)info->id, pcm->name, sizeof(info->id));
    602 		strncpy((char *)info->name, pcm->name, sizeof(info->name));
    603 		strncpy((char *)info->subname, pcm->name, sizeof(info->subname));
    604 	}
    605 	info->subdevices_count = 1;
    606 	return 0;
    607 }
    608 
    609 static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params,
    610 					snd_pcm_hw_param_t var)
    611 {
    612 	return &params->masks[var - SND_PCM_HW_PARAM_FIRST_MASK];
    613 }
    614 
    615 static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params,
    616 						snd_pcm_hw_param_t var)
    617 {
    618 	return &params->intervals[var - SND_PCM_HW_PARAM_FIRST_INTERVAL];
    619 }
    620 
    621 static int hw_param_interval_refine_one(snd_pcm_hw_params_t *params,
    622 					snd_pcm_hw_param_t var,
    623 					snd_interval_t *src)
    624 {
    625 	snd_interval_t *i;
    626 
    627 	if (!(params->rmask & (1<<var)))	/* nothing to do? */
    628 		return 0;
    629 	i = hw_param_interval(params, var);
    630 	if (snd_interval_empty(i)) {
    631 		SNDERR("dshare interval %i empty?", (int)var);
    632 		return -EINVAL;
    633 	}
    634 	if (snd_interval_refine(i, src))
    635 		params->cmask |= 1<<var;
    636 	return 0;
    637 }
    638 
    639 static int hw_param_interval_refine_minmax(snd_pcm_hw_params_t *params,
    640 					   snd_pcm_hw_param_t var,
    641 					   unsigned int imin,
    642 					   unsigned int imax)
    643 {
    644 	snd_interval_t t;
    645 
    646 	memset(&t, 0, sizeof(t));
    647 	snd_interval_set_minmax(&t, imin, imax);
    648 	t.integer = 1;
    649 	return hw_param_interval_refine_one(params, var, &t);
    650 }
    651 
    652 #undef REFINE_DEBUG
    653 
    654 int snd_pcm_direct_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
    655 {
    656 	snd_pcm_direct_t *dshare = pcm->private_data;
    657 	static const snd_mask_t access = { .bits = {
    658 					(1<<SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) |
    659 					(1<<SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) |
    660 					(1<<SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
    661 					(1<<SNDRV_PCM_ACCESS_RW_NONINTERLEAVED),
    662 					0, 0, 0 } };
    663 	int err;
    664 
    665 #ifdef REFINE_DEBUG
    666 	snd_output_t *log;
    667 	snd_output_stdio_attach(&log, stderr, 0);
    668 	snd_output_puts(log, "DMIX REFINE (begin):\n");
    669 	snd_pcm_hw_params_dump(params, log);
    670 #endif
    671 	if (params->rmask & (1<<SND_PCM_HW_PARAM_ACCESS)) {
    672 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS))) {
    673 			SNDERR("dshare access mask empty?");
    674 			return -EINVAL;
    675 		}
    676 		if (snd_mask_refine(hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS), &access))
    677 			params->cmask |= 1<<SND_PCM_HW_PARAM_ACCESS;
    678 	}
    679 	if (params->rmask & (1<<SND_PCM_HW_PARAM_FORMAT)) {
    680 		if (snd_mask_empty(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT))) {
    681 			SNDERR("dshare format mask empty?");
    682 			return -EINVAL;
    683 		}
    684 		if (snd_mask_refine_set(hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT),
    685 					dshare->shmptr->hw.format))
    686 			params->cmask |= 1<<SND_PCM_HW_PARAM_FORMAT;
    687 	}
    688 	//snd_mask_none(hw_param_mask(params, SND_PCM_HW_PARAM_SUBFORMAT));
    689 	if (params->rmask & (1<<SND_PCM_HW_PARAM_CHANNELS)) {
    690 		if (snd_interval_empty(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS))) {
    691 			SNDERR("dshare channels mask empty?");
    692 			return -EINVAL;
    693 		}
    694 		err = snd_interval_refine_set(hw_param_interval(params, SND_PCM_HW_PARAM_CHANNELS), dshare->channels);
    695 		if (err < 0)
    696 			return err;
    697 	}
    698 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_RATE,
    699 					   &dshare->shmptr->hw.rate);
    700 	if (err < 0)
    701 		return err;
    702 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_SIZE,
    703 					   &dshare->shmptr->hw.period_size);
    704 	if (err < 0)
    705 		return err;
    706 	err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_PERIOD_TIME,
    707 					   &dshare->shmptr->hw.period_time);
    708 	if (err < 0)
    709 		return err;
    710 	if (dshare->max_periods < 0) {
    711 		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
    712 						   &dshare->shmptr->hw.buffer_size);
    713 		if (err < 0)
    714 			return err;
    715 		err = hw_param_interval_refine_one(params, SND_PCM_HW_PARAM_BUFFER_TIME,
    716 						   &dshare->shmptr->hw.buffer_time);
    717 		if (err < 0)
    718 			return err;
    719 	} else if (params->rmask & ((1<<SND_PCM_HW_PARAM_PERIODS)|
    720 				    (1<<SND_PCM_HW_PARAM_BUFFER_BYTES)|
    721 				    (1<<SND_PCM_HW_PARAM_BUFFER_SIZE)|
    722 				    (1<<SND_PCM_HW_PARAM_BUFFER_TIME))) {
    723 		int changed;
    724 		unsigned int max_periods = dshare->max_periods;
    725 		if (max_periods < 2)
    726 			max_periods = dshare->slave_buffer_size / dshare->slave_period_size;
    727 		do {
    728 			changed = 0;
    729 			err = hw_param_interval_refine_minmax(params, SND_PCM_HW_PARAM_PERIODS,
    730 							      2, max_periods);
    731 			if (err < 0)
    732 				return err;
    733 			changed |= err;
    734 			err = snd_pcm_hw_refine_soft(pcm, params);
    735 			if (err < 0)
    736 				return err;
    737 			changed |= err;
    738 		} while (changed);
    739 	}
    740 	params->info = dshare->shmptr->s.info;
    741 #ifdef REFINE_DEBUG
    742 	snd_output_puts(log, "DMIX REFINE (end):\n");
    743 	snd_pcm_hw_params_dump(params, log);
    744 	snd_output_close(log);
    745 #endif
    746 	return 0;
    747 }
    748 
    749 int snd_pcm_direct_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
    750 {
    751 	snd_pcm_direct_t *dmix = pcm->private_data;
    752 
    753 	params->info = dmix->shmptr->s.info;
    754 	params->rate_num = dmix->shmptr->s.rate;
    755 	params->rate_den = 1;
    756 	params->fifo_size = 0;
    757 	params->msbits = dmix->shmptr->s.msbits;
    758 	return 0;
    759 }
    760 
    761 int snd_pcm_direct_hw_free(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
    762 {
    763 	/* values are cached in the pcm structure */
    764 	return 0;
    765 }
    766 
    767 int snd_pcm_direct_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t * params ATTRIBUTE_UNUSED)
    768 {
    769 	/* values are cached in the pcm structure */
    770 	return 0;
    771 }
    772 
    773 int snd_pcm_direct_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
    774 {
    775         return snd_pcm_channel_info_shm(pcm, info, -1);
    776 }
    777 
    778 int snd_pcm_direct_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
    779 {
    780 	return 0;
    781 }
    782 
    783 int snd_pcm_direct_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
    784 {
    785 	return 0;
    786 }
    787 
    788 int snd_pcm_direct_resume(snd_pcm_t *pcm)
    789 {
    790 	snd_pcm_direct_t *dmix = pcm->private_data;
    791 	int err;
    792 
    793 	snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
    794 	err = snd_pcm_resume(dmix->spcm);
    795 	if (err == -ENOSYS) {
    796 		/* FIXME: error handling? */
    797 		snd_pcm_prepare(dmix->spcm);
    798 		snd_pcm_start(dmix->spcm);
    799 		err = 0;
    800 	}
    801 	snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
    802 	return err;
    803 }
    804 
    805 #define COPY_SLAVE(field) (dmix->shmptr->s.field = spcm->field)
    806 
    807 /* copy the slave setting */
    808 static void save_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
    809 {
    810 	spcm->info &= ~SND_PCM_INFO_PAUSE;
    811 
    812 	COPY_SLAVE(access);
    813 	COPY_SLAVE(format);
    814 	COPY_SLAVE(subformat);
    815 	COPY_SLAVE(channels);
    816 	COPY_SLAVE(rate);
    817 	COPY_SLAVE(period_size);
    818 	COPY_SLAVE(period_time);
    819 	COPY_SLAVE(periods);
    820 	COPY_SLAVE(tstamp_mode);
    821 	COPY_SLAVE(period_step);
    822 	COPY_SLAVE(avail_min);
    823 	COPY_SLAVE(start_threshold);
    824 	COPY_SLAVE(stop_threshold);
    825 	COPY_SLAVE(silence_threshold);
    826 	COPY_SLAVE(silence_size);
    827 	COPY_SLAVE(boundary);
    828 	COPY_SLAVE(info);
    829 	COPY_SLAVE(msbits);
    830 	COPY_SLAVE(rate_num);
    831 	COPY_SLAVE(rate_den);
    832 	COPY_SLAVE(hw_flags);
    833 	COPY_SLAVE(fifo_size);
    834 	COPY_SLAVE(buffer_size);
    835 	COPY_SLAVE(buffer_time);
    836 	COPY_SLAVE(sample_bits);
    837 	COPY_SLAVE(frame_bits);
    838 }
    839 
    840 #undef COPY_SLAVE
    841 
    842 /*
    843  * this function initializes hardware and starts playback operation with
    844  * no stop threshold (it operates all time without xrun checking)
    845  * also, the driver silences the unused ring buffer areas for us
    846  */
    847 int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params)
    848 {
    849 	snd_pcm_hw_params_t *hw_params;
    850 	snd_pcm_sw_params_t *sw_params;
    851 	int ret, buffer_is_not_initialized;
    852 	snd_pcm_uframes_t boundary;
    853 	struct pollfd fd;
    854 	int loops = 10;
    855 
    856 	snd_pcm_hw_params_alloca(&hw_params);
    857 	snd_pcm_sw_params_alloca(&sw_params);
    858 
    859       __again:
    860       	if (loops-- <= 0) {
    861       		SNDERR("unable to find a valid configuration for slave");
    862       		return -EINVAL;
    863       	}
    864 	ret = snd_pcm_hw_params_any(spcm, hw_params);
    865 	if (ret < 0) {
    866 		SNDERR("snd_pcm_hw_params_any failed");
    867 		return ret;
    868 	}
    869 	ret = snd_pcm_hw_params_set_access(spcm, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED);
    870 	if (ret < 0) {
    871 		ret = snd_pcm_hw_params_set_access(spcm, hw_params, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
    872 		if (ret < 0) {
    873 			SNDERR("slave plugin does not support mmap interleaved or mmap noninterleaved access");
    874 			return ret;
    875 		}
    876 	}
    877 	if (params->format == SND_PCM_FORMAT_UNKNOWN)
    878 		ret = -EINVAL;
    879 	else
    880 		ret = snd_pcm_hw_params_set_format(spcm, hw_params,
    881 						   params->format);
    882 	if (ret < 0) {
    883 		static const snd_pcm_format_t dmix_formats[] = {
    884 			SND_PCM_FORMAT_S32,
    885 			SND_PCM_FORMAT_S32 ^ SND_PCM_FORMAT_S32_LE ^ SND_PCM_FORMAT_S32_BE,
    886 			SND_PCM_FORMAT_S16,
    887 			SND_PCM_FORMAT_S16 ^ SND_PCM_FORMAT_S16_LE ^ SND_PCM_FORMAT_S16_BE,
    888 			SND_PCM_FORMAT_S24_3LE,
    889 			SND_PCM_FORMAT_U8,
    890 		};
    891 		snd_pcm_format_t format;
    892 		unsigned int i;
    893 
    894 		for (i = 0; i < sizeof dmix_formats / sizeof dmix_formats[0]; ++i) {
    895 			format = dmix_formats[i];
    896 			ret = snd_pcm_hw_params_set_format(spcm, hw_params, format);
    897 			if (ret >= 0)
    898 				break;
    899 		}
    900 		if (ret < 0 && dmix->type != SND_PCM_TYPE_DMIX) {
    901 			/* TODO: try to choose a good format */
    902 			ret = INTERNAL(snd_pcm_hw_params_set_format_first)(spcm, hw_params, &format);
    903 		}
    904 		if (ret < 0) {
    905 			SNDERR("requested or auto-format is not available");
    906 			return ret;
    907 		}
    908 		params->format = format;
    909 	}
    910 	ret = INTERNAL(snd_pcm_hw_params_set_channels_near)(spcm, hw_params, (unsigned int *)&params->channels);
    911 	if (ret < 0) {
    912 		SNDERR("requested count of channels is not available");
    913 		return ret;
    914 	}
    915 	ret = INTERNAL(snd_pcm_hw_params_set_rate_near)(spcm, hw_params, (unsigned int *)&params->rate, 0);
    916 	if (ret < 0) {
    917 		SNDERR("requested rate is not available");
    918 		return ret;
    919 	}
    920 
    921 	buffer_is_not_initialized = 0;
    922 	if (params->buffer_time > 0) {
    923 		ret = INTERNAL(snd_pcm_hw_params_set_buffer_time_near)(spcm, hw_params, (unsigned int *)&params->buffer_time, 0);
    924 		if (ret < 0) {
    925 			SNDERR("unable to set buffer time");
    926 			return ret;
    927 		}
    928 	} else if (params->buffer_size > 0) {
    929 		ret = INTERNAL(snd_pcm_hw_params_set_buffer_size_near)(spcm, hw_params, (snd_pcm_uframes_t *)&params->buffer_size);
    930 		if (ret < 0) {
    931 			SNDERR("unable to set buffer size");
    932 			return ret;
    933 		}
    934 	} else {
    935 		buffer_is_not_initialized = 1;
    936 	}
    937 
    938 	if (params->period_time > 0) {
    939 		ret = INTERNAL(snd_pcm_hw_params_set_period_time_near)(spcm, hw_params, (unsigned int *)&params->period_time, 0);
    940 		if (ret < 0) {
    941 			SNDERR("unable to set period_time");
    942 			return ret;
    943 		}
    944 	} else if (params->period_size > 0) {
    945 		ret = INTERNAL(snd_pcm_hw_params_set_period_size_near)(spcm, hw_params, (snd_pcm_uframes_t *)&params->period_size, 0);
    946 		if (ret < 0) {
    947 			SNDERR("unable to set period_size");
    948 			return ret;
    949 		}
    950 	}
    951 
    952 	if (buffer_is_not_initialized && params->periods > 0) {
    953 		unsigned int periods = params->periods;
    954 		ret = INTERNAL(snd_pcm_hw_params_set_periods_near)(spcm, hw_params, &params->periods, 0);
    955 		if (ret < 0) {
    956 			SNDERR("unable to set requested periods");
    957 			return ret;
    958 		}
    959 		if (params->periods == 1) {
    960 			params->periods = periods;
    961 			if (params->period_time > 0) {
    962 				params->period_time /= 2;
    963 				goto __again;
    964 			} else if (params->period_size > 0) {
    965 				params->period_size /= 2;
    966 				goto __again;
    967 			}
    968 			SNDERR("unable to use stream with periods == 1");
    969 			return ret;
    970 		}
    971 	}
    972 
    973 	ret = snd_pcm_hw_params(spcm, hw_params);
    974 	if (ret < 0) {
    975 		SNDERR("unable to install hw params");
    976 		return ret;
    977 	}
    978 
    979 	/* store some hw_params values to shared info */
    980 	dmix->shmptr->hw.format = snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT));
    981 	dmix->shmptr->hw.rate = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_RATE);
    982 	dmix->shmptr->hw.buffer_size = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_BUFFER_SIZE);
    983 	dmix->shmptr->hw.buffer_time = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_BUFFER_TIME);
    984 	dmix->shmptr->hw.period_size = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIOD_SIZE);
    985 	dmix->shmptr->hw.period_time = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIOD_TIME);
    986 	dmix->shmptr->hw.periods = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIODS);
    987 
    988 
    989 	ret = snd_pcm_sw_params_current(spcm, sw_params);
    990 	if (ret < 0) {
    991 		SNDERR("unable to get current sw_params");
    992 		return ret;
    993 	}
    994 
    995 	ret = snd_pcm_sw_params_get_boundary(sw_params, &boundary);
    996 	if (ret < 0) {
    997 		SNDERR("unable to get boundary");
    998 		return ret;
    999 	}
   1000 	ret = snd_pcm_sw_params_set_stop_threshold(spcm, sw_params, boundary);
   1001 	if (ret < 0) {
   1002 		SNDERR("unable to set stop threshold");
   1003 		return ret;
   1004 	}
   1005 
   1006 	/* set timestamp mode to MMAP
   1007 	 * the slave timestamp is copied appropriately in dsnoop/dmix/dshare
   1008 	 * based on the tstamp_mode of each client
   1009 	 */
   1010 	ret = snd_pcm_sw_params_set_tstamp_mode(spcm, sw_params,
   1011 						SND_PCM_TSTAMP_ENABLE);
   1012 	if (ret < 0) {
   1013 		SNDERR("unable to tstamp mode MMAP");
   1014 		return ret;
   1015 	}
   1016 
   1017 	if (dmix->type != SND_PCM_TYPE_DMIX)
   1018 		goto __skip_silencing;
   1019 
   1020 	ret = snd_pcm_sw_params_set_silence_threshold(spcm, sw_params, 0);
   1021 	if (ret < 0) {
   1022 		SNDERR("unable to set silence threshold");
   1023 		return ret;
   1024 	}
   1025 	ret = snd_pcm_sw_params_set_silence_size(spcm, sw_params, boundary);
   1026 	if (ret < 0) {
   1027 		SNDERR("unable to set silence threshold (please upgrade to 0.9.0rc8+ driver)");
   1028 		return ret;
   1029 	}
   1030 
   1031       __skip_silencing:
   1032 
   1033 	ret = snd_pcm_sw_params(spcm, sw_params);
   1034 	if (ret < 0) {
   1035 		SNDERR("unable to install sw params (please upgrade to 0.9.0rc8+ driver)");
   1036 		return ret;
   1037 	}
   1038 
   1039 	if (dmix->type == SND_PCM_TYPE_DSHARE) {
   1040 		const snd_pcm_channel_area_t *dst_areas;
   1041 		dst_areas = snd_pcm_mmap_areas(spcm);
   1042 		snd_pcm_areas_silence(dst_areas, 0, spcm->channels, spcm->buffer_size, spcm->format);
   1043 	}
   1044 
   1045 	ret = snd_pcm_start(spcm);
   1046 	if (ret < 0) {
   1047 		SNDERR("unable to start PCM stream");
   1048 		return ret;
   1049 	}
   1050 
   1051 	if (snd_pcm_poll_descriptors_count(spcm) != 1) {
   1052 		SNDERR("unable to use hardware pcm with fd more than one!!!");
   1053 		return ret;
   1054 	}
   1055 	snd_pcm_poll_descriptors(spcm, &fd, 1);
   1056 	dmix->hw_fd = fd.fd;
   1057 
   1058 	save_slave_setting(dmix, spcm);
   1059 
   1060 	/* Currently, we assume that each dmix client has the same
   1061 	 * hw_params setting.
   1062 	 * If the arbitrary hw_parmas is supported in future,
   1063 	 * boundary has to be taken from the slave config but
   1064 	 * recalculated for the native boundary size (for 32bit
   1065 	 * emulation on 64bit arch).
   1066 	 */
   1067 	dmix->slave_buffer_size = spcm->buffer_size;
   1068 	dmix->slave_period_size = spcm->period_size;
   1069 	dmix->slave_boundary = spcm->boundary;
   1070 
   1071 	spcm->donot_close = 1;
   1072 
   1073 	{
   1074 		int ver = 0;
   1075 		ioctl(spcm->poll_fd, SNDRV_PCM_IOCTL_PVERSION, &ver);
   1076 		if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 8))
   1077 			dmix->shmptr->use_server = 1;
   1078 	}
   1079 
   1080 	return 0;
   1081 }
   1082 
   1083 /*
   1084  * the trick is used here; we cannot use effectively the hardware handle because
   1085  * we cannot drive multiple accesses to appl_ptr; so we use slave timer of given
   1086  * PCM hardware handle; it's not this easy and cheap?
   1087  */
   1088 int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix)
   1089 {
   1090 	int ret;
   1091 	snd_pcm_info_t *info;
   1092 	char name[128];
   1093 	int capture = dmix->type == SND_PCM_TYPE_DSNOOP ? 1 : 0;
   1094 
   1095 	dmix->tread = 1;
   1096 	dmix->timer_need_poll = 0;
   1097 	snd_pcm_info_alloca(&info);
   1098 	ret = snd_pcm_info(dmix->spcm, info);
   1099 	if (ret < 0) {
   1100 		SNDERR("unable to info for slave pcm");
   1101 		return ret;
   1102 	}
   1103 	sprintf(name, "hw:CLASS=%i,SCLASS=0,CARD=%i,DEV=%i,SUBDEV=%i",
   1104 				(int)SND_TIMER_CLASS_PCM,
   1105 				snd_pcm_info_get_card(info),
   1106 				snd_pcm_info_get_device(info),
   1107 				snd_pcm_info_get_subdevice(info) * 2 + capture);
   1108 	ret = snd_timer_open(&dmix->timer, name, SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD);
   1109 	if (ret < 0) {
   1110 		dmix->tread = 0;
   1111 		ret = snd_timer_open(&dmix->timer, name, SND_TIMER_OPEN_NONBLOCK);
   1112 		if (ret < 0) {
   1113 			SNDERR("unable to open timer '%s'", name);
   1114 			return ret;
   1115 		}
   1116 	}
   1117 
   1118 	if (snd_timer_poll_descriptors_count(dmix->timer) != 1) {
   1119 		SNDERR("unable to use timer '%s' with more than one fd!", name);
   1120 		return ret;
   1121 	}
   1122 	snd_timer_poll_descriptors(dmix->timer, &dmix->timer_fd, 1);
   1123 	dmix->poll_fd = dmix->timer_fd.fd;
   1124 
   1125 	dmix->timer_event_suspend = 1<<SND_TIMER_EVENT_MSUSPEND;
   1126 	dmix->timer_event_resume = 1<<SND_TIMER_EVENT_MRESUME;
   1127 
   1128 	/*
   1129 	 * Some hacks for older kernel drivers
   1130 	 */
   1131 	{
   1132 		int ver = 0;
   1133 		ioctl(dmix->poll_fd, SNDRV_TIMER_IOCTL_PVERSION, &ver);
   1134 		/* In older versions, check via poll before read() is needed
   1135 		 * because of the confliction between TIMER_START and
   1136 		 * FIONBIO ioctls.
   1137 		 */
   1138 		if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 4))
   1139 			dmix->timer_need_poll = 1;
   1140 		/*
   1141 		 * In older versions, timer uses pause events instead
   1142 		 * suspend/resume events.
   1143 		 */
   1144 		if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 5)) {
   1145 			dmix->timer_event_suspend = 1<<SND_TIMER_EVENT_MPAUSE;
   1146 			dmix->timer_event_resume = 1<<SND_TIMER_EVENT_MCONTINUE;
   1147 		}
   1148 	}
   1149 	return 0;
   1150 }
   1151 
   1152 static snd_pcm_uframes_t recalc_boundary_size(unsigned long long bsize, snd_pcm_uframes_t buffer_size)
   1153 {
   1154 	if (bsize > LONG_MAX) {
   1155 		bsize = buffer_size;
   1156 		while (bsize * 2 <= LONG_MAX - buffer_size)
   1157 			bsize *= 2;
   1158 	}
   1159 	return (snd_pcm_uframes_t)bsize;
   1160 }
   1161 
   1162 #define COPY_SLAVE(field) (spcm->field = dmix->shmptr->s.field)
   1163 
   1164 /* copy the slave setting */
   1165 static void copy_slave_setting(snd_pcm_direct_t *dmix, snd_pcm_t *spcm)
   1166 {
   1167 	COPY_SLAVE(access);
   1168 	COPY_SLAVE(format);
   1169 	COPY_SLAVE(subformat);
   1170 	COPY_SLAVE(channels);
   1171 	COPY_SLAVE(rate);
   1172 	COPY_SLAVE(period_size);
   1173 	COPY_SLAVE(period_time);
   1174 	COPY_SLAVE(periods);
   1175 	COPY_SLAVE(tstamp_mode);
   1176 	COPY_SLAVE(period_step);
   1177 	COPY_SLAVE(avail_min);
   1178 	COPY_SLAVE(start_threshold);
   1179 	COPY_SLAVE(stop_threshold);
   1180 	COPY_SLAVE(silence_threshold);
   1181 	COPY_SLAVE(silence_size);
   1182 	COPY_SLAVE(boundary);
   1183 	COPY_SLAVE(info);
   1184 	COPY_SLAVE(msbits);
   1185 	COPY_SLAVE(rate_num);
   1186 	COPY_SLAVE(rate_den);
   1187 	COPY_SLAVE(hw_flags);
   1188 	COPY_SLAVE(fifo_size);
   1189 	COPY_SLAVE(buffer_size);
   1190 	COPY_SLAVE(buffer_time);
   1191 	COPY_SLAVE(sample_bits);
   1192 	COPY_SLAVE(frame_bits);
   1193 
   1194 	spcm->info &= ~SND_PCM_INFO_PAUSE;
   1195 	spcm->boundary = recalc_boundary_size(dmix->shmptr->s.boundary, spcm->buffer_size);
   1196 }
   1197 
   1198 #undef COPY_SLAVE
   1199 
   1200 
   1201 /*
   1202  * open a slave PCM as secondary client (dup'ed fd)
   1203  */
   1204 int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name)
   1205 {
   1206 	int ret;
   1207 	snd_pcm_t *spcm;
   1208 
   1209 	ret = snd_pcm_hw_open_fd(spcmp, client_name, dmix->hw_fd, 0, 0);
   1210 	if (ret < 0) {
   1211 		SNDERR("unable to open hardware");
   1212 		return ret;
   1213 	}
   1214 
   1215 	spcm = *spcmp;
   1216 	spcm->donot_close = 1;
   1217 	spcm->setup = 1;
   1218 
   1219 	copy_slave_setting(dmix, spcm);
   1220 
   1221 	/* Use the slave setting as SPCM, so far */
   1222 	dmix->slave_buffer_size = spcm->buffer_size;
   1223 	dmix->slave_period_size = dmix->shmptr->s.period_size;
   1224 	dmix->slave_boundary = spcm->boundary;
   1225 
   1226 	ret = snd_pcm_mmap(spcm);
   1227 	if (ret < 0) {
   1228 		SNDERR("unable to mmap channels");
   1229 		return ret;
   1230 	}
   1231 	return 0;
   1232 }
   1233 
   1234 /*
   1235  * open a slave PCM as secondary client (dup'ed fd)
   1236  */
   1237 int snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix,
   1238 					      snd_pcm_t *spcm,
   1239 					      struct slave_params *params ATTRIBUTE_UNUSED)
   1240 {
   1241 	int ret;
   1242 
   1243 	spcm->donot_close = 1;
   1244 	spcm->setup = 1;
   1245 
   1246 	copy_slave_setting(dmix, spcm);
   1247 
   1248 	/* Use the slave setting as SPCM, so far */
   1249 	dmix->slave_buffer_size = spcm->buffer_size;
   1250 	dmix->slave_period_size = dmix->shmptr->s.period_size;
   1251 	dmix->slave_boundary = spcm->boundary;
   1252 
   1253 	ret = snd_pcm_mmap(spcm);
   1254 	if (ret < 0) {
   1255 		SNDERR("unable to mmap channels");
   1256 		return ret;
   1257 	}
   1258 	return 0;
   1259 }
   1260 
   1261 int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
   1262 {
   1263 	snd_timer_params_t *params;
   1264 	unsigned int filter;
   1265 	int ret;
   1266 
   1267 	snd_timer_params_alloca(&params);
   1268 	snd_timer_params_set_auto_start(params, 1);
   1269 	if (dmix->type != SND_PCM_TYPE_DSNOOP)
   1270 		snd_timer_params_set_early_event(params, 1);
   1271 	snd_timer_params_set_ticks(params, 1);
   1272 	if (dmix->tread) {
   1273 		filter = (1<<SND_TIMER_EVENT_TICK) |
   1274 			 dmix->timer_event_suspend |
   1275 			 dmix->timer_event_resume;
   1276 		snd_timer_params_set_filter(params, filter);
   1277 	}
   1278 	ret = snd_timer_params(dmix->timer, params);
   1279 	if (ret < 0) {
   1280 		SNDERR("unable to set timer parameters");
   1281                 return ret;
   1282 	}
   1283 	return 0;
   1284 }
   1285 
   1286 /*
   1287  *  ring buffer operation
   1288  */
   1289 int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm)
   1290 {
   1291 	unsigned int chn, channels;
   1292 	int bits, interleaved = 1;
   1293 	const snd_pcm_channel_area_t *dst_areas;
   1294 	const snd_pcm_channel_area_t *src_areas;
   1295 
   1296 	bits = snd_pcm_format_physical_width(pcm->format);
   1297 	if ((bits % 8) != 0)
   1298 		interleaved = 0;
   1299 	channels = dmix->channels;
   1300 	dst_areas = snd_pcm_mmap_areas(dmix->spcm);
   1301 	src_areas = snd_pcm_mmap_areas(pcm);
   1302 	for (chn = 1; chn < channels; chn++) {
   1303 		if (dst_areas[chn-1].addr != dst_areas[chn].addr) {
   1304 			interleaved = 0;
   1305 			break;
   1306 		}
   1307 		if (src_areas[chn-1].addr != src_areas[chn].addr) {
   1308 			interleaved = 0;
   1309 			break;
   1310 		}
   1311 	}
   1312 	for (chn = 0; chn < channels; chn++) {
   1313 		if (dmix->bindings && dmix->bindings[chn] != chn) {
   1314 			interleaved = 0;
   1315 			break;
   1316 		}
   1317 		if (dst_areas[chn].first != chn * bits ||
   1318 		    dst_areas[chn].step != channels * bits) {
   1319 			interleaved = 0;
   1320 			break;
   1321 		}
   1322 		if (src_areas[chn].first != chn * bits ||
   1323 		    src_areas[chn].step != channels * bits) {
   1324 			interleaved = 0;
   1325 			break;
   1326 		}
   1327 	}
   1328 	return dmix->interleaved = interleaved;
   1329 }
   1330 
   1331 /*
   1332  * parse the channel map
   1333  * id == client channel
   1334  * value == slave's channel
   1335  */
   1336 int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
   1337 				  struct slave_params *params,
   1338 				  snd_config_t *cfg)
   1339 {
   1340 	snd_config_iterator_t i, next;
   1341 	unsigned int chn, chn1, count = 0;
   1342 	unsigned int *bindings;
   1343 	int err;
   1344 
   1345 	dmix->channels = UINT_MAX;
   1346 	if (cfg == NULL)
   1347 		return 0;
   1348 	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
   1349 		SNDERR("invalid type for bindings");
   1350 		return -EINVAL;
   1351 	}
   1352 	snd_config_for_each(i, next, cfg) {
   1353 		snd_config_t *n = snd_config_iterator_entry(i);
   1354 		const char *id;
   1355 		long cchannel;
   1356 		if (snd_config_get_id(n, &id) < 0)
   1357 			continue;
   1358 		err = safe_strtol(id, &cchannel);
   1359 		if (err < 0 || cchannel < 0) {
   1360 			SNDERR("invalid client channel in binding: %s\n", id);
   1361 			return -EINVAL;
   1362 		}
   1363 		if ((unsigned)cchannel >= count)
   1364 			count = cchannel + 1;
   1365 	}
   1366 	if (count == 0)
   1367 		return 0;
   1368 	if (count > 1024) {
   1369 		SNDERR("client channel out of range");
   1370 		return -EINVAL;
   1371 	}
   1372 	bindings = malloc(count * sizeof(unsigned int));
   1373 	if (bindings == NULL)
   1374 		return -ENOMEM;
   1375 	for (chn = 0; chn < count; chn++)
   1376 		bindings[chn] = UINT_MAX;		/* don't route */
   1377 	snd_config_for_each(i, next, cfg) {
   1378 		snd_config_t *n = snd_config_iterator_entry(i);
   1379 		const char *id;
   1380 		long cchannel, schannel;
   1381 		if (snd_config_get_id(n, &id) < 0)
   1382 			continue;
   1383 		safe_strtol(id, &cchannel);
   1384 		if (snd_config_get_integer(n, &schannel) < 0) {
   1385 			SNDERR("unable to get slave channel (should be integer type) in binding: %s\n", id);
   1386 			free(bindings);
   1387 			return -EINVAL;
   1388 		}
   1389 		if (schannel < 0 || schannel >= params->channels) {
   1390 			SNDERR("invalid slave channel number %ld in binding to %ld",
   1391 			       schannel, cchannel);
   1392 			free(bindings);
   1393 			return -EINVAL;
   1394 		}
   1395 		bindings[cchannel] = schannel;
   1396 	}
   1397 	if (dmix->type == SND_PCM_TYPE_DSNOOP ||
   1398 	    ! dmix->bindings)
   1399 		goto __skip_same_dst;
   1400 	for (chn = 0; chn < count; chn++) {
   1401 		for (chn1 = 0; chn1 < count; chn1++) {
   1402 			if (chn == chn1)
   1403 				continue;
   1404 			if (bindings[chn] == dmix->bindings[chn1]) {
   1405 				SNDERR("unable to route channels %d,%d to same destination %d", chn, chn1, bindings[chn]);
   1406 				free(bindings);
   1407 				return -EINVAL;
   1408 			}
   1409 		}
   1410 	}
   1411       __skip_same_dst:
   1412 	dmix->bindings = bindings;
   1413 	dmix->channels = count;
   1414 	return 0;
   1415 }
   1416 
   1417 /*
   1418  * parse slave config and calculate the ipc_key offset
   1419  */
   1420 
   1421 static int _snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root,
   1422 						snd_config_t *sconf,
   1423 						int direction,
   1424 						int hop)
   1425 {
   1426 	snd_config_iterator_t i, next;
   1427 	snd_config_t *pcm_conf;
   1428 	int err;
   1429 	long card = 0, device = 0, subdevice = 0;
   1430 	const char *str;
   1431 
   1432 	if (snd_config_get_string(sconf, &str) >= 0) {
   1433 		if (hop > SND_CONF_MAX_HOPS) {
   1434 			SNDERR("Too many definition levels (looped?)");
   1435 			return -EINVAL;
   1436 		}
   1437 		err = snd_config_search_definition(root, "pcm", str, &pcm_conf);
   1438 		if (err < 0) {
   1439 			SNDERR("Unknown slave PCM %s", str);
   1440 			return err;
   1441 		}
   1442 		err = _snd_pcm_direct_get_slave_ipc_offset(root, pcm_conf,
   1443 							   direction,
   1444 							   hop + 1);
   1445 		snd_config_delete(pcm_conf);
   1446 		return err;
   1447 	}
   1448 
   1449 #if 0	/* for debug purposes */
   1450 	{
   1451 		snd_output_t *out;
   1452 		snd_output_stdio_attach(&out, stderr, 0);
   1453 		snd_config_save(sconf, out);
   1454 		snd_output_close(out);
   1455 	}
   1456 #endif
   1457 
   1458 	if (snd_config_search(sconf, "slave", &pcm_conf) >= 0 &&
   1459 	    (snd_config_search(pcm_conf, "pcm", &pcm_conf) >= 0 ||
   1460 	    (snd_config_get_string(pcm_conf, &str) >= 0 &&
   1461 	    snd_config_search_definition(root, "pcm_slave", str, &pcm_conf) >= 0 &&
   1462 	    snd_config_search(pcm_conf, "pcm", &pcm_conf) >= 0)))
   1463 		return _snd_pcm_direct_get_slave_ipc_offset(root, pcm_conf,
   1464 							    direction,
   1465 							    hop + 1);
   1466 
   1467 	snd_config_for_each(i, next, sconf) {
   1468 		snd_config_t *n = snd_config_iterator_entry(i);
   1469 		const char *id, *str;
   1470 		if (snd_config_get_id(n, &id) < 0)
   1471 			continue;
   1472 		if (strcmp(id, "type") == 0) {
   1473 			err = snd_config_get_string(n, &str);
   1474 			if (err < 0) {
   1475 				SNDERR("Invalid value for PCM type definition\n");
   1476 				return -EINVAL;
   1477 			}
   1478 			if (strcmp(str, "hw")) {
   1479 				SNDERR("Invalid type '%s' for slave PCM\n", str);
   1480 				return -EINVAL;
   1481 			}
   1482 			continue;
   1483 		}
   1484 		if (strcmp(id, "card") == 0) {
   1485 			err = snd_config_get_integer(n, &card);
   1486 			if (err < 0) {
   1487 				err = snd_config_get_string(n, &str);
   1488 				if (err < 0) {
   1489 					SNDERR("Invalid type for %s", id);
   1490 					return -EINVAL;
   1491 				}
   1492 				card = snd_card_get_index(str);
   1493 				if (card < 0) {
   1494 					SNDERR("Invalid value for %s", id);
   1495 					return card;
   1496 				}
   1497 			}
   1498 			continue;
   1499 		}
   1500 		if (strcmp(id, "device") == 0) {
   1501 			err = snd_config_get_integer(n, &device);
   1502 			if (err < 0) {
   1503 				SNDERR("Invalid type for %s", id);
   1504 				return err;
   1505 			}
   1506 			continue;
   1507 		}
   1508 		if (strcmp(id, "subdevice") == 0) {
   1509 			err = snd_config_get_integer(n, &subdevice);
   1510 			if (err < 0) {
   1511 				SNDERR("Invalid type for %s", id);
   1512 				return err;
   1513 			}
   1514 			continue;
   1515 		}
   1516 	}
   1517 	if (card < 0)
   1518 		card = 0;
   1519 	if (device < 0)
   1520 		device = 0;
   1521 	if (subdevice < 0)
   1522 		subdevice = 0;
   1523 	return (direction << 1) + (device << 2) + (subdevice << 8) + (card << 12);
   1524 }
   1525 
   1526 static int snd_pcm_direct_get_slave_ipc_offset(snd_config_t *root,
   1527 					snd_config_t *sconf,
   1528 					int direction)
   1529 {
   1530 	return _snd_pcm_direct_get_slave_ipc_offset(root, sconf, direction, 0);
   1531 }
   1532 
   1533 int snd_pcm_direct_parse_open_conf(snd_config_t *root, snd_config_t *conf,
   1534 				   int stream, struct snd_pcm_direct_open_conf *rec)
   1535 {
   1536 	snd_config_iterator_t i, next;
   1537 	int ipc_key_add_uid = 0;
   1538 	snd_config_t *n;
   1539 	int err;
   1540 
   1541 	rec->slave = NULL;
   1542 	rec->bindings = NULL;
   1543 	rec->ipc_key = 0;
   1544 	rec->ipc_perm = 0600;
   1545 	rec->ipc_gid = -1;
   1546 	rec->slowptr = 1;
   1547 	rec->max_periods = 0;
   1548 
   1549 	/* read defaults */
   1550 	if (snd_config_search(root, "defaults.pcm.dmix_max_periods", &n) >= 0) {
   1551 		long val;
   1552 		err = snd_config_get_integer(n, &val);
   1553 		if (err >= 0)
   1554 			rec->max_periods = val;
   1555 	}
   1556 
   1557 	snd_config_for_each(i, next, conf) {
   1558 		const char *id;
   1559 		n = snd_config_iterator_entry(i);
   1560 		if (snd_config_get_id(n, &id) < 0)
   1561 			continue;
   1562 		if (snd_pcm_conf_generic_id(id))
   1563 			continue;
   1564 		if (strcmp(id, "ipc_key") == 0) {
   1565 			long key;
   1566 			err = snd_config_get_integer(n, &key);
   1567 			if (err < 0) {
   1568 				SNDERR("The field ipc_key must be an integer type");
   1569 
   1570 				return err;
   1571 			}
   1572 			rec->ipc_key = key;
   1573 			continue;
   1574 		}
   1575 		if (strcmp(id, "ipc_perm") == 0) {
   1576 			long perm;
   1577 			err = snd_config_get_integer(n, &perm);
   1578 			if (err < 0) {
   1579 				SNDERR("Invalid type for %s", id);
   1580 				return err;
   1581 			}
   1582 			if ((perm & ~0777) != 0) {
   1583 				SNDERR("The field ipc_perm must be a valid file permission");
   1584 				return -EINVAL;
   1585 			}
   1586 			rec->ipc_perm = perm;
   1587 			continue;
   1588 		}
   1589 		if (strcmp(id, "ipc_gid") == 0) {
   1590 			char *group;
   1591 			char *endp;
   1592 			err = snd_config_get_ascii(n, &group);
   1593 			if (err < 0) {
   1594 				SNDERR("The field ipc_gid must be a valid group");
   1595 				return err;
   1596 			}
   1597 			if (! *group) {
   1598 				rec->ipc_gid = -1;
   1599 				free(group);
   1600 				continue;
   1601 			}
   1602 			if (isdigit(*group) == 0) {
   1603 				struct group *grp = getgrnam(group);
   1604 				if (grp == NULL) {
   1605 					SNDERR("The field ipc_gid must be a valid group (create group %s)", group);
   1606 					free(group);
   1607 					return -EINVAL;
   1608 				}
   1609 				rec->ipc_gid = grp->gr_gid;
   1610 			} else {
   1611 				rec->ipc_gid = strtol(group, &endp, 10);
   1612 			}
   1613 			free(group);
   1614 			continue;
   1615 		}
   1616 		if (strcmp(id, "ipc_key_add_uid") == 0) {
   1617 			if ((err = snd_config_get_bool(n)) < 0) {
   1618 				SNDERR("The field ipc_key_add_uid must be a boolean type");
   1619 				return err;
   1620 			}
   1621 			ipc_key_add_uid = err;
   1622 			continue;
   1623 		}
   1624 		if (strcmp(id, "slave") == 0) {
   1625 			rec->slave = n;
   1626 			continue;
   1627 		}
   1628 		if (strcmp(id, "bindings") == 0) {
   1629 			rec->bindings = n;
   1630 			continue;
   1631 		}
   1632 		if (strcmp(id, "slowptr") == 0) {
   1633 			err = snd_config_get_bool(n);
   1634 			if (err < 0)
   1635 				return err;
   1636 			rec->slowptr = err;
   1637 			continue;
   1638 		}
   1639 		if (strcmp(id, "max_periods") == 0) {
   1640 			long val;
   1641 			err = snd_config_get_integer(n, &val);
   1642 			if (err < 0)
   1643 				return err;
   1644 			rec->max_periods = val;
   1645 			continue;
   1646 		}
   1647 		SNDERR("Unknown field %s", id);
   1648 		return -EINVAL;
   1649 	}
   1650 	if (!rec->slave) {
   1651 		SNDERR("slave is not defined");
   1652 		return -EINVAL;
   1653 	}
   1654 	if (!rec->ipc_key) {
   1655 		SNDERR("Unique IPC key is not defined");
   1656 		return -EINVAL;
   1657 	}
   1658 	if (ipc_key_add_uid)
   1659 		rec->ipc_key += getuid();
   1660 	err = snd_pcm_direct_get_slave_ipc_offset(root, conf, stream);
   1661 	if (err < 0)
   1662 		return err;
   1663 	rec->ipc_key += err;
   1664 
   1665 	return 0;
   1666 }
   1667