]> git.alsa-project.org Git - alsa-lib.git/blob - src/pcm/pcm_hw.c
c9fca93c5d65099b64dc02091fd5bd5f5da2b1b7
[alsa-lib.git] / src / pcm / pcm_hw.c
1 /**
2  * \file pcm/pcm_hw.c
3  * \ingroup PCM_Plugins
4  * \brief PCM HW Plugin Interface
5  * \author Abramo Bagnara <abramo@alsa-project.org>
6  * \author Jaroslav Kysela <perex@perex.cz>
7  * \date 2000-2001
8  */
9 /*
10  *  PCM - Hardware
11  *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
12  *
13  *
14  *   This library is free software; you can redistribute it and/or modify
15  *   it under the terms of the GNU Lesser General Public License as
16  *   published by the Free Software Foundation; either version 2.1 of
17  *   the License, or (at your option) any later version.
18  *
19  *   This program is distributed in the hope that it will be useful,
20  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *   GNU Lesser General Public License for more details.
23  *
24  *   You should have received a copy of the GNU Lesser General Public
25  *   License along with this library; if not, write to the Free Software
26  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
27  *
28  */
29
30 #include "pcm_local.h"
31 #include "../control/control_local.h"
32 #include "../timer/timer_local.h"
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stddef.h>
36 #include <unistd.h>
37 #include <stdbool.h>
38 #include <signal.h>
39 #include <string.h>
40 #include <fcntl.h>
41 #include <sys/ioctl.h>
42 #include <sys/mman.h>
43
44 //#define DEBUG_RW              /* use to debug readi/writei/readn/writen */
45 //#define DEBUG_MMAP            /* debug mmap_commit */
46
47 #ifndef PIC
48 /* entry for static linking */
49 const char *_snd_module_pcm_hw = "";
50 #endif
51
52 #ifndef DOC_HIDDEN
53
54 #ifndef F_SETSIG
55 #define F_SETSIG 10
56 #endif
57
58 /*
59  *  Compatibility
60  */
61
62 struct sndrv_pcm_hw_params_old {
63         unsigned int flags;
64         unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
65                            SNDRV_PCM_HW_PARAM_ACCESS + 1];
66         struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
67                                         SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
68         unsigned int rmask;
69         unsigned int cmask;
70         unsigned int info;
71         unsigned int msbits;
72         unsigned int rate_num;
73         unsigned int rate_den;
74         sndrv_pcm_uframes_t fifo_size;
75         unsigned char reserved[64];
76 };
77
78 #define SND_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old)
79 #define SND_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old)
80
81 static int use_old_hw_params_ioctl(int fd, unsigned int cmd, snd_pcm_hw_params_t *params);
82 static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm);
83 static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops;
84 static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops_timer;
85
86 /*
87  *
88  */
89
90 typedef struct {
91         int version;
92         int fd;
93         int card, device, subdevice;
94
95         volatile struct snd_pcm_mmap_status * mmap_status;
96         struct snd_pcm_mmap_control *mmap_control;
97         bool mmap_status_fallbacked;
98         bool mmap_control_fallbacked;
99         struct snd_pcm_sync_ptr *sync_ptr;
100
101         bool prepare_reset_sw_params;
102         bool perfect_drain;
103
104         int period_event;
105         snd_timer_t *period_timer;
106         struct pollfd period_timer_pfd;
107         int period_timer_need_poll;
108         /* restricted parameters */
109         snd_pcm_format_t format;
110         struct {
111                 int min;
112                 int max;
113         } rates;
114         int channels;
115         int drain_silence;
116         /* for chmap */
117         unsigned int chmap_caps;
118         snd_pcm_chmap_query_t **chmap_override;
119 } snd_pcm_hw_t;
120
121 #define SNDRV_FILE_PCM_STREAM_PLAYBACK          ALSA_DEVICE_DIRECTORY "pcmC%iD%ip"
122 #define SNDRV_FILE_PCM_STREAM_CAPTURE           ALSA_DEVICE_DIRECTORY "pcmC%iD%ic"
123 #define SNDRV_PCM_VERSION_MAX                   SNDRV_PROTOCOL_VERSION(2, 0, 9)
124
125 /* update appl_ptr with driver */
126 #define FAST_PCM_STATE(hw) \
127         ((snd_pcm_state_t) (hw)->mmap_status->state)
128 #define FAST_PCM_TSTAMP(hw) \
129         ((hw)->mmap_status->tstamp)
130
131 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm)
132 {
133         struct timespec res;
134         snd_pcm_hw_t *hw = pcm->private_data;
135         res = FAST_PCM_TSTAMP(hw);
136         if (SNDRV_PROTOCOL_VERSION(2, 0, 5) > hw->version)
137                 res.tv_nsec *= 1000L;
138         return res;
139 }
140 #endif /* DOC_HIDDEN */
141
142 static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags)
143 {
144         int err;
145         hw->sync_ptr->flags = flags;
146         if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) {
147                 err = -errno;
148                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err);
149                 return err;
150         }
151         return 0;
152 }
153
154 static int issue_avail_min(snd_pcm_hw_t *hw)
155 {
156         if (!hw->mmap_control_fallbacked)
157                 return 0;
158
159         /* Avoid unexpected change of applptr in kernel space. */
160         return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_APPL);
161 }
162
163 static int issue_applptr(snd_pcm_hw_t *hw)
164 {
165         if (!hw->mmap_control_fallbacked)
166                 return 0;
167
168         /* Avoid unexpected change of avail_min in kernel space. */
169         return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
170 }
171
172 static int request_hwsync(snd_pcm_hw_t *hw)
173 {
174         if (!hw->mmap_status_fallbacked)
175                 return 0;
176
177         /*
178          * Query both of control/status data to avoid unexpected change of
179          * control data in kernel space.
180          */
181         return sync_ptr1(hw,
182                          SNDRV_PCM_SYNC_PTR_HWSYNC |
183                          SNDRV_PCM_SYNC_PTR_APPL |
184                          SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
185 }
186
187 static int query_status_and_control_data(snd_pcm_hw_t *hw)
188 {
189         if (!hw->mmap_control_fallbacked)
190                 return 0;
191
192         /*
193          * Query both of control/status data to avoid unexpected change of
194          * control data in kernel space.
195          */
196         return sync_ptr1(hw,
197                          SNDRV_PCM_SYNC_PTR_APPL |
198                          SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
199 }
200
201 static int query_status_data(snd_pcm_hw_t *hw)
202 {
203         if (!hw->mmap_status_fallbacked)
204                 return 0;
205
206         /*
207          * Query both of control/status data to avoid unexpected change of
208          * control data in kernel space.
209          */
210         return sync_ptr1(hw,
211                          SNDRV_PCM_SYNC_PTR_APPL |
212                          SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
213 }
214
215 static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw)
216 {
217         if (hw->period_timer_need_poll) {
218                 while (poll(&hw->period_timer_pfd, 1, 0) > 0) {
219                         snd_timer_tread_t rbuf[4];
220                         snd_timer_read(hw->period_timer, rbuf, sizeof(rbuf));
221                 }
222         } else {
223                 snd_timer_tread_t rbuf[4];
224                 snd_timer_read(hw->period_timer, rbuf, sizeof(rbuf));
225         }
226         return 0;
227 }
228
229 static int snd_pcm_hw_poll_descriptors_count(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
230 {
231         return 2;
232 }
233
234 static int snd_pcm_hw_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
235 {
236         snd_pcm_hw_t *hw = pcm->private_data;
237
238         if (space < 2)
239                 return -ENOMEM;
240         pfds[0].fd = hw->fd;
241         pfds[0].events = pcm->poll_events | POLLERR | POLLNVAL;
242         pfds[1].fd = hw->period_timer_pfd.fd;
243         pfds[1].events = POLLIN | POLLERR | POLLNVAL;
244         return 2;
245 }
246
247 static int snd_pcm_hw_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned nfds, unsigned short *revents)
248 {
249         snd_pcm_hw_t *hw = pcm->private_data;
250         unsigned int events;
251
252         if (nfds != 2 || pfds[0].fd != hw->fd || pfds[1].fd != hw->period_timer_pfd.fd)
253                 return -EINVAL;
254         events = pfds[0].revents;
255         if (pfds[1].revents & POLLIN) {
256                 snd_pcm_hw_clear_timer_queue(hw);
257                 events |= pcm->poll_events & ~(POLLERR|POLLNVAL);
258         }
259         *revents = events;
260         return 0;
261 }
262
263 static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
264 {
265         long flags;
266         snd_pcm_hw_t *hw = pcm->private_data;
267         int fd = hw->fd, err;
268
269         if ((flags = fcntl(fd, F_GETFL)) < 0) {
270                 err = -errno;
271                 snd_checknum(PCM, "F_GETFL failed (%i)", err);
272                 return err;
273         }
274         if (nonblock)
275                 flags |= O_NONBLOCK;
276         else
277                 flags &= ~O_NONBLOCK;
278         if (fcntl(fd, F_SETFL, flags) < 0) {
279                 err = -errno;
280                 snd_checknum(PCM, "F_SETFL for O_NONBLOCK failed (%i)", err);
281                 return err;
282         }
283         return 0;
284 }
285
286 static int snd_pcm_hw_async(snd_pcm_t *pcm, int sig, pid_t pid)
287 {
288         long flags;
289         snd_pcm_hw_t *hw = pcm->private_data;
290         int fd = hw->fd, err;
291
292         if ((flags = fcntl(fd, F_GETFL)) < 0) {
293                 err = -errno;
294                 snd_checknum(PCM, "F_GETFL failed (%i)", err);
295                 return err;
296         }
297         if (sig >= 0)
298                 flags |= O_ASYNC;
299         else
300                 flags &= ~O_ASYNC;
301         if (fcntl(fd, F_SETFL, flags) < 0) {
302                 err = -errno;
303                 snd_checknum(PCM, "F_SETFL for O_ASYNC failed (%i)", err);
304                 return err;
305         }
306         if (sig < 0)
307                 return 0;
308         if (fcntl(fd, F_SETSIG, (long)sig) < 0) {
309                 err = -errno;
310                 snd_checknum(PCM, "F_SETSIG failed (%i)", err);
311                 return err;
312         }
313         if (fcntl(fd, F_SETOWN, (long)pid) < 0) {
314                 err = -errno;
315                 snd_checknum(PCM, "F_SETOWN failed (%i)", err);
316                 return err;
317         }
318         return 0;
319 }
320
321 static int snd_pcm_hw_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
322 {
323         snd_pcm_hw_t *hw = pcm->private_data;
324         int fd = hw->fd, err;
325         if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, info) < 0) {
326                 err = -errno;
327                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_INFO failed (%i)", err);
328                 return err;
329         }
330         /* may be configurable (optional) */
331         if (__snd_pcm_info_eld_fixup_check(info))
332                 return __snd_pcm_info_eld_fixup(info);
333         return 0;
334 }
335
336 static inline int hw_refine_call(snd_pcm_hw_t *pcm_hw, snd_pcm_hw_params_t *params)
337 {
338         /* check for new hw_params structure; it's available from 2.0.2 version of PCM API */
339         if (SNDRV_PROTOCOL_VERSION(2, 0, 2) <= pcm_hw->version)
340                 return ioctl(pcm_hw->fd, SNDRV_PCM_IOCTL_HW_REFINE, params);
341         return use_old_hw_params_ioctl(pcm_hw->fd, SND_PCM_IOCTL_HW_REFINE_OLD, params);
342 }
343
344 static int snd_pcm_hw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
345 {
346         snd_pcm_hw_t *hw = pcm->private_data;
347         int err;
348
349         if (hw->format != SND_PCM_FORMAT_UNKNOWN) {
350                 err = _snd_pcm_hw_params_set_format(params, hw->format);
351                 if (err < 0)
352                         return err;
353         }
354         if (hw->channels > 0) {
355                 err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
356                                             hw->channels, 0);
357                 if (err < 0)
358                         return err;
359         }
360         if (hw->rates.min > 0) {
361                 err = _snd_pcm_hw_param_set_minmax(params, SND_PCM_HW_PARAM_RATE,
362                                                    hw->rates.min, 0, hw->rates.max + 1, -1);
363                 if (err < 0)
364                         return err;
365         }
366
367         if (hw_refine_call(hw, params) < 0) {
368                 err = -errno;
369                 // SYSMSG("SNDRV_PCM_IOCTL_HW_REFINE failed");
370                 return err;
371         }
372
373         if (params->info != ~0U) {
374                 params->info &= ~0xf0000000;
375                 if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY)
376                         params->info |= SND_PCM_INFO_MONOTONIC;
377         }
378
379         return 0;
380 }
381
382 #ifndef DOC_HIDDEN
383 #define hw_param_mask(params,var) \
384         &((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
385 #endif
386
387 static int hw_params_call(snd_pcm_hw_t *pcm_hw, snd_pcm_hw_params_t *params)
388 {
389         int err;
390
391         /* check for new hw_params structure; it's available from 2.0.2 version of PCM API */
392         if (SNDRV_PROTOCOL_VERSION(2, 0, 2) <= pcm_hw->version)
393                 err = ioctl(pcm_hw->fd, SNDRV_PCM_IOCTL_HW_PARAMS, params);
394         else
395                 err = use_old_hw_params_ioctl(pcm_hw->fd, SND_PCM_IOCTL_HW_PARAMS_OLD, params);
396         if (err >= 0 && pcm_hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 17) && params->msbits > 0) {
397                 snd_mask_t *m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
398                 if (snd_mask_single(m)) {
399                         snd_pcm_format_t format = snd_mask_min(m);
400                         int width = snd_pcm_format_width(format);
401                         if (width > 0 && params->msbits > (unsigned int)width)
402                                 params->msbits = width;
403                 }
404         }
405         return err;
406 }
407
408 static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
409 {
410         snd_pcm_hw_t *hw = pcm->private_data;
411         int err;
412         if (hw_params_call(hw, params) < 0) {
413                 err = -errno;
414                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_HW_PARAMS failed (%i)", err);
415                 return err;
416         }
417         params->info &= ~0xf0000000;
418         if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY)
419                 params->info |= SND_PCM_INFO_MONOTONIC;
420         hw->perfect_drain = !!(params->info & SND_PCM_INFO_PERFECT_DRAIN) ||
421                             !!(params->flags & SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE);
422         return query_status_data(hw);
423 }
424
425 static void snd_pcm_hw_close_timer(snd_pcm_hw_t *hw)
426 {
427         if (hw->period_timer) {
428                 snd_timer_close(hw->period_timer);
429                 hw->period_timer = NULL;
430         }
431 }
432
433 static int snd_pcm_hw_change_timer(snd_pcm_t *pcm, int enable)
434 {
435         snd_pcm_hw_t *hw = pcm->private_data;
436         snd_timer_params_t params = {0};
437         unsigned int suspend, resume;
438         int err;
439
440         if (enable) {
441                 err = snd_timer_hw_open(&hw->period_timer,
442                                 "hw-pcm-period-event",
443                                 SND_TIMER_CLASS_PCM, SND_TIMER_SCLASS_NONE,
444                                 hw->card, hw->device,
445                                 (hw->subdevice << 1) | (pcm->stream & 1),
446                                 SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD);
447                 if (err < 0) {
448                         err = snd_timer_hw_open(&hw->period_timer,
449                                 "hw-pcm-period-event",
450                                 SND_TIMER_CLASS_PCM, SND_TIMER_SCLASS_NONE,
451                                 hw->card, hw->device,
452                                 (hw->subdevice << 1) | (pcm->stream & 1),
453                                 SND_TIMER_OPEN_NONBLOCK);
454                         return err;
455                 }
456                 if (snd_timer_poll_descriptors_count(hw->period_timer) != 1) {
457                         snd_pcm_hw_close_timer(hw);
458                         return -EINVAL;
459                 }
460                 hw->period_timer_pfd.events = POLLIN;
461                 hw->period_timer_pfd.revents = 0;
462                 snd_timer_poll_descriptors(hw->period_timer,
463                                            &hw->period_timer_pfd, 1);
464                 hw->period_timer_need_poll = 0;
465                 suspend = 1<<SND_TIMER_EVENT_MSUSPEND;
466                 resume = 1<<SND_TIMER_EVENT_MRESUME;
467                 /*
468                  * hacks for older kernel drivers
469                  */
470                 {
471                         int ver = 0;
472                         if (ioctl(hw->period_timer_pfd.fd, SNDRV_TIMER_IOCTL_PVERSION, &ver))
473                                 snd_warn(PCM, "unable to get protocol version");
474                         /*
475                          * In older versions, check via poll before read() is
476                          * needed because of the confliction between
477                          * TIMER_START and FIONBIO ioctls.
478                          */
479                         if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 4))
480                                 hw->period_timer_need_poll = 1;
481                         /*
482                          * In older versions, timer uses pause events instead
483                          * suspend/resume events.
484                          */
485                         if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 5)) {
486                                 suspend = 1<<SND_TIMER_EVENT_MPAUSE;
487                                 resume = 1<<SND_TIMER_EVENT_MCONTINUE;
488                         }
489                 }
490                 snd_timer_params_set_auto_start(&params, 1);
491                 snd_timer_params_set_ticks(&params, 1);
492                 INTERNAL(snd_timer_params_set_filter)(&params, (1<<SND_TIMER_EVENT_TICK) |
493                                             suspend | resume);
494                 err = snd_timer_params(hw->period_timer, &params);
495                 if (err < 0) {
496                         snd_pcm_hw_close_timer(hw);
497                         return err;
498                 }
499                 err = snd_timer_start(hw->period_timer);
500                 if (err < 0) {
501                         snd_pcm_hw_close_timer(hw);
502                         return err;
503                 }
504                 pcm->fast_ops = &snd_pcm_hw_fast_ops_timer;
505         } else {
506                 snd_pcm_hw_close_timer(hw);
507                 pcm->fast_ops = &snd_pcm_hw_fast_ops;
508                 hw->period_event = 0;
509         }
510         return 0;
511 }
512
513 static int snd_pcm_hw_hw_free(snd_pcm_t *pcm)
514 {
515         snd_pcm_hw_t *hw = pcm->private_data;
516         int fd = hw->fd, err;
517         snd_pcm_hw_change_timer(pcm, 0);
518         if (ioctl(fd, SNDRV_PCM_IOCTL_HW_FREE) < 0) {
519                 err = -errno;
520                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_HW_FREE failed (%i)", err);
521                 return err;
522         }
523         return 0;
524 }
525
526 static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
527 {
528         snd_pcm_hw_t *hw = pcm->private_data;
529         int fd = hw->fd, err = 0;
530         int old_period_event = sw_get_period_event(params);
531         sw_set_period_event(params, 0);
532         if ((snd_pcm_tstamp_t) params->tstamp_mode == pcm->tstamp_mode &&
533             (snd_pcm_tstamp_type_t) params->tstamp_type == pcm->tstamp_type &&
534             params->period_step == pcm->period_step &&
535             params->start_threshold == pcm->start_threshold &&
536             params->stop_threshold == pcm->stop_threshold &&
537             params->silence_threshold == pcm->silence_threshold &&
538             params->silence_size == pcm->silence_size &&
539             old_period_event == hw->period_event) {
540                 hw->mmap_control->avail_min = params->avail_min;
541                 err = issue_avail_min(hw);
542                 goto out;
543         }
544         if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW &&
545             hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) {
546                 snd_checknum(PCM, "Kernel doesn't support SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW");
547                 err = -EINVAL;
548                 goto out;
549         }
550         if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC &&
551             hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 5)) {
552                 snd_checknum(PCM, "Kernel doesn't support SND_PCM_TSTAMP_TYPE_MONOTONIC");
553                 err = -EINVAL;
554                 goto out;
555         }
556         if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) {
557                 err = -errno;
558                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
559                 goto out;
560         }
561         hw->prepare_reset_sw_params = false;
562         if ((snd_pcm_tstamp_type_t) params->tstamp_type != pcm->tstamp_type) {
563                 if (hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) {
564                         int on = (snd_pcm_tstamp_type_t) params->tstamp_type ==
565                                 SND_PCM_TSTAMP_TYPE_MONOTONIC;
566                         if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) {
567                                 err = -errno;
568                                 snd_check(PCM, "TSTAMP failed");
569                                 goto out;
570                         }
571                 }
572                 pcm->tstamp_type = params->tstamp_type;
573         }
574         hw->mmap_control->avail_min = params->avail_min;
575         if (hw->period_event != old_period_event) {
576                 err = snd_pcm_hw_change_timer(pcm, old_period_event);
577                 if (err < 0)
578                         goto out;
579                 hw->period_event = old_period_event;
580         }
581  out:
582         sw_set_period_event(params, old_period_event);
583         return err;
584 }
585
586 static int snd_pcm_hw_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
587 {
588         snd_pcm_hw_t *hw = pcm->private_data;
589         struct snd_pcm_channel_info i;
590         int fd = hw->fd, err;
591         i.channel = info->channel;
592         if (ioctl(fd, SNDRV_PCM_IOCTL_CHANNEL_INFO, &i) < 0) {
593                 err = -errno;
594                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_CHANNEL_INFO failed (%i)", err);
595                 return err;
596         }
597         info->channel = i.channel;
598         info->addr = 0;
599         info->first = i.first;
600         info->step = i.step;
601         info->type = SND_PCM_AREA_MMAP;
602         info->u.mmap.fd = fd;
603         info->u.mmap.offset = i.offset;
604         return 0;
605 }
606
607 static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
608 {
609         snd_pcm_hw_t *hw = pcm->private_data;
610         int fd = hw->fd, err;
611         if (SNDRV_PROTOCOL_VERSION(2, 0, 13) > hw->version) {
612                 if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS, status) < 0) {
613                         err = -errno;
614                         snd_checknum(PCM, "SNDRV_PCM_IOCTL_STATUS failed (%i)", err);
615                         return err;
616                 }
617         } else {
618                 if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS_EXT, status) < 0) {
619                         err = -errno;
620                         snd_checknum(PCM, "SNDRV_PCM_IOCTL_STATUS_EXT failed (%i)", err);
621                         return err;
622                 }
623         }
624         if (SNDRV_PROTOCOL_VERSION(2, 0, 5) > hw->version) {
625                 status->tstamp.tv_nsec *= 1000L;
626                 status->trigger_tstamp.tv_nsec *= 1000L;
627         }
628         return 0;
629 }
630
631 static snd_pcm_state_t snd_pcm_hw_state(snd_pcm_t *pcm)
632 {
633         snd_pcm_hw_t *hw = pcm->private_data;
634         /* the -ENODEV may come from the snd_disconnect_ioctl() or
635            snd_power_wait() in kernel */
636         if (query_status_data(hw) == -ENODEV)
637                 return SND_PCM_STATE_DISCONNECTED;
638         return (snd_pcm_state_t) hw->mmap_status->state;
639 }
640
641 static int snd_pcm_hw_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
642 {
643         snd_pcm_hw_t *hw = pcm->private_data;
644         int fd = hw->fd, err;
645         if (ioctl(fd, SNDRV_PCM_IOCTL_DELAY, delayp) < 0) {
646                 err = -errno;
647                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_DELAY failed (%i)", err);
648                 return err;
649         }
650         return 0;
651 }
652
653 static int snd_pcm_hw_hwsync(snd_pcm_t *pcm)
654 {
655         snd_pcm_hw_t *hw = pcm->private_data;
656         int fd = hw->fd, err;
657         if (SNDRV_PROTOCOL_VERSION(2, 0, 3) <= hw->version) {
658                 if (hw->mmap_status_fallbacked) {
659                         err = request_hwsync(hw);
660                         if (err < 0)
661                                 return err;
662                 } else {
663                         if (ioctl(fd, SNDRV_PCM_IOCTL_HWSYNC) < 0) {
664                                 err = -errno;
665                                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_HWSYNC failed (%i)", err);
666                                 return err;
667                         }
668                 }
669         } else {
670                 snd_pcm_sframes_t delay;
671                 int err = snd_pcm_hw_delay(pcm, &delay);
672                 if (err < 0) {
673                         switch (FAST_PCM_STATE(hw)) {
674                         case SND_PCM_STATE_PREPARED:
675                         case SND_PCM_STATE_SUSPENDED:
676                                 return 0;
677                         default:
678                                 return err;
679                         }
680                 }
681         }
682         return 0;
683 }
684
685 static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
686 {
687         snd_pcm_hw_t *hw = pcm->private_data;
688         snd_pcm_sw_params_t sw_params;
689         int fd = hw->fd, err;
690
691         if (hw->prepare_reset_sw_params) {
692                 snd_pcm_sw_params_current_no_lock(pcm, &sw_params);
693                 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sw_params) < 0) {
694                         err = -errno;
695                         snd_checknum(PCM, "SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
696                         return err;
697                 }
698                 hw->prepare_reset_sw_params = false;
699         }
700         if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE) < 0) {
701                 err = -errno;
702                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_PREPARE failed (%i)", err);
703                 return err;
704         }
705         return query_status_and_control_data(hw);
706 }
707
708 static int snd_pcm_hw_reset(snd_pcm_t *pcm)
709 {
710         snd_pcm_hw_t *hw = pcm->private_data;
711         int fd = hw->fd, err;
712         if (ioctl(fd, SNDRV_PCM_IOCTL_RESET) < 0) {
713                 err = -errno;
714                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_RESET failed (%i)", err);
715                 return err;
716         }
717         return query_status_and_control_data(hw);
718 }
719
720 static int snd_pcm_hw_start(snd_pcm_t *pcm)
721 {
722         snd_pcm_hw_t *hw = pcm->private_data;
723         int err;
724 #if 0
725         assert(pcm->stream != SND_PCM_STREAM_PLAYBACK ||
726                snd_pcm_mmap_playback_hw_avail(pcm) > 0);
727 #endif
728         issue_applptr(hw);
729         if (ioctl(hw->fd, SNDRV_PCM_IOCTL_START) < 0) {
730                 err = -errno;
731                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_START failed (%i)", err);
732 #if 0
733                 if (err == -EBADFD)
734                         snd_error(PCM, "PCM state = %s", snd_pcm_state_name(snd_pcm_hw_state(pcm)));
735 #endif
736                 return err;
737         }
738         return 0;
739 }
740
741 static int snd_pcm_hw_drop(snd_pcm_t *pcm)
742 {
743         snd_pcm_hw_t *hw = pcm->private_data;
744         int err;
745         if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DROP) < 0) {
746                 err = -errno;
747                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_DROP failed (%i)", err);
748                 return err;
749         } else {
750         }
751         return 0;
752 }
753
754 static int snd_pcm_hw_drain(snd_pcm_t *pcm)
755 {
756         snd_pcm_hw_t *hw = pcm->private_data;
757         snd_pcm_sw_params_t sw_params;
758         snd_pcm_uframes_t silence_size;
759         int err;
760
761         if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
762                 goto __skip_silence;
763         /* stream probably in SETUP, prevent divide by zero */
764         if (pcm->period_size == 0)
765                 goto __skip_silence;
766         if (hw->drain_silence == 0 || hw->perfect_drain)
767                 goto __skip_silence;
768         snd_pcm_sw_params_current_no_lock(pcm, &sw_params);
769         if (hw->drain_silence > 0) {
770                 silence_size = (pcm->rate * hw->drain_silence) / 1000;
771                 goto __manual_silence;
772         }
773         /* compute end silence size, align to period size + extra time */
774         if ((pcm->boundary % pcm->period_size) == 0) {
775                 silence_size = pcm->period_size - (*pcm->appl.ptr % pcm->period_size);
776                 if (silence_size == pcm->period_size)
777                         silence_size = 0;
778         } else {
779                 /* it not not easy to compute the period crossing point
780                  * in this case because the period is not aligned to the boundary
781                  * - use the full range (one period) in this case
782                  */
783                 silence_size = pcm->period_size;
784         }
785         silence_size += pcm->rate / 10; /* 1/10th of second */
786 __manual_silence:
787         if (sw_params.silence_size < silence_size) {
788                 /* fill the silence soon as possible (in the bellow ioctl
789                  * or the next period wake up)
790                  */
791                 sw_params.silence_threshold = pcm->buffer_size;
792                 if (silence_size > pcm->buffer_size)
793                         silence_size = pcm->buffer_size;
794                 sw_params.silence_size = silence_size;
795                 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sw_params) < 0) {
796                         err = -errno;
797                         snd_checknum(PCM, "SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
798                         return err;
799                 }
800                 hw->prepare_reset_sw_params = true;
801         }
802 __skip_silence:
803         if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DRAIN) < 0) {
804                 err = -errno;
805                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_DRAIN failed (%i)", err);
806                 return err;
807         }
808         return 0;
809 }
810
811 static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable)
812 {
813         snd_pcm_hw_t *hw = pcm->private_data;
814         int err;
815         if (ioctl(hw->fd, SNDRV_PCM_IOCTL_PAUSE, enable) < 0) {
816                 err = -errno;
817                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_PAUSE failed (%i)", err);
818                 return err;
819         }
820         return 0;
821 }
822
823 static snd_pcm_sframes_t snd_pcm_hw_rewindable(snd_pcm_t *pcm)
824 {
825         return snd_pcm_mmap_hw_rewindable(pcm);
826 }
827
828 static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
829 {
830         snd_pcm_hw_t *hw = pcm->private_data;
831         int err;
832         if (ioctl(hw->fd, SNDRV_PCM_IOCTL_REWIND, &frames) < 0) {
833                 err = -errno;
834                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_REWIND failed (%i)", err);
835                 return err;
836         }
837         err = query_status_and_control_data(hw);
838         if (err < 0)
839                 return err;
840         return frames;
841 }
842
843 static snd_pcm_sframes_t snd_pcm_hw_forwardable(snd_pcm_t *pcm)
844 {
845         return snd_pcm_mmap_avail(pcm);
846 }
847
848 static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
849 {
850         snd_pcm_hw_t *hw = pcm->private_data;
851         int err;
852         if (SNDRV_PROTOCOL_VERSION(2, 0, 4) <= hw->version) {
853                 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_FORWARD, &frames) < 0) {
854                         err = -errno;
855                         snd_checknum(PCM, "SNDRV_PCM_IOCTL_FORWARD failed (%i)", err);
856                         return err;
857                 }
858                 err = query_status_and_control_data(hw);
859                 if (err < 0)
860                         return err;
861                 return frames;
862         } else {
863                 snd_pcm_sframes_t avail;
864
865                 switch (FAST_PCM_STATE(hw)) {
866                 case SNDRV_PCM_STATE_RUNNING:
867                 case SNDRV_PCM_STATE_DRAINING:
868                 case SNDRV_PCM_STATE_PAUSED:
869                 case SNDRV_PCM_STATE_PREPARED:
870                         break;
871                 case SNDRV_PCM_STATE_XRUN:
872                         return -EPIPE;
873                 default:
874                         return -EBADFD;
875                 }
876                 avail = snd_pcm_mmap_avail(pcm);
877                 if (avail < 0)
878                         return 0;
879                 if (frames > (snd_pcm_uframes_t)avail)
880                         frames = avail;
881                 snd_pcm_mmap_appl_forward(pcm, frames);
882                 return frames;
883         }
884 }
885
886 static int snd_pcm_hw_resume(snd_pcm_t *pcm)
887 {
888         snd_pcm_hw_t *hw = pcm->private_data;
889         int fd = hw->fd, err;
890         if (ioctl(fd, SNDRV_PCM_IOCTL_RESUME) < 0) {
891                 err = -errno;
892                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_RESUME failed (%i)", err);
893                 return err;
894         }
895         return 0;
896 }
897
898 static int hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
899 {
900         snd_pcm_hw_t *hw1 = pcm1->private_data;
901         snd_pcm_hw_t *hw2 = pcm2->private_data;
902         if (ioctl(hw1->fd, SNDRV_PCM_IOCTL_LINK, hw2->fd) < 0) {
903                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_LINK failed (%i)", -errno);
904                 return -errno;
905         }
906         return 0;
907 }
908
909 static int snd_pcm_hw_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
910 {
911         if (master->type != SND_PCM_TYPE_HW) {
912                 snd_checknum(PCM, "Invalid type for SNDRV_PCM_IOCTL_LINK (%i)", master->type);
913                 return -EINVAL;
914         }
915         return hw_link(master, pcm);
916 }
917
918 static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
919 {
920         if (pcm2->type != SND_PCM_TYPE_HW) {
921                 if (pcm2->fast_ops->link_slaves)
922                         return pcm2->fast_ops->link_slaves(pcm2->fast_op_arg, pcm1);
923                 return -ENOSYS;
924         }
925         return hw_link(pcm1, pcm2);
926  }
927
928 static int snd_pcm_hw_unlink(snd_pcm_t *pcm)
929 {
930         snd_pcm_hw_t *hw = pcm->private_data;
931
932         if (ioctl(hw->fd, SNDRV_PCM_IOCTL_UNLINK) < 0) {
933                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_UNLINK failed (%i)", -errno);
934                 return -errno;
935         }
936         return 0;
937 }
938
939 static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
940 {
941         int err;
942         snd_pcm_hw_t *hw = pcm->private_data;
943         int fd = hw->fd;
944         struct snd_xferi xferi;
945         xferi.buf = (char*) buffer;
946         xferi.frames = size;
947         xferi.result = 0; /* make valgrind happy */
948         if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi) < 0)
949                 err = -errno;
950         else
951                 err = query_status_and_control_data(hw);
952 #ifdef DEBUG_RW
953         fprintf(stderr, "hw_writei: frames = %li, xferi.result = %li, err = %i\n", size, xferi.result, err);
954 #endif
955         if (err < 0)
956                 return snd_pcm_check_error(pcm, err);
957         return xferi.result;
958 }
959
960 static snd_pcm_sframes_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
961 {
962         int err;
963         snd_pcm_hw_t *hw = pcm->private_data;
964         int fd = hw->fd;
965         struct snd_xfern xfern;
966         memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
967         xfern.bufs = bufs;
968         xfern.frames = size;
969         if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern) < 0)
970                 err = -errno;
971         else
972                 err = query_status_and_control_data(hw);
973 #ifdef DEBUG_RW
974         fprintf(stderr, "hw_writen: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
975 #endif
976         if (err < 0)
977                 return snd_pcm_check_error(pcm, err);
978         return xfern.result;
979 }
980
981 static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
982 {
983         int err;
984         snd_pcm_hw_t *hw = pcm->private_data;
985         int fd = hw->fd;
986         struct snd_xferi xferi;
987         xferi.buf = buffer;
988         xferi.frames = size;
989         xferi.result = 0; /* make valgrind happy */
990         if (ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi) < 0)
991                 err = -errno;
992         else
993                 err = query_status_and_control_data(hw);
994 #ifdef DEBUG_RW
995         fprintf(stderr, "hw_readi: frames = %li, result = %li, err = %i\n", size, xferi.result, err);
996 #endif
997         if (err < 0)
998                 return snd_pcm_check_error(pcm, err);
999         return xferi.result;
1000 }
1001
1002 static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
1003 {
1004         int err;
1005         snd_pcm_hw_t *hw = pcm->private_data;
1006         int fd = hw->fd;
1007         struct snd_xfern xfern;
1008         memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
1009         xfern.bufs = bufs;
1010         xfern.frames = size;
1011         if (ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern) < 0)
1012                 err = -errno;
1013         else
1014                 err = query_status_and_control_data(hw);
1015 #ifdef DEBUG_RW
1016         fprintf(stderr, "hw_readn: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
1017 #endif
1018         if (err < 0)
1019                 return snd_pcm_check_error(pcm, err);
1020         return xfern.result;
1021 }
1022
1023 static bool map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr,
1024                             bool force_fallback)
1025 {
1026         struct snd_pcm_mmap_status *mmap_status;
1027         bool fallbacked;
1028
1029         mmap_status = MAP_FAILED;
1030         if (!force_fallback) {
1031                 mmap_status = mmap(NULL, page_align(sizeof(*mmap_status)),
1032                                    PROT_READ, MAP_FILE|MAP_SHARED,
1033                                    hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
1034         }
1035
1036         if (mmap_status == MAP_FAILED || mmap_status == NULL) {
1037                 mmap_status = &sync_ptr->s.status;
1038                 fallbacked = true;
1039         } else {
1040                 fallbacked = false;
1041         }
1042
1043         hw->mmap_status = mmap_status;
1044
1045         return fallbacked;
1046 }
1047
1048 static bool map_control_data(snd_pcm_hw_t *hw,
1049                              struct snd_pcm_sync_ptr *sync_ptr,
1050                              bool force_fallback)
1051 {
1052         struct snd_pcm_mmap_control *mmap_control;
1053         bool fallbacked;
1054
1055         mmap_control = MAP_FAILED;
1056         if (!force_fallback) {
1057                 mmap_control = mmap(NULL, page_align(sizeof(*mmap_control)),
1058                                     PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
1059                                     hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
1060         }
1061
1062         if (mmap_control == MAP_FAILED || mmap_control == NULL) {
1063                 mmap_control = &sync_ptr->c.control;
1064                 fallbacked = true;
1065         } else {
1066                 fallbacked = false;
1067         }
1068
1069         hw->mmap_control = mmap_control;
1070
1071         return fallbacked;
1072 }
1073
1074 static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback)
1075 {
1076         snd_pcm_hw_t *hw = pcm->private_data;
1077         struct snd_pcm_sync_ptr *sync_ptr;
1078         int err;
1079
1080         /* Preparation for fallback to failure of mmap(2). */
1081         sync_ptr = malloc(sizeof(*sync_ptr));
1082         if (sync_ptr == NULL)
1083                 return -ENOMEM;
1084         memset(sync_ptr, 0, sizeof(*sync_ptr));
1085
1086         hw->mmap_status_fallbacked =
1087                         map_status_data(hw, sync_ptr, force_fallback);
1088         hw->mmap_control_fallbacked =
1089                         map_control_data(hw, sync_ptr, force_fallback);
1090
1091         /* Any fallback mode needs to keep the buffer. */
1092         if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked) {
1093                 hw->sync_ptr = sync_ptr;
1094         } else {
1095                 free(sync_ptr);
1096                 hw->sync_ptr = NULL;
1097         }
1098
1099         /* do not initialize in case of append and keep the values from the
1100          * kernel
1101          */
1102         if (!(pcm->mode & SND_PCM_APPEND)) {
1103                 /* Initialize the data. */
1104                 hw->mmap_control->appl_ptr = 0;
1105                 hw->mmap_control->avail_min = 1;
1106         }
1107         snd_pcm_set_hw_ptr(pcm, &hw->mmap_status->hw_ptr, hw->fd,
1108                            SNDRV_PCM_MMAP_OFFSET_STATUS +
1109                                 offsetof(struct snd_pcm_mmap_status, hw_ptr));
1110         snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd,
1111                              SNDRV_PCM_MMAP_OFFSET_CONTROL);
1112         if (hw->mmap_control_fallbacked) {
1113                 unsigned int flags = 0;
1114                 /* read appl_ptr and avail_min from kernel when device opened
1115                  * with SND_PCM_APPEND flag
1116                  */
1117                 if (pcm->mode & SND_PCM_APPEND)
1118                         flags = SNDRV_PCM_SYNC_PTR_APPL |
1119                                 SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
1120                 err = sync_ptr1(hw, flags);
1121                 if (err < 0)
1122                         return err;
1123         }
1124
1125         return 0;
1126 }
1127
1128 static void unmap_status_data(snd_pcm_hw_t *hw)
1129 {
1130         if (!hw->mmap_status_fallbacked) {
1131                 if (munmap((void *)hw->mmap_status,
1132                            page_align(sizeof(*hw->mmap_status))) < 0)
1133                         snd_checknum(PCM, "status munmap failed (%u)", errno);
1134         }
1135 }
1136
1137 static void unmap_control_data(snd_pcm_hw_t *hw)
1138 {
1139         if (!hw->mmap_control_fallbacked) {
1140                 if (munmap((void *)hw->mmap_control,
1141                            page_align(sizeof(*hw->mmap_control))) < 0)
1142                         snd_checknum(PCM, "control munmap failed (%u)", errno);
1143         }
1144 }
1145
1146 static void unmap_status_and_control_data(snd_pcm_hw_t *hw)
1147 {
1148         unmap_status_data(hw);
1149         unmap_control_data(hw);
1150
1151         if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked)
1152                 free(hw->sync_ptr);
1153
1154         hw->mmap_status = NULL;
1155         hw->mmap_control = NULL;
1156         hw->mmap_status_fallbacked = false;
1157         hw->mmap_control_fallbacked = false;
1158         hw->sync_ptr = NULL;
1159 }
1160
1161 static int snd_pcm_hw_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1162 {
1163         return 0;
1164 }
1165
1166 static int snd_pcm_hw_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1167 {
1168         return 0;
1169 }
1170
1171 static int snd_pcm_hw_close(snd_pcm_t *pcm)
1172 {
1173         snd_pcm_hw_t *hw = pcm->private_data;
1174         int err = 0;
1175         if (close(hw->fd)) {
1176                 err = -errno;
1177                 snd_checknum(PCM, "close failed (%i)", err);
1178         }
1179
1180         unmap_status_and_control_data(hw);
1181
1182         free(hw);
1183         return err;
1184 }
1185
1186 static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
1187                                                 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
1188                                                 snd_pcm_uframes_t size)
1189 {
1190         snd_pcm_hw_t *hw = pcm->private_data;
1191
1192         snd_pcm_mmap_appl_forward(pcm, size);
1193         issue_applptr(hw);
1194 #ifdef DEBUG_MMAP
1195         fprintf(stderr, "appl_forward: hw_ptr = %li, appl_ptr = %li, size = %li\n", *pcm->hw.ptr, *pcm->appl.ptr, size);
1196 #endif
1197         return size;
1198 }
1199
1200 static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
1201 {
1202         snd_pcm_hw_t *hw = pcm->private_data;
1203         snd_pcm_uframes_t avail;
1204
1205         query_status_data(hw);
1206         avail = snd_pcm_mmap_avail(pcm);
1207         switch (FAST_PCM_STATE(hw)) {
1208         case SNDRV_PCM_STATE_RUNNING:
1209                 if (avail >= pcm->stop_threshold) {
1210                         /* SNDRV_PCM_IOCTL_XRUN ioctl has been implemented since PCM kernel API 2.0.1 */
1211                         if (SNDRV_PROTOCOL_VERSION(2, 0, 1) <= hw->version) {
1212                                 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_XRUN) < 0)
1213                                         return -errno;
1214                         }
1215                         /* everything is ok, state == SND_PCM_STATE_XRUN at the moment */
1216                         return -EPIPE;
1217                 }
1218                 break;
1219         case SNDRV_PCM_STATE_XRUN:
1220                 return -EPIPE;
1221         default:
1222                 break;
1223         }
1224         return avail;
1225 }
1226
1227 static int snd_pcm_hw_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
1228                                  snd_htimestamp_t *tstamp)
1229 {
1230         snd_pcm_sframes_t avail1;
1231         int ok = 0;
1232
1233         /* unfortunately, loop is necessary to ensure valid timestamp */
1234         while (1) {
1235                 avail1 = snd_pcm_hw_avail_update(pcm);
1236                 if (avail1 < 0)
1237                         return avail1;
1238                 if (ok && (snd_pcm_uframes_t)avail1 == *avail)
1239                         break;
1240                 *avail = avail1;
1241                 *tstamp = snd_pcm_hw_fast_tstamp(pcm);
1242                 ok = 1;
1243         }
1244         return 0;
1245 }
1246
1247 static void __fill_chmap_ctl_id(snd_ctl_elem_id_t *id, int dev, int subdev,
1248                                 int stream)
1249 {
1250         snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1251         if (stream == SND_PCM_STREAM_PLAYBACK)
1252                 snd_ctl_elem_id_set_name(id, "Playback Channel Map");
1253         else
1254                 snd_ctl_elem_id_set_name(id, "Capture Channel Map");
1255         snd_ctl_elem_id_set_device(id, dev);
1256         snd_ctl_elem_id_set_index(id, subdev);
1257 }
1258
1259 static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
1260 {
1261         snd_pcm_hw_t *hw = pcm->private_data;
1262         __fill_chmap_ctl_id(id, hw->device, hw->subdevice, pcm->stream);
1263 }
1264
1265 static int is_chmap_type(int type)
1266 {
1267         return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
1268                 type <= SND_CTL_TLVT_CHMAP_PAIRED);
1269 }
1270
1271 /**
1272  * \!brief Query the available channel maps
1273  * \param card the card number
1274  * \param dev the PCM device number
1275  * \param subdev the PCM substream index
1276  * \param stream the direction of PCM stream
1277  * \return the NULL-terminated array of integer pointers, or NULL at error.
1278  *
1279  * This function works like snd_pcm_query_chmaps() but it takes the card,
1280  * device, substream and stream numbers instead of the already opened
1281  * snd_pcm_t instance, so that you can query available channel maps of
1282  * a PCM before actually opening it.
1283  *
1284  * As the parameters stand, the query is performed only to the hw PCM
1285  * devices, not the abstracted PCM object in alsa-lib.
1286  */
1287 snd_pcm_chmap_query_t **
1288 snd_pcm_query_chmaps_from_hw(int card, int dev, int subdev,
1289                              snd_pcm_stream_t stream)
1290 {
1291         snd_ctl_t *ctl;
1292         snd_ctl_elem_id_t id = {0};
1293         unsigned int tlv[2048], *start;
1294         unsigned int type;
1295         snd_pcm_chmap_query_t **map;
1296         int i, ret, nums;
1297
1298         ret = snd_ctl_hw_open(&ctl, NULL, card, 0);
1299         if (ret < 0) {
1300                 snd_checknum(PCM, "Cannot open the associated CTL");
1301                 return NULL;
1302         }
1303
1304         __fill_chmap_ctl_id(&id, dev, subdev, stream);
1305         ret = snd_ctl_elem_tlv_read(ctl, &id, tlv, sizeof(tlv));
1306         snd_ctl_close(ctl);
1307         if (ret < 0) {
1308                 snd_checknum(PCM, "Cannot read Channel Map TLV");
1309                 return NULL;
1310         }
1311
1312 #if 0
1313         for (i = 0; i < 32; i++)
1314                 fprintf(stderr, "%02x: %08x\n", i, tlv[i]);
1315 #endif
1316         /* FIXME: the parser below assumes that the TLV only contains
1317          * chmap-related blocks
1318          */
1319         type = tlv[SNDRV_CTL_TLVO_TYPE];
1320         if (type != SND_CTL_TLVT_CONTAINER) {
1321                 if (!is_chmap_type(type)) {
1322                         snd_checknum(PCM, "Invalid TLV type %d", type);
1323                         return NULL;
1324                 }
1325                 start = tlv;
1326                 nums = 1;
1327         } else {
1328                 unsigned int *p;
1329                 int size;
1330                 start = tlv + 2;
1331                 size = tlv[SNDRV_CTL_TLVO_LEN];
1332                 nums = 0;
1333                 for (p = start; size > 0; ) {
1334                         if (!is_chmap_type(p[0])) {
1335                                 snd_checknum(PCM, "Invalid TLV type %d", p[0]);
1336                                 return NULL;
1337                         }
1338                         nums++;
1339                         size -= p[1] + 8;
1340                         p += p[1] / 4 + 2;
1341                 }
1342         }
1343         map = calloc(nums + 1, sizeof(int *));
1344         if (!map)
1345                 return NULL;
1346         for (i = 0; i < nums; i++) {
1347                 map[i] = malloc(start[1] + 8);
1348                 if (!map[i]) {
1349                         snd_pcm_free_chmaps(map);
1350                         return NULL;
1351                 }
1352                 map[i]->type = start[0] - 0x100;
1353                 map[i]->map.channels = start[1] / 4;
1354                 memcpy(map[i]->map.pos, start + 2, start[1]);
1355                 start += start[1] / 4 + 2;
1356         }
1357         return map;
1358 }
1359
1360 enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
1361
1362 static int chmap_caps(snd_pcm_hw_t *hw, int type)
1363 {
1364         if (hw->chmap_caps & (1 << type))
1365                 return 1;
1366         if (hw->chmap_caps & (1 << (type + 8)))
1367                 return 0;
1368         return 1;
1369 }
1370
1371 static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
1372 {
1373         hw->chmap_caps |= (1 << type);
1374 }
1375
1376 static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
1377 {
1378         hw->chmap_caps |= (1 << (type + 8));
1379 }
1380
1381 static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
1382 {
1383         snd_pcm_hw_t *hw = pcm->private_data;
1384         snd_pcm_chmap_query_t **map;
1385
1386         if (hw->chmap_override)
1387                 return _snd_pcm_copy_chmap_query(hw->chmap_override);
1388
1389         if (!chmap_caps(hw, CHMAP_CTL_QUERY))
1390                 return NULL;
1391
1392         map = snd_pcm_query_chmaps_from_hw(hw->card, hw->device,
1393                                            hw->subdevice, pcm->stream);
1394         if (map)
1395                 chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
1396         else
1397                 chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
1398         return map;
1399 }
1400
1401 static snd_pcm_chmap_t *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
1402 {
1403         snd_pcm_hw_t *hw = pcm->private_data;
1404         snd_pcm_chmap_t *map;
1405         snd_ctl_t *ctl;
1406         snd_ctl_elem_id_t id = {0};
1407         snd_ctl_elem_value_t val = {0};
1408         unsigned int i;
1409         int ret;
1410
1411         if (hw->chmap_override)
1412                 return _snd_pcm_choose_fixed_chmap(pcm, hw->chmap_override);
1413
1414         if (!chmap_caps(hw, CHMAP_CTL_GET))
1415                 return NULL;
1416
1417         switch (FAST_PCM_STATE(hw)) {
1418         case SNDRV_PCM_STATE_PREPARED:
1419         case SNDRV_PCM_STATE_RUNNING:
1420         case SNDRV_PCM_STATE_XRUN:
1421         case SNDRV_PCM_STATE_DRAINING:
1422         case SNDRV_PCM_STATE_PAUSED:
1423         case SNDRV_PCM_STATE_SUSPENDED:
1424                 break;
1425         default:
1426                 snd_checknum(PCM, "Invalid PCM state for chmap_get: %s",
1427                                   snd_pcm_state_name(FAST_PCM_STATE(hw)));
1428
1429                 return NULL;
1430         }
1431         map = malloc(pcm->channels * sizeof(map->pos[0]) + sizeof(*map));
1432         if (!map)
1433                 return NULL;
1434         map->channels = pcm->channels;
1435         ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
1436         if (ret < 0) {
1437                 free(map);
1438                 snd_checknum(PCM, "Cannot open the associated CTL");
1439                 chmap_caps_set_error(hw, CHMAP_CTL_GET);
1440                 return NULL;
1441         }
1442         fill_chmap_ctl_id(pcm, &id);
1443         snd_ctl_elem_value_set_id(&val, &id);
1444         ret = snd_ctl_elem_read(ctl, &val);
1445         snd_ctl_close(ctl);
1446         if (ret < 0) {
1447                 free(map);
1448                 snd_checknum(PCM, "Cannot read Channel Map ctl");
1449                 chmap_caps_set_error(hw, CHMAP_CTL_GET);
1450                 return NULL;
1451         }
1452         for (i = 0; i < pcm->channels; i++)
1453                 map->pos[i] = snd_ctl_elem_value_get_integer(&val, i);
1454         chmap_caps_set_ok(hw, CHMAP_CTL_GET);
1455         return map;
1456 }
1457
1458 static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
1459 {
1460         snd_pcm_hw_t *hw = pcm->private_data;
1461         snd_ctl_t *ctl;
1462         snd_ctl_elem_id_t id = {0};
1463         snd_ctl_elem_value_t val = {0};
1464         unsigned int i;
1465         int ret;
1466
1467         if (hw->chmap_override)
1468                 return -ENXIO;
1469
1470         if (!chmap_caps(hw, CHMAP_CTL_SET))
1471                 return -ENXIO;
1472
1473         if (map->channels > 128) {
1474                 snd_checknum(PCM, "Invalid number of channels %d", map->channels);
1475                 return -EINVAL;
1476         }
1477         if (FAST_PCM_STATE(hw) != SNDRV_PCM_STATE_PREPARED) {
1478                 snd_checknum(PCM, "Invalid PCM state for chmap_set: %s",
1479                                   snd_pcm_state_name(FAST_PCM_STATE(hw)));
1480
1481                 return -EBADFD;
1482         }
1483         ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
1484         if (ret < 0) {
1485                 snd_checknum(PCM, "Cannot open the associated CTL");
1486                 chmap_caps_set_error(hw, CHMAP_CTL_SET);
1487                 return ret;
1488         }
1489
1490         fill_chmap_ctl_id(pcm, &id);
1491         snd_ctl_elem_value_set_id(&val, &id);
1492         for (i = 0; i < map->channels; i++)
1493                 snd_ctl_elem_value_set_integer(&val, i, map->pos[i]);
1494         ret = snd_ctl_elem_write(ctl, &val);
1495         snd_ctl_close(ctl);
1496         if (ret >= 0)
1497                 chmap_caps_set_ok(hw, CHMAP_CTL_SET);
1498         else if (ret == -ENOENT || ret == -EPERM || ret == -ENXIO) {
1499                 chmap_caps_set_error(hw, CHMAP_CTL_SET);
1500                 ret = -ENXIO;
1501         }
1502         if (ret < 0)
1503                 snd_checknum(PCM, "Cannot write Channel Map ctl");
1504         return ret;
1505 }
1506
1507 static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
1508 {
1509         snd_pcm_hw_t *hw = pcm->private_data;
1510         char *name;
1511         int err = snd_card_get_name(hw->card, &name);
1512         if (err < 0) {
1513                 snd_error(PCM, "cannot get card name");
1514                 return;
1515         }
1516         snd_output_printf(out, "Hardware PCM card %d '%s' device %d subdevice %d\n",
1517                           hw->card, name, hw->device, hw->subdevice);
1518         free(name);
1519         if (pcm->setup) {
1520                 snd_output_printf(out, "Its setup is:\n");
1521                 snd_pcm_dump_setup(pcm, out);
1522                 snd_output_printf(out, "  appl_ptr     : %li\n", hw->mmap_control->appl_ptr);
1523                 snd_output_printf(out, "  hw_ptr       : %li\n", hw->mmap_status->hw_ptr);
1524         }
1525 }
1526
1527 static const snd_pcm_ops_t snd_pcm_hw_ops = {
1528         .close = snd_pcm_hw_close,
1529         .info = snd_pcm_hw_info,
1530         .hw_refine = snd_pcm_hw_hw_refine,
1531         .hw_params = snd_pcm_hw_hw_params,
1532         .hw_free = snd_pcm_hw_hw_free,
1533         .sw_params = snd_pcm_hw_sw_params,
1534         .channel_info = snd_pcm_hw_channel_info,
1535         .dump = snd_pcm_hw_dump,
1536         .nonblock = snd_pcm_hw_nonblock,
1537         .async = snd_pcm_hw_async,
1538         .mmap = snd_pcm_hw_mmap,
1539         .munmap = snd_pcm_hw_munmap,
1540         .query_chmaps = snd_pcm_hw_query_chmaps,
1541         .get_chmap = snd_pcm_hw_get_chmap,
1542         .set_chmap = snd_pcm_hw_set_chmap,
1543 };
1544
1545 static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
1546         .status = snd_pcm_hw_status,
1547         .state = snd_pcm_hw_state,
1548         .hwsync = snd_pcm_hw_hwsync,
1549         .delay = snd_pcm_hw_delay,
1550         .prepare = snd_pcm_hw_prepare,
1551         .reset = snd_pcm_hw_reset,
1552         .start = snd_pcm_hw_start,
1553         .drop = snd_pcm_hw_drop,
1554         .drain = snd_pcm_hw_drain,
1555         .pause = snd_pcm_hw_pause,
1556         .rewindable = snd_pcm_hw_rewindable,
1557         .rewind = snd_pcm_hw_rewind,
1558         .forwardable = snd_pcm_hw_forwardable,
1559         .forward = snd_pcm_hw_forward,
1560         .resume = snd_pcm_hw_resume,
1561         .link = snd_pcm_hw_link,
1562         .link_slaves = snd_pcm_hw_link_slaves,
1563         .unlink = snd_pcm_hw_unlink,
1564         .writei = snd_pcm_hw_writei,
1565         .writen = snd_pcm_hw_writen,
1566         .readi = snd_pcm_hw_readi,
1567         .readn = snd_pcm_hw_readn,
1568         .avail_update = snd_pcm_hw_avail_update,
1569         .mmap_commit = snd_pcm_hw_mmap_commit,
1570         .htimestamp = snd_pcm_hw_htimestamp,
1571         .poll_descriptors = NULL,
1572         .poll_descriptors_count = NULL,
1573         .poll_revents = NULL,
1574 };
1575
1576 static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops_timer = {
1577         .status = snd_pcm_hw_status,
1578         .state = snd_pcm_hw_state,
1579         .hwsync = snd_pcm_hw_hwsync,
1580         .delay = snd_pcm_hw_delay,
1581         .prepare = snd_pcm_hw_prepare,
1582         .reset = snd_pcm_hw_reset,
1583         .start = snd_pcm_hw_start,
1584         .drop = snd_pcm_hw_drop,
1585         .drain = snd_pcm_hw_drain,
1586         .pause = snd_pcm_hw_pause,
1587         .rewindable = snd_pcm_hw_rewindable,
1588         .rewind = snd_pcm_hw_rewind,
1589         .forwardable = snd_pcm_hw_forwardable,
1590         .forward = snd_pcm_hw_forward,
1591         .resume = snd_pcm_hw_resume,
1592         .link = snd_pcm_hw_link,
1593         .link_slaves = snd_pcm_hw_link_slaves,
1594         .unlink = snd_pcm_hw_unlink,
1595         .writei = snd_pcm_hw_writei,
1596         .writen = snd_pcm_hw_writen,
1597         .readi = snd_pcm_hw_readi,
1598         .readn = snd_pcm_hw_readn,
1599         .avail_update = snd_pcm_hw_avail_update,
1600         .mmap_commit = snd_pcm_hw_mmap_commit,
1601         .htimestamp = snd_pcm_hw_htimestamp,
1602         .poll_descriptors = snd_pcm_hw_poll_descriptors,
1603         .poll_descriptors_count = snd_pcm_hw_poll_descriptors_count,
1604         .poll_revents = snd_pcm_hw_poll_revents,
1605 };
1606
1607 /**
1608  * \brief Creates a new hw PCM
1609  * \param pcmp Returns created PCM handle
1610  * \param name Name of PCM
1611  * \param fd File descriptor
1612  * \param sync_ptr_ioctl Boolean flag for sync_ptr ioctl
1613  * \retval zero on success otherwise a negative error code
1614  * \warning Using of this function might be dangerous in the sense
1615  *          of compatibility reasons. The prototype might be freely
1616  *          changed in future.
1617  */
1618 int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd,
1619                        int sync_ptr_ioctl)
1620 {
1621         int ver, mode;
1622         snd_pcm_tstamp_type_t tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
1623         long fmode;
1624         snd_pcm_t *pcm = NULL;
1625         snd_pcm_hw_t *hw = NULL;
1626         snd_pcm_info_t info;
1627         int ret;
1628
1629         assert(pcmp);
1630
1631         memset(&info, 0, sizeof(info));
1632         if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
1633                 ret = -errno;
1634                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_INFO failed (%i)", ret);
1635                 close(fd);
1636                 return ret;
1637
1638         }
1639
1640         if ((fmode = fcntl(fd, F_GETFL)) < 0) {
1641                 ret = -errno;
1642                 close(fd);
1643                 return ret;
1644         }
1645         mode = 0;
1646         if (fmode & O_NONBLOCK)
1647                 mode |= SND_PCM_NONBLOCK;
1648         if (fmode & O_ASYNC)
1649                 mode |= SND_PCM_ASYNC;
1650         if (fmode & O_APPEND)
1651                 mode |= SND_PCM_APPEND;
1652
1653         if (ioctl(fd, SNDRV_PCM_IOCTL_PVERSION, &ver) < 0) {
1654                 ret = -errno;
1655                 snd_checknum(PCM, "SNDRV_PCM_IOCTL_PVERSION failed (%i)", ret);
1656                 close(fd);
1657                 return ret;
1658         }
1659         if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_PCM_VERSION_MAX))
1660                 return -SND_ERROR_INCOMPATIBLE_VERSION;
1661
1662         if (SNDRV_PROTOCOL_VERSION(2, 0, 14) <= ver) {
1663                 /* inform the protocol version we're supporting */
1664                 unsigned int user_ver = SNDRV_PCM_VERSION;
1665                 if (ioctl(fd, SNDRV_PCM_IOCTL_USER_PVERSION, &user_ver) < 0) {
1666                         ret = -errno;
1667                         snd_check(PCM, "USER_PVERSION failed");
1668                         return ret;
1669                 }
1670         }
1671
1672 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1673         if (SNDRV_PROTOCOL_VERSION(2, 0, 9) <= ver) {
1674                 struct timespec timespec;
1675                 if (clock_gettime(CLOCK_MONOTONIC, &timespec) == 0) {
1676                         if (!(mode & SND_PCM_APPEND)) {
1677                                 int on = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
1678                                 if (ioctl(fd, SNDRV_PCM_IOCTL_TTSTAMP, &on) < 0) {
1679                                         ret = -errno;
1680                                         snd_check(PCM, "TTSTAMP failed");
1681                                         return ret;
1682                                 }
1683                         }
1684                         tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC;
1685                 }
1686         } else
1687 #endif
1688           if (SNDRV_PROTOCOL_VERSION(2, 0, 5) <= ver && !(mode & SND_PCM_APPEND)) {
1689                 int on = 1;
1690                 if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) {
1691                         ret = -errno;
1692                         snd_check(PCM, "TSTAMP failed");
1693                         return ret;
1694                 }
1695         }
1696
1697         hw = calloc(1, sizeof(snd_pcm_hw_t));
1698         if (!hw) {
1699                 close(fd);
1700                 return -ENOMEM;
1701         }
1702
1703         hw->version = ver;
1704         hw->card = info.card;
1705         hw->device = info.device;
1706         hw->subdevice = info.subdevice;
1707         hw->fd = fd;
1708         /* no restriction */
1709         hw->format = SND_PCM_FORMAT_UNKNOWN;
1710         hw->rates.min = hw->rates.max = 0;
1711         hw->channels = 0;
1712
1713         ret = snd_pcm_new(&pcm, SND_PCM_TYPE_HW, name, info.stream, mode);
1714         if (ret < 0) {
1715                 free(hw);
1716                 close(fd);
1717                 return ret;
1718         }
1719
1720         pcm->ops = &snd_pcm_hw_ops;
1721         pcm->fast_ops = &snd_pcm_hw_fast_ops;
1722         pcm->private_data = hw;
1723         pcm->poll_fd = fd;
1724         pcm->poll_events = info.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
1725         pcm->tstamp_type = tstamp_type;
1726 #ifdef THREAD_SAFE_API
1727         pcm->need_lock = 0;     /* hw plugin is thread-safe */
1728 #endif
1729         pcm->own_state_check = 1; /* skip the common state check */
1730
1731         ret = map_status_and_control_data(pcm, !!sync_ptr_ioctl);
1732         if (ret < 0) {
1733                 snd_pcm_close(pcm);
1734                 return ret;
1735         }
1736
1737         *pcmp = pcm;
1738         return 0;
1739 }
1740
1741 /**
1742  * \brief Creates a new hw PCM
1743  * \param pcmp Returns created PCM handle
1744  * \param name Name of PCM
1745  * \param card Number of card
1746  * \param device Number of device
1747  * \param subdevice Number of subdevice
1748  * \param stream PCM Stream
1749  * \param mode PCM Mode
1750  * \param mmap_emulation Obsoleted parameter
1751  * \param sync_ptr_ioctl Use SYNC_PTR ioctl rather than mmap for control structures
1752  * \retval zero on success otherwise a negative error code
1753  * \warning Using of this function might be dangerous in the sense
1754  *          of compatibility reasons. The prototype might be freely
1755  *          changed in future.
1756  */
1757 int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
1758                     int card, int device, int subdevice,
1759                     snd_pcm_stream_t stream, int mode,
1760                     int mmap_emulation ATTRIBUTE_UNUSED,
1761                     int sync_ptr_ioctl)
1762 {
1763         char filename[sizeof(SNDRV_FILE_PCM_STREAM_PLAYBACK) + 20];
1764         const char *filefmt;
1765         int ret = 0, fd = -1;
1766         int attempt = 0;
1767         snd_pcm_info_t info;
1768         int fmode;
1769         snd_ctl_t *ctl;
1770
1771         assert(pcmp);
1772
1773         if ((ret = snd_ctl_hw_open(&ctl, NULL, card, 0)) < 0)
1774                 return ret;
1775
1776         switch (stream) {
1777         case SND_PCM_STREAM_PLAYBACK:
1778                 filefmt = SNDRV_FILE_PCM_STREAM_PLAYBACK;
1779                 break;
1780         case SND_PCM_STREAM_CAPTURE:
1781                 filefmt = SNDRV_FILE_PCM_STREAM_CAPTURE;
1782                 break;
1783         default:
1784                 snd_error(PCM, "invalid stream %d", stream);
1785                 return -EINVAL;
1786         }
1787         sprintf(filename, filefmt, card, device);
1788
1789       __again:
1790         if (attempt++ > 3) {
1791                 ret = -EBUSY;
1792                 goto _err;
1793         }
1794         ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice);
1795         if (ret < 0)
1796                 goto _err;
1797         fmode = O_RDWR;
1798         if (mode & SND_PCM_NONBLOCK)
1799                 fmode |= O_NONBLOCK;
1800         if (mode & SND_PCM_ASYNC)
1801                 fmode |= O_ASYNC;
1802         if (mode & SND_PCM_APPEND)
1803                 fmode |= O_APPEND;
1804         fd = snd_open_device(filename, fmode);
1805         if (fd < 0) {
1806                 ret = -errno;
1807                 snd_checknum(PCM, "open '%s' failed (%i)", filename, ret);
1808                 goto _err;
1809         }
1810         if (subdevice >= 0) {
1811                 memset(&info, 0, sizeof(info));
1812                 if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
1813                         ret = -errno;
1814                         snd_checknum(PCM, "SNDRV_PCM_IOCTL_INFO failed (%i)", ret);
1815                         goto _err;
1816                 }
1817                 if (info.subdevice != (unsigned int) subdevice) {
1818                         close(fd);
1819                         fd = -1;
1820                         goto __again;
1821                 }
1822         }
1823         snd_ctl_close(ctl);
1824         return snd_pcm_hw_open_fd(pcmp, name, fd, sync_ptr_ioctl);
1825        _err:
1826         if (fd >= 0)
1827                 close(fd);
1828         snd_ctl_close(ctl);
1829         return ret;
1830 }
1831
1832 /*! \page pcm_plugins
1833
1834 \section pcm_plugins_hw Plugin: hw
1835
1836 This plugin communicates directly with the ALSA kernel driver. It is a raw
1837 communication without any conversions. The emulation of mmap access can be
1838 optionally enabled, but expect worse latency in the case.
1839
1840 The nonblock option specifies whether the device is opened in a non-blocking
1841 manner.  Note that the blocking behavior for read/write access won't be
1842 changed by this option.  This influences only on the blocking behavior at
1843 opening the device.  If you would like to keep the compatibility with the
1844 older ALSA stuff, turn this option off.
1845
1846 \code
1847 pcm.name {
1848         type hw                 # Kernel PCM
1849         card INT/STR            # Card name (string) or number (integer)
1850         [device INT]            # Device number (default 0)
1851         [subdevice INT]         # Subdevice number (default -1: first available)
1852         [sync_ptr_ioctl BOOL]   # Use SYNC_PTR ioctl rather than the direct mmap access for control structures
1853         [nonblock BOOL]         # Force non-blocking open mode
1854         [format STR]            # Restrict only to the given format
1855         [channels INT]          # Restrict only to the given channels
1856         [rate INT]              # Restrict only to the given rate
1857           or [rate [INT INT]]   # Restrict only to the given rate range (min max)
1858         [chmap MAP]             # Override channel maps; MAP is a string array
1859         [drain_silence INT]     # Add silence in drain (-1 = auto /default/, 0 = off, > 0 milliseconds)
1860 }
1861 \endcode
1862
1863 \subsection pcm_plugins_hw_funcref Function reference
1864
1865 <UL>
1866   <LI>snd_pcm_hw_open()
1867   <LI>_snd_pcm_hw_open()
1868 </UL>
1869
1870 */
1871
1872 /**
1873  * \brief Creates a new hw PCM
1874  * \param pcmp Returns created PCM handle
1875  * \param name Name of PCM
1876  * \param root Root configuration node
1877  * \param conf Configuration node with hw PCM description
1878  * \param stream PCM Stream
1879  * \param mode PCM Mode
1880  * \warning Using of this function might be dangerous in the sense
1881  *          of compatibility reasons. The prototype might be freely
1882  *          changed in future.
1883  */
1884 int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
1885                      snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf,
1886                      snd_pcm_stream_t stream, int mode)
1887 {
1888         snd_config_iterator_t i, next;
1889         long card = -1, device = 0, subdevice = -1;
1890         const char *str;
1891         int err, sync_ptr_ioctl = 0;
1892         int min_rate = 0, max_rate = 0, channels = 0, drain_silence = -1;
1893         snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
1894         snd_config_t *n;
1895         int nonblock = 1; /* non-block per default */
1896         snd_pcm_chmap_query_t **chmap = NULL;
1897         snd_pcm_hw_t *hw;
1898
1899         /* look for defaults.pcm.nonblock definition */
1900         if (snd_config_search(root, "defaults.pcm.nonblock", &n) >= 0) {
1901                 err = snd_config_get_bool(n);
1902                 if (err >= 0)
1903                         nonblock = err;
1904         }
1905         snd_config_for_each(i, next, conf) {
1906                 const char *id;
1907                 n = snd_config_iterator_entry(i);
1908                 if (snd_config_get_id(n, &id) < 0)
1909                         continue;
1910                 if (snd_pcm_conf_generic_id(id))
1911                         continue;
1912                 if (strcmp(id, "card") == 0) {
1913                         err = snd_config_get_card(n);
1914                         if (err < 0)
1915                                 goto fail;
1916                         card = err;
1917                         continue;
1918                 }
1919                 if (strcmp(id, "device") == 0) {
1920                         err = snd_config_get_integer(n, &device);
1921                         if (err < 0) {
1922                                 snd_error(PCM, "Invalid type for %s", id);
1923                                 goto fail;
1924                         }
1925                         continue;
1926                 }
1927                 if (strcmp(id, "subdevice") == 0) {
1928                         err = snd_config_get_integer(n, &subdevice);
1929                         if (err < 0) {
1930                                 snd_error(PCM, "Invalid type for %s", id);
1931                                 goto fail;
1932                         }
1933                         continue;
1934                 }
1935                 if (strcmp(id, "sync_ptr_ioctl") == 0) {
1936                         err = snd_config_get_bool(n);
1937                         if (err < 0)
1938                                 continue;
1939                         sync_ptr_ioctl = err;
1940                         continue;
1941                 }
1942                 if (strcmp(id, "nonblock") == 0) {
1943                         err = snd_config_get_bool(n);
1944                         if (err < 0)
1945                                 continue;
1946                         nonblock = err;
1947                         continue;
1948                 }
1949                 if (strcmp(id, "rate") == 0) {
1950                         long val;
1951                         if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND &&
1952                             snd_config_is_array(n)) {
1953                                 snd_config_t *m;
1954                                 err = snd_config_search(n, "0", &m);
1955                                 if (err < 0) {
1956                                         snd_error(PCM, "array expected for rate compound");
1957                                         goto fail;
1958                                 }
1959                                 err = snd_config_get_integer(m, &val);
1960                                 if (err < 0) {
1961                                         snd_error(PCM, "Invalid type for rate.0");
1962                                         goto fail;
1963                                 }
1964                                 min_rate = max_rate = val;
1965                                 err = snd_config_search(n, "1", &m);
1966                                 if (err >= 0) {
1967                                         err = snd_config_get_integer(m, &val);
1968                                         if (err < 0) {
1969                                                 snd_error(PCM, "Invalid type for rate.0");
1970                                                 goto fail;
1971                                         }
1972                                         max_rate = val;
1973                                 }
1974                         } else {
1975                                 err = snd_config_get_integer(n, &val);
1976                                 if (err < 0) {
1977                                         snd_error(PCM, "Invalid type for %s", id);
1978                                         goto fail;
1979                                 }
1980                                 min_rate = max_rate = val;
1981                         }
1982                         continue;
1983                 }
1984                 if (strcmp(id, "min_rate") == 0) {
1985                         long val;
1986                         err = snd_config_get_integer(n, &val);
1987                         if (err < 0) {
1988                                 snd_error(PCM, "Invalid type for %s", id);
1989                                 goto fail;
1990                         }
1991                         min_rate = val;
1992                         continue;
1993                 }
1994                 if (strcmp(id, "max_rate") == 0) {
1995                         long val;
1996                         err = snd_config_get_integer(n, &val);
1997                         if (err < 0) {
1998                                 snd_error(PCM, "Invalid type for %s", id);
1999                                 goto fail;
2000                         }
2001                         max_rate = val;
2002                         continue;
2003                 }
2004                 if (strcmp(id, "format") == 0) {
2005                         err = snd_config_get_string(n, &str);
2006                         if (err < 0) {
2007                                 snd_error(PCM, "invalid type for %s", id);
2008                                 goto fail;
2009                         }
2010                         format = snd_pcm_format_value(str);
2011                         continue;
2012                 }
2013                 if (strcmp(id, "channels") == 0) {
2014                         long val;
2015                         err = snd_config_get_integer(n, &val);
2016                         if (err < 0) {
2017                                 snd_error(PCM, "Invalid type for %s", id);
2018                                 goto fail;
2019                         }
2020                         channels = val;
2021                         continue;
2022                 }
2023                 if (strcmp(id, "chmap") == 0) {
2024                         snd_pcm_free_chmaps(chmap);
2025                         chmap = _snd_pcm_parse_config_chmaps(n);
2026                         if (!chmap) {
2027                                 snd_error(PCM, "Invalid channel map for %s", id);
2028                                 err = -EINVAL;
2029                                 goto fail;
2030                         }
2031                         continue;
2032                 }
2033                 if (strcmp(id, "drain_silence") == 0) {
2034                         long val;
2035                         err = snd_config_get_integer(n, &val);
2036                         if (err < 0) {
2037                                 snd_error(PCM, "Invalid type for %s", id);
2038                                 goto fail;
2039                         }
2040                         drain_silence = val;
2041                         continue;
2042                 }
2043                 snd_error(PCM, "Unknown field %s", id);
2044                 err = -EINVAL;
2045                 goto fail;
2046         }
2047         if (card < 0) {
2048                 snd_error(PCM, "card is not defined");
2049                 err = -EINVAL;
2050                 goto fail;
2051         }
2052         if ((min_rate < 0) || (max_rate < min_rate)) {
2053                 snd_error(PCM, "min_rate - max_rate configuration invalid");
2054                 err = -EINVAL;
2055                 goto fail;
2056         }
2057         err = snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,
2058                               mode | (nonblock ? SND_PCM_NONBLOCK : 0),
2059                               0, sync_ptr_ioctl);
2060         if (err < 0)
2061                 goto fail;
2062         if (nonblock && ! (mode & SND_PCM_NONBLOCK)) {
2063                 /* revert to blocking mode for read/write access */
2064                 snd_pcm_hw_nonblock(*pcmp, 0);
2065                 (*pcmp)->mode = mode;
2066         } else
2067                 /* make sure the SND_PCM_NO_xxx flags don't get lost on the
2068                  * way */
2069                 (*pcmp)->mode |= mode & (SND_PCM_NO_AUTO_RESAMPLE|
2070                                          SND_PCM_NO_AUTO_CHANNELS|
2071                                          SND_PCM_NO_AUTO_FORMAT|
2072                                          SND_PCM_NO_SOFTVOL);
2073
2074         hw = (*pcmp)->private_data;
2075         if (format != SND_PCM_FORMAT_UNKNOWN)
2076                 hw->format = format;
2077         if (channels > 0)
2078                 hw->channels = channels;
2079         if (min_rate > 0) {
2080                 hw->rates.min = min_rate;
2081                 hw->rates.max = max_rate;
2082         }
2083         if (chmap)
2084                 hw->chmap_override = chmap;
2085         hw->drain_silence = drain_silence;
2086
2087         return 0;
2088
2089 fail:
2090         snd_pcm_free_chmaps(chmap);
2091         return err;
2092 }
2093
2094 #ifndef DOC_HIDDEN
2095 SND_DLSYM_BUILD_VERSION(_snd_pcm_hw_open, SND_PCM_DLSYM_VERSION);
2096 #endif
2097
2098 /*
2099  *  To be removed helpers, but keep binary compatibility at the time
2100  */
2101
2102 #ifndef DOC_HIDDEN
2103 #define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
2104 #define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
2105 #endif
2106
2107 static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params,
2108                                                struct sndrv_pcm_hw_params_old *oparams)
2109 {
2110         unsigned int i;
2111
2112         memset(params, 0, sizeof(*params));
2113         params->flags = oparams->flags;
2114         for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
2115                 params->masks[i].bits[0] = oparams->masks[i];
2116         memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
2117         params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
2118         params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
2119         params->info = oparams->info;
2120         params->msbits = oparams->msbits;
2121         params->rate_num = oparams->rate_num;
2122         params->rate_den = oparams->rate_den;
2123         params->fifo_size = oparams->fifo_size;
2124 }
2125
2126 static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old *oparams,
2127                                              snd_pcm_hw_params_t *params,
2128                                              unsigned int *cmask)
2129 {
2130         unsigned int i, j;
2131
2132         memset(oparams, 0, sizeof(*oparams));
2133         oparams->flags = params->flags;
2134         for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++) {
2135                 oparams->masks[i] = params->masks[i].bits[0];
2136                 for (j = 1; j < sizeof(params->masks[i].bits) / sizeof(unsigned int); j++)
2137                         if (params->masks[i].bits[j]) {
2138                                 *cmask |= 1 << i;
2139                                 break;
2140                         }
2141         }
2142         memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
2143         oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
2144         oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
2145         oparams->info = params->info;
2146         oparams->msbits = params->msbits;
2147         oparams->rate_num = params->rate_num;
2148         oparams->rate_den = params->rate_den;
2149         oparams->fifo_size = params->fifo_size;
2150 }
2151
2152 static int use_old_hw_params_ioctl(int fd, unsigned int cmd, snd_pcm_hw_params_t *params)
2153 {
2154         struct sndrv_pcm_hw_params_old oparams;
2155         unsigned int cmask = 0;
2156         int res;
2157
2158         snd_pcm_hw_convert_to_old_params(&oparams, params, &cmask);
2159         res = ioctl(fd, cmd, &oparams);
2160         snd_pcm_hw_convert_from_old_params(params, &oparams);
2161         params->cmask |= cmask;
2162         return res;
2163 }