xref: /third_party/alsa-lib/src/pcm/pcm_direct.c (revision d5ac70f0)
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 &params->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 &params->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 *)&params->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 *)&params->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 *)&params->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 *)&params->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 *)&params->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 *)&params->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, &params->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(&params, 1);
1661	if (dmix->type != SND_PCM_TYPE_DSNOOP)
1662		snd_timer_params_set_early_event(&params, 1);
1663	snd_timer_params_set_ticks(&params, 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)(&params, filter);
1668	}
1669	ret = snd_timer_params(dmix->timer, &params);
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