4 * \brief PCM HW Plugin Interface
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \author Jaroslav Kysela <perex@perex.cz>
11 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
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.
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.
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
30 #include "pcm_local.h"
31 #include "../control/control_local.h"
32 #include "../timer/timer_local.h"
41 #include <sys/ioctl.h>
44 //#define DEBUG_RW /* use to debug readi/writei/readn/writen */
45 //#define DEBUG_MMAP /* debug mmap_commit */
48 /* entry for static linking */
49 const char *_snd_module_pcm_hw = "";
62 struct sndrv_pcm_hw_params_old {
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];
72 unsigned int rate_num;
73 unsigned int rate_den;
74 sndrv_pcm_uframes_t fifo_size;
75 unsigned char reserved[64];
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)
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;
93 int card, device, subdevice;
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;
101 bool prepare_reset_sw_params;
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;
117 unsigned int chmap_caps;
118 snd_pcm_chmap_query_t **chmap_override;
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)
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)
131 struct timespec snd_pcm_hw_fast_tstamp(snd_pcm_t *pcm)
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;
140 #endif /* DOC_HIDDEN */
142 static int sync_ptr1(snd_pcm_hw_t *hw, unsigned int flags)
145 hw->sync_ptr->flags = flags;
146 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) {
148 snd_checknum(PCM, "SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err);
154 static int issue_avail_min(snd_pcm_hw_t *hw)
156 if (!hw->mmap_control_fallbacked)
159 /* Avoid unexpected change of applptr in kernel space. */
160 return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_APPL);
163 static int issue_applptr(snd_pcm_hw_t *hw)
165 if (!hw->mmap_control_fallbacked)
168 /* Avoid unexpected change of avail_min in kernel space. */
169 return sync_ptr1(hw, SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
172 static int request_hwsync(snd_pcm_hw_t *hw)
174 if (!hw->mmap_status_fallbacked)
178 * Query both of control/status data to avoid unexpected change of
179 * control data in kernel space.
182 SNDRV_PCM_SYNC_PTR_HWSYNC |
183 SNDRV_PCM_SYNC_PTR_APPL |
184 SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
187 static int query_status_and_control_data(snd_pcm_hw_t *hw)
189 if (!hw->mmap_control_fallbacked)
193 * Query both of control/status data to avoid unexpected change of
194 * control data in kernel space.
197 SNDRV_PCM_SYNC_PTR_APPL |
198 SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
201 static int query_status_data(snd_pcm_hw_t *hw)
203 if (!hw->mmap_status_fallbacked)
207 * Query both of control/status data to avoid unexpected change of
208 * control data in kernel space.
211 SNDRV_PCM_SYNC_PTR_APPL |
212 SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
215 static int snd_pcm_hw_clear_timer_queue(snd_pcm_hw_t *hw)
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));
223 snd_timer_tread_t rbuf[4];
224 snd_timer_read(hw->period_timer, rbuf, sizeof(rbuf));
229 static int snd_pcm_hw_poll_descriptors_count(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
234 static int snd_pcm_hw_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int space)
236 snd_pcm_hw_t *hw = pcm->private_data;
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;
247 static int snd_pcm_hw_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned nfds, unsigned short *revents)
249 snd_pcm_hw_t *hw = pcm->private_data;
252 if (nfds != 2 || pfds[0].fd != hw->fd || pfds[1].fd != hw->period_timer_pfd.fd)
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);
263 static int snd_pcm_hw_nonblock(snd_pcm_t *pcm, int nonblock)
266 snd_pcm_hw_t *hw = pcm->private_data;
267 int fd = hw->fd, err;
269 if ((flags = fcntl(fd, F_GETFL)) < 0) {
271 snd_checknum(PCM, "F_GETFL failed (%i)", err);
277 flags &= ~O_NONBLOCK;
278 if (fcntl(fd, F_SETFL, flags) < 0) {
280 snd_checknum(PCM, "F_SETFL for O_NONBLOCK failed (%i)", err);
286 static int snd_pcm_hw_async(snd_pcm_t *pcm, int sig, pid_t pid)
289 snd_pcm_hw_t *hw = pcm->private_data;
290 int fd = hw->fd, err;
292 if ((flags = fcntl(fd, F_GETFL)) < 0) {
294 snd_checknum(PCM, "F_GETFL failed (%i)", err);
301 if (fcntl(fd, F_SETFL, flags) < 0) {
303 snd_checknum(PCM, "F_SETFL for O_ASYNC failed (%i)", err);
308 if (fcntl(fd, F_SETSIG, (long)sig) < 0) {
310 snd_checknum(PCM, "F_SETSIG failed (%i)", err);
313 if (fcntl(fd, F_SETOWN, (long)pid) < 0) {
315 snd_checknum(PCM, "F_SETOWN failed (%i)", err);
321 static int snd_pcm_hw_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
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) {
327 snd_checknum(PCM, "SNDRV_PCM_IOCTL_INFO failed (%i)", err);
330 /* may be configurable (optional) */
331 if (__snd_pcm_info_eld_fixup_check(info))
332 return __snd_pcm_info_eld_fixup(info);
336 static inline int hw_refine_call(snd_pcm_hw_t *pcm_hw, snd_pcm_hw_params_t *params)
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);
344 static int snd_pcm_hw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
346 snd_pcm_hw_t *hw = pcm->private_data;
349 if (hw->format != SND_PCM_FORMAT_UNKNOWN) {
350 err = _snd_pcm_hw_params_set_format(params, hw->format);
354 if (hw->channels > 0) {
355 err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
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);
367 if (hw_refine_call(hw, params) < 0) {
369 // SYSMSG("SNDRV_PCM_IOCTL_HW_REFINE failed");
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;
383 #define hw_param_mask(params,var) \
384 &((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
387 static int hw_params_call(snd_pcm_hw_t *pcm_hw, snd_pcm_hw_params_t *params)
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);
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;
408 static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
410 snd_pcm_hw_t *hw = pcm->private_data;
412 if (hw_params_call(hw, params) < 0) {
414 snd_checknum(PCM, "SNDRV_PCM_IOCTL_HW_PARAMS failed (%i)", err);
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);
425 static void snd_pcm_hw_close_timer(snd_pcm_hw_t *hw)
427 if (hw->period_timer) {
428 snd_timer_close(hw->period_timer);
429 hw->period_timer = NULL;
433 static int snd_pcm_hw_change_timer(snd_pcm_t *pcm, int enable)
435 snd_pcm_hw_t *hw = pcm->private_data;
436 snd_timer_params_t params = {0};
437 unsigned int suspend, resume;
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);
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);
456 if (snd_timer_poll_descriptors_count(hw->period_timer) != 1) {
457 snd_pcm_hw_close_timer(hw);
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;
468 * hacks for older kernel drivers
472 if (ioctl(hw->period_timer_pfd.fd, SNDRV_TIMER_IOCTL_PVERSION, &ver))
473 snd_warn(PCM, "unable to get protocol version");
475 * In older versions, check via poll before read() is
476 * needed because of the confliction between
477 * TIMER_START and FIONBIO ioctls.
479 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 4))
480 hw->period_timer_need_poll = 1;
482 * In older versions, timer uses pause events instead
483 * suspend/resume events.
485 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 5)) {
486 suspend = 1<<SND_TIMER_EVENT_MPAUSE;
487 resume = 1<<SND_TIMER_EVENT_MCONTINUE;
490 snd_timer_params_set_auto_start(¶ms, 1);
491 snd_timer_params_set_ticks(¶ms, 1);
492 INTERNAL(snd_timer_params_set_filter)(¶ms, (1<<SND_TIMER_EVENT_TICK) |
494 err = snd_timer_params(hw->period_timer, ¶ms);
496 snd_pcm_hw_close_timer(hw);
499 err = snd_timer_start(hw->period_timer);
501 snd_pcm_hw_close_timer(hw);
504 pcm->fast_ops = &snd_pcm_hw_fast_ops_timer;
506 snd_pcm_hw_close_timer(hw);
507 pcm->fast_ops = &snd_pcm_hw_fast_ops;
508 hw->period_event = 0;
513 static int snd_pcm_hw_hw_free(snd_pcm_t *pcm)
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) {
520 snd_checknum(PCM, "SNDRV_PCM_IOCTL_HW_FREE failed (%i)", err);
526 static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
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);
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");
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");
556 if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) {
558 snd_checknum(PCM, "SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
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) {
568 snd_check(PCM, "TSTAMP failed");
572 pcm->tstamp_type = params->tstamp_type;
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);
579 hw->period_event = old_period_event;
582 sw_set_period_event(params, old_period_event);
586 static int snd_pcm_hw_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
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) {
594 snd_checknum(PCM, "SNDRV_PCM_IOCTL_CHANNEL_INFO failed (%i)", err);
597 info->channel = i.channel;
599 info->first = i.first;
601 info->type = SND_PCM_AREA_MMAP;
602 info->u.mmap.fd = fd;
603 info->u.mmap.offset = i.offset;
607 static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
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) {
614 snd_checknum(PCM, "SNDRV_PCM_IOCTL_STATUS failed (%i)", err);
618 if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS_EXT, status) < 0) {
620 snd_checknum(PCM, "SNDRV_PCM_IOCTL_STATUS_EXT failed (%i)", err);
624 if (SNDRV_PROTOCOL_VERSION(2, 0, 5) > hw->version) {
625 status->tstamp.tv_nsec *= 1000L;
626 status->trigger_tstamp.tv_nsec *= 1000L;
631 static snd_pcm_state_t snd_pcm_hw_state(snd_pcm_t *pcm)
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;
641 static int snd_pcm_hw_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
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) {
647 snd_checknum(PCM, "SNDRV_PCM_IOCTL_DELAY failed (%i)", err);
653 static int snd_pcm_hw_hwsync(snd_pcm_t *pcm)
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);
663 if (ioctl(fd, SNDRV_PCM_IOCTL_HWSYNC) < 0) {
665 snd_checknum(PCM, "SNDRV_PCM_IOCTL_HWSYNC failed (%i)", err);
670 snd_pcm_sframes_t delay;
671 int err = snd_pcm_hw_delay(pcm, &delay);
673 switch (FAST_PCM_STATE(hw)) {
674 case SND_PCM_STATE_PREPARED:
675 case SND_PCM_STATE_SUSPENDED:
685 static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
687 snd_pcm_hw_t *hw = pcm->private_data;
688 snd_pcm_sw_params_t sw_params;
689 int fd = hw->fd, err;
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) {
695 snd_checknum(PCM, "SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
698 hw->prepare_reset_sw_params = false;
700 if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE) < 0) {
702 snd_checknum(PCM, "SNDRV_PCM_IOCTL_PREPARE failed (%i)", err);
705 return query_status_and_control_data(hw);
708 static int snd_pcm_hw_reset(snd_pcm_t *pcm)
710 snd_pcm_hw_t *hw = pcm->private_data;
711 int fd = hw->fd, err;
712 if (ioctl(fd, SNDRV_PCM_IOCTL_RESET) < 0) {
714 snd_checknum(PCM, "SNDRV_PCM_IOCTL_RESET failed (%i)", err);
717 return query_status_and_control_data(hw);
720 static int snd_pcm_hw_start(snd_pcm_t *pcm)
722 snd_pcm_hw_t *hw = pcm->private_data;
725 assert(pcm->stream != SND_PCM_STREAM_PLAYBACK ||
726 snd_pcm_mmap_playback_hw_avail(pcm) > 0);
729 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_START) < 0) {
731 snd_checknum(PCM, "SNDRV_PCM_IOCTL_START failed (%i)", err);
734 snd_error(PCM, "PCM state = %s", snd_pcm_state_name(snd_pcm_hw_state(pcm)));
741 static int snd_pcm_hw_drop(snd_pcm_t *pcm)
743 snd_pcm_hw_t *hw = pcm->private_data;
745 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DROP) < 0) {
747 snd_checknum(PCM, "SNDRV_PCM_IOCTL_DROP failed (%i)", err);
754 static int snd_pcm_hw_drain(snd_pcm_t *pcm)
756 snd_pcm_hw_t *hw = pcm->private_data;
757 snd_pcm_sw_params_t sw_params;
758 snd_pcm_uframes_t silence_size;
761 if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
763 /* stream probably in SETUP, prevent divide by zero */
764 if (pcm->period_size == 0)
766 if (hw->drain_silence == 0 || hw->perfect_drain)
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;
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)
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
783 silence_size = pcm->period_size;
785 silence_size += pcm->rate / 10; /* 1/10th of second */
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)
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) {
797 snd_checknum(PCM, "SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
800 hw->prepare_reset_sw_params = true;
803 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DRAIN) < 0) {
805 snd_checknum(PCM, "SNDRV_PCM_IOCTL_DRAIN failed (%i)", err);
811 static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable)
813 snd_pcm_hw_t *hw = pcm->private_data;
815 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_PAUSE, enable) < 0) {
817 snd_checknum(PCM, "SNDRV_PCM_IOCTL_PAUSE failed (%i)", err);
823 static snd_pcm_sframes_t snd_pcm_hw_rewindable(snd_pcm_t *pcm)
825 return snd_pcm_mmap_hw_rewindable(pcm);
828 static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
830 snd_pcm_hw_t *hw = pcm->private_data;
832 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_REWIND, &frames) < 0) {
834 snd_checknum(PCM, "SNDRV_PCM_IOCTL_REWIND failed (%i)", err);
837 err = query_status_and_control_data(hw);
843 static snd_pcm_sframes_t snd_pcm_hw_forwardable(snd_pcm_t *pcm)
845 return snd_pcm_mmap_avail(pcm);
848 static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
850 snd_pcm_hw_t *hw = pcm->private_data;
852 if (SNDRV_PROTOCOL_VERSION(2, 0, 4) <= hw->version) {
853 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_FORWARD, &frames) < 0) {
855 snd_checknum(PCM, "SNDRV_PCM_IOCTL_FORWARD failed (%i)", err);
858 err = query_status_and_control_data(hw);
863 snd_pcm_sframes_t avail;
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:
871 case SNDRV_PCM_STATE_XRUN:
876 avail = snd_pcm_mmap_avail(pcm);
879 if (frames > (snd_pcm_uframes_t)avail)
881 snd_pcm_mmap_appl_forward(pcm, frames);
886 static int snd_pcm_hw_resume(snd_pcm_t *pcm)
888 snd_pcm_hw_t *hw = pcm->private_data;
889 int fd = hw->fd, err;
890 if (ioctl(fd, SNDRV_PCM_IOCTL_RESUME) < 0) {
892 snd_checknum(PCM, "SNDRV_PCM_IOCTL_RESUME failed (%i)", err);
898 static int hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
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);
909 static int snd_pcm_hw_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
911 if (master->type != SND_PCM_TYPE_HW) {
912 snd_checknum(PCM, "Invalid type for SNDRV_PCM_IOCTL_LINK (%i)", master->type);
915 return hw_link(master, pcm);
918 static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
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);
925 return hw_link(pcm1, pcm2);
928 static int snd_pcm_hw_unlink(snd_pcm_t *pcm)
930 snd_pcm_hw_t *hw = pcm->private_data;
932 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_UNLINK) < 0) {
933 snd_checknum(PCM, "SNDRV_PCM_IOCTL_UNLINK failed (%i)", -errno);
939 static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
942 snd_pcm_hw_t *hw = pcm->private_data;
944 struct snd_xferi xferi;
945 xferi.buf = (char*) buffer;
947 xferi.result = 0; /* make valgrind happy */
948 if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi) < 0)
951 err = query_status_and_control_data(hw);
953 fprintf(stderr, "hw_writei: frames = %li, xferi.result = %li, err = %i\n", size, xferi.result, err);
956 return snd_pcm_check_error(pcm, err);
960 static snd_pcm_sframes_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
963 snd_pcm_hw_t *hw = pcm->private_data;
965 struct snd_xfern xfern;
966 memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
969 if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern) < 0)
972 err = query_status_and_control_data(hw);
974 fprintf(stderr, "hw_writen: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
977 return snd_pcm_check_error(pcm, err);
981 static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
984 snd_pcm_hw_t *hw = pcm->private_data;
986 struct snd_xferi xferi;
989 xferi.result = 0; /* make valgrind happy */
990 if (ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi) < 0)
993 err = query_status_and_control_data(hw);
995 fprintf(stderr, "hw_readi: frames = %li, result = %li, err = %i\n", size, xferi.result, err);
998 return snd_pcm_check_error(pcm, err);
1002 static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
1005 snd_pcm_hw_t *hw = pcm->private_data;
1007 struct snd_xfern xfern;
1008 memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
1010 xfern.frames = size;
1011 if (ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern) < 0)
1014 err = query_status_and_control_data(hw);
1016 fprintf(stderr, "hw_readn: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
1019 return snd_pcm_check_error(pcm, err);
1020 return xfern.result;
1023 static bool map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr,
1024 bool force_fallback)
1026 struct snd_pcm_mmap_status *mmap_status;
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);
1036 if (mmap_status == MAP_FAILED || mmap_status == NULL) {
1037 mmap_status = &sync_ptr->s.status;
1043 hw->mmap_status = mmap_status;
1048 static bool map_control_data(snd_pcm_hw_t *hw,
1049 struct snd_pcm_sync_ptr *sync_ptr,
1050 bool force_fallback)
1052 struct snd_pcm_mmap_control *mmap_control;
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);
1062 if (mmap_control == MAP_FAILED || mmap_control == NULL) {
1063 mmap_control = &sync_ptr->c.control;
1069 hw->mmap_control = mmap_control;
1074 static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback)
1076 snd_pcm_hw_t *hw = pcm->private_data;
1077 struct snd_pcm_sync_ptr *sync_ptr;
1080 /* Preparation for fallback to failure of mmap(2). */
1081 sync_ptr = malloc(sizeof(*sync_ptr));
1082 if (sync_ptr == NULL)
1084 memset(sync_ptr, 0, sizeof(*sync_ptr));
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);
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;
1096 hw->sync_ptr = NULL;
1099 /* do not initialize in case of append and keep the values from the
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;
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
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);
1128 static void unmap_status_data(snd_pcm_hw_t *hw)
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);
1137 static void unmap_control_data(snd_pcm_hw_t *hw)
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);
1146 static void unmap_status_and_control_data(snd_pcm_hw_t *hw)
1148 unmap_status_data(hw);
1149 unmap_control_data(hw);
1151 if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked)
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;
1161 static int snd_pcm_hw_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1166 static int snd_pcm_hw_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1171 static int snd_pcm_hw_close(snd_pcm_t *pcm)
1173 snd_pcm_hw_t *hw = pcm->private_data;
1175 if (close(hw->fd)) {
1177 snd_checknum(PCM, "close failed (%i)", err);
1180 unmap_status_and_control_data(hw);
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)
1190 snd_pcm_hw_t *hw = pcm->private_data;
1192 snd_pcm_mmap_appl_forward(pcm, size);
1195 fprintf(stderr, "appl_forward: hw_ptr = %li, appl_ptr = %li, size = %li\n", *pcm->hw.ptr, *pcm->appl.ptr, size);
1200 static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
1202 snd_pcm_hw_t *hw = pcm->private_data;
1203 snd_pcm_uframes_t avail;
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)
1215 /* everything is ok, state == SND_PCM_STATE_XRUN at the moment */
1219 case SNDRV_PCM_STATE_XRUN:
1227 static int snd_pcm_hw_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
1228 snd_htimestamp_t *tstamp)
1230 snd_pcm_sframes_t avail1;
1233 /* unfortunately, loop is necessary to ensure valid timestamp */
1235 avail1 = snd_pcm_hw_avail_update(pcm);
1238 if (ok && (snd_pcm_uframes_t)avail1 == *avail)
1241 *tstamp = snd_pcm_hw_fast_tstamp(pcm);
1247 static void __fill_chmap_ctl_id(snd_ctl_elem_id_t *id, int dev, int subdev,
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");
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);
1259 static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
1261 snd_pcm_hw_t *hw = pcm->private_data;
1262 __fill_chmap_ctl_id(id, hw->device, hw->subdevice, pcm->stream);
1265 static int is_chmap_type(int type)
1267 return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
1268 type <= SND_CTL_TLVT_CHMAP_PAIRED);
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.
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.
1284 * As the parameters stand, the query is performed only to the hw PCM
1285 * devices, not the abstracted PCM object in alsa-lib.
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)
1292 snd_ctl_elem_id_t id = {0};
1293 unsigned int tlv[2048], *start;
1295 snd_pcm_chmap_query_t **map;
1298 ret = snd_ctl_hw_open(&ctl, NULL, card, 0);
1300 snd_checknum(PCM, "Cannot open the associated CTL");
1304 __fill_chmap_ctl_id(&id, dev, subdev, stream);
1305 ret = snd_ctl_elem_tlv_read(ctl, &id, tlv, sizeof(tlv));
1308 snd_checknum(PCM, "Cannot read Channel Map TLV");
1313 for (i = 0; i < 32; i++)
1314 fprintf(stderr, "%02x: %08x\n", i, tlv[i]);
1316 /* FIXME: the parser below assumes that the TLV only contains
1317 * chmap-related blocks
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);
1331 size = tlv[SNDRV_CTL_TLVO_LEN];
1333 for (p = start; size > 0; ) {
1334 if (!is_chmap_type(p[0])) {
1335 snd_checknum(PCM, "Invalid TLV type %d", p[0]);
1343 map = calloc(nums + 1, sizeof(int *));
1346 for (i = 0; i < nums; i++) {
1347 map[i] = malloc(start[1] + 8);
1349 snd_pcm_free_chmaps(map);
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;
1360 enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
1362 static int chmap_caps(snd_pcm_hw_t *hw, int type)
1364 if (hw->chmap_caps & (1 << type))
1366 if (hw->chmap_caps & (1 << (type + 8)))
1371 static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
1373 hw->chmap_caps |= (1 << type);
1376 static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
1378 hw->chmap_caps |= (1 << (type + 8));
1381 static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
1383 snd_pcm_hw_t *hw = pcm->private_data;
1384 snd_pcm_chmap_query_t **map;
1386 if (hw->chmap_override)
1387 return _snd_pcm_copy_chmap_query(hw->chmap_override);
1389 if (!chmap_caps(hw, CHMAP_CTL_QUERY))
1392 map = snd_pcm_query_chmaps_from_hw(hw->card, hw->device,
1393 hw->subdevice, pcm->stream);
1395 chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
1397 chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
1401 static snd_pcm_chmap_t *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
1403 snd_pcm_hw_t *hw = pcm->private_data;
1404 snd_pcm_chmap_t *map;
1406 snd_ctl_elem_id_t id = {0};
1407 snd_ctl_elem_value_t val = {0};
1411 if (hw->chmap_override)
1412 return _snd_pcm_choose_fixed_chmap(pcm, hw->chmap_override);
1414 if (!chmap_caps(hw, CHMAP_CTL_GET))
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:
1426 snd_checknum(PCM, "Invalid PCM state for chmap_get: %s",
1427 snd_pcm_state_name(FAST_PCM_STATE(hw)));
1431 map = malloc(pcm->channels * sizeof(map->pos[0]) + sizeof(*map));
1434 map->channels = pcm->channels;
1435 ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
1438 snd_checknum(PCM, "Cannot open the associated CTL");
1439 chmap_caps_set_error(hw, CHMAP_CTL_GET);
1442 fill_chmap_ctl_id(pcm, &id);
1443 snd_ctl_elem_value_set_id(&val, &id);
1444 ret = snd_ctl_elem_read(ctl, &val);
1448 snd_checknum(PCM, "Cannot read Channel Map ctl");
1449 chmap_caps_set_error(hw, CHMAP_CTL_GET);
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);
1458 static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
1460 snd_pcm_hw_t *hw = pcm->private_data;
1462 snd_ctl_elem_id_t id = {0};
1463 snd_ctl_elem_value_t val = {0};
1467 if (hw->chmap_override)
1470 if (!chmap_caps(hw, CHMAP_CTL_SET))
1473 if (map->channels > 128) {
1474 snd_checknum(PCM, "Invalid number of channels %d", map->channels);
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)));
1483 ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
1485 snd_checknum(PCM, "Cannot open the associated CTL");
1486 chmap_caps_set_error(hw, CHMAP_CTL_SET);
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);
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);
1503 snd_checknum(PCM, "Cannot write Channel Map ctl");
1507 static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
1509 snd_pcm_hw_t *hw = pcm->private_data;
1511 int err = snd_card_get_name(hw->card, &name);
1513 snd_error(PCM, "cannot get card name");
1516 snd_output_printf(out, "Hardware PCM card %d '%s' device %d subdevice %d\n",
1517 hw->card, name, hw->device, hw->subdevice);
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);
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,
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,
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,
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.
1618 int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd,
1622 snd_pcm_tstamp_type_t tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
1624 snd_pcm_t *pcm = NULL;
1625 snd_pcm_hw_t *hw = NULL;
1626 snd_pcm_info_t info;
1631 memset(&info, 0, sizeof(info));
1632 if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
1634 snd_checknum(PCM, "SNDRV_PCM_IOCTL_INFO failed (%i)", ret);
1640 if ((fmode = fcntl(fd, F_GETFL)) < 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;
1653 if (ioctl(fd, SNDRV_PCM_IOCTL_PVERSION, &ver) < 0) {
1655 snd_checknum(PCM, "SNDRV_PCM_IOCTL_PVERSION failed (%i)", ret);
1659 if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_PCM_VERSION_MAX))
1660 return -SND_ERROR_INCOMPATIBLE_VERSION;
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) {
1667 snd_check(PCM, "USER_PVERSION failed");
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, ×pec) == 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) {
1680 snd_check(PCM, "TTSTAMP failed");
1684 tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC;
1688 if (SNDRV_PROTOCOL_VERSION(2, 0, 5) <= ver && !(mode & SND_PCM_APPEND)) {
1690 if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) {
1692 snd_check(PCM, "TSTAMP failed");
1697 hw = calloc(1, sizeof(snd_pcm_hw_t));
1704 hw->card = info.card;
1705 hw->device = info.device;
1706 hw->subdevice = info.subdevice;
1708 /* no restriction */
1709 hw->format = SND_PCM_FORMAT_UNKNOWN;
1710 hw->rates.min = hw->rates.max = 0;
1713 ret = snd_pcm_new(&pcm, SND_PCM_TYPE_HW, name, info.stream, mode);
1720 pcm->ops = &snd_pcm_hw_ops;
1721 pcm->fast_ops = &snd_pcm_hw_fast_ops;
1722 pcm->private_data = hw;
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 */
1729 pcm->own_state_check = 1; /* skip the common state check */
1731 ret = map_status_and_control_data(pcm, !!sync_ptr_ioctl);
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.
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,
1763 char filename[sizeof(SNDRV_FILE_PCM_STREAM_PLAYBACK) + 20];
1764 const char *filefmt;
1765 int ret = 0, fd = -1;
1767 snd_pcm_info_t info;
1773 if ((ret = snd_ctl_hw_open(&ctl, NULL, card, 0)) < 0)
1777 case SND_PCM_STREAM_PLAYBACK:
1778 filefmt = SNDRV_FILE_PCM_STREAM_PLAYBACK;
1780 case SND_PCM_STREAM_CAPTURE:
1781 filefmt = SNDRV_FILE_PCM_STREAM_CAPTURE;
1784 snd_error(PCM, "invalid stream %d", stream);
1787 sprintf(filename, filefmt, card, device);
1790 if (attempt++ > 3) {
1794 ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice);
1798 if (mode & SND_PCM_NONBLOCK)
1799 fmode |= O_NONBLOCK;
1800 if (mode & SND_PCM_ASYNC)
1802 if (mode & SND_PCM_APPEND)
1804 fd = snd_open_device(filename, fmode);
1807 snd_checknum(PCM, "open '%s' failed (%i)", filename, ret);
1810 if (subdevice >= 0) {
1811 memset(&info, 0, sizeof(info));
1812 if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
1814 snd_checknum(PCM, "SNDRV_PCM_IOCTL_INFO failed (%i)", ret);
1817 if (info.subdevice != (unsigned int) subdevice) {
1824 return snd_pcm_hw_open_fd(pcmp, name, fd, sync_ptr_ioctl);
1832 /*! \page pcm_plugins
1834 \section pcm_plugins_hw Plugin: hw
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.
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.
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)
1863 \subsection pcm_plugins_hw_funcref Function reference
1866 <LI>snd_pcm_hw_open()
1867 <LI>_snd_pcm_hw_open()
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.
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)
1888 snd_config_iterator_t i, next;
1889 long card = -1, device = 0, subdevice = -1;
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;
1895 int nonblock = 1; /* non-block per default */
1896 snd_pcm_chmap_query_t **chmap = NULL;
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);
1905 snd_config_for_each(i, next, conf) {
1907 n = snd_config_iterator_entry(i);
1908 if (snd_config_get_id(n, &id) < 0)
1910 if (snd_pcm_conf_generic_id(id))
1912 if (strcmp(id, "card") == 0) {
1913 err = snd_config_get_card(n);
1919 if (strcmp(id, "device") == 0) {
1920 err = snd_config_get_integer(n, &device);
1922 snd_error(PCM, "Invalid type for %s", id);
1927 if (strcmp(id, "subdevice") == 0) {
1928 err = snd_config_get_integer(n, &subdevice);
1930 snd_error(PCM, "Invalid type for %s", id);
1935 if (strcmp(id, "sync_ptr_ioctl") == 0) {
1936 err = snd_config_get_bool(n);
1939 sync_ptr_ioctl = err;
1942 if (strcmp(id, "nonblock") == 0) {
1943 err = snd_config_get_bool(n);
1949 if (strcmp(id, "rate") == 0) {
1951 if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND &&
1952 snd_config_is_array(n)) {
1954 err = snd_config_search(n, "0", &m);
1956 snd_error(PCM, "array expected for rate compound");
1959 err = snd_config_get_integer(m, &val);
1961 snd_error(PCM, "Invalid type for rate.0");
1964 min_rate = max_rate = val;
1965 err = snd_config_search(n, "1", &m);
1967 err = snd_config_get_integer(m, &val);
1969 snd_error(PCM, "Invalid type for rate.0");
1975 err = snd_config_get_integer(n, &val);
1977 snd_error(PCM, "Invalid type for %s", id);
1980 min_rate = max_rate = val;
1984 if (strcmp(id, "min_rate") == 0) {
1986 err = snd_config_get_integer(n, &val);
1988 snd_error(PCM, "Invalid type for %s", id);
1994 if (strcmp(id, "max_rate") == 0) {
1996 err = snd_config_get_integer(n, &val);
1998 snd_error(PCM, "Invalid type for %s", id);
2004 if (strcmp(id, "format") == 0) {
2005 err = snd_config_get_string(n, &str);
2007 snd_error(PCM, "invalid type for %s", id);
2010 format = snd_pcm_format_value(str);
2013 if (strcmp(id, "channels") == 0) {
2015 err = snd_config_get_integer(n, &val);
2017 snd_error(PCM, "Invalid type for %s", id);
2023 if (strcmp(id, "chmap") == 0) {
2024 snd_pcm_free_chmaps(chmap);
2025 chmap = _snd_pcm_parse_config_chmaps(n);
2027 snd_error(PCM, "Invalid channel map for %s", id);
2033 if (strcmp(id, "drain_silence") == 0) {
2035 err = snd_config_get_integer(n, &val);
2037 snd_error(PCM, "Invalid type for %s", id);
2040 drain_silence = val;
2043 snd_error(PCM, "Unknown field %s", id);
2048 snd_error(PCM, "card is not defined");
2052 if ((min_rate < 0) || (max_rate < min_rate)) {
2053 snd_error(PCM, "min_rate - max_rate configuration invalid");
2057 err = snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,
2058 mode | (nonblock ? SND_PCM_NONBLOCK : 0),
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;
2067 /* make sure the SND_PCM_NO_xxx flags don't get lost on the
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);
2074 hw = (*pcmp)->private_data;
2075 if (format != SND_PCM_FORMAT_UNKNOWN)
2076 hw->format = format;
2078 hw->channels = channels;
2080 hw->rates.min = min_rate;
2081 hw->rates.max = max_rate;
2084 hw->chmap_override = chmap;
2085 hw->drain_silence = drain_silence;
2090 snd_pcm_free_chmaps(chmap);
2095 SND_DLSYM_BUILD_VERSION(_snd_pcm_hw_open, SND_PCM_DLSYM_VERSION);
2099 * To be removed helpers, but keep binary compatibility at the time
2103 #define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
2104 #define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
2107 static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params,
2108 struct sndrv_pcm_hw_params_old *oparams)
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;
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)
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]) {
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;
2152 static int use_old_hw_params_ioctl(int fd, unsigned int cmd, snd_pcm_hw_params_t *params)
2154 struct sndrv_pcm_hw_params_old oparams;
2155 unsigned int cmask = 0;
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;