OSDN Git Service

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