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 SYSMSG("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 SYSMSG("F_GETFL failed (%i)", err);
277 flags &= ~O_NONBLOCK;
278 if (fcntl(fd, F_SETFL, flags) < 0) {
280 SYSMSG("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 SYSMSG("F_GETFL failed (%i)", err);
301 if (fcntl(fd, F_SETFL, flags) < 0) {
303 SYSMSG("F_SETFL for O_ASYNC failed (%i)", err);
308 if (fcntl(fd, F_SETSIG, (long)sig) < 0) {
310 SYSMSG("F_SETSIG failed (%i)", err);
313 if (fcntl(fd, F_SETOWN, (long)pid) < 0) {
315 SYSMSG("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 SYSMSG("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;
382 #define hw_param_mask(params,var) \
383 &((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
385 static int hw_params_call(snd_pcm_hw_t *pcm_hw, snd_pcm_hw_params_t *params)
389 /* check for new hw_params structure; it's available from 2.0.2 version of PCM API */
390 if (SNDRV_PROTOCOL_VERSION(2, 0, 2) <= pcm_hw->version)
391 err = ioctl(pcm_hw->fd, SNDRV_PCM_IOCTL_HW_PARAMS, params);
393 err = use_old_hw_params_ioctl(pcm_hw->fd, SND_PCM_IOCTL_HW_PARAMS_OLD, params);
394 if (err >= 0 && pcm_hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 17) && params->msbits > 0) {
395 snd_mask_t *m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
396 if (snd_mask_single(m)) {
397 snd_pcm_format_t format = snd_mask_min(m);
398 int width = snd_pcm_format_width(format);
399 if (width > 0 && params->msbits > (unsigned int)width)
400 params->msbits = width;
406 static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
408 snd_pcm_hw_t *hw = pcm->private_data;
410 if (hw_params_call(hw, params) < 0) {
412 SYSMSG("SNDRV_PCM_IOCTL_HW_PARAMS failed (%i)", err);
415 params->info &= ~0xf0000000;
416 if (pcm->tstamp_type != SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY)
417 params->info |= SND_PCM_INFO_MONOTONIC;
418 hw->perfect_drain = !!(params->info & SND_PCM_INFO_PERFECT_DRAIN) ||
419 !!(params->flags & SND_PCM_HW_PARAMS_NO_DRAIN_SILENCE);
420 return query_status_data(hw);
423 static void snd_pcm_hw_close_timer(snd_pcm_hw_t *hw)
425 if (hw->period_timer) {
426 snd_timer_close(hw->period_timer);
427 hw->period_timer = NULL;
431 static int snd_pcm_hw_change_timer(snd_pcm_t *pcm, int enable)
433 snd_pcm_hw_t *hw = pcm->private_data;
434 snd_timer_params_t params = {0};
435 unsigned int suspend, resume;
439 err = snd_timer_hw_open(&hw->period_timer,
440 "hw-pcm-period-event",
441 SND_TIMER_CLASS_PCM, SND_TIMER_SCLASS_NONE,
442 hw->card, hw->device,
443 (hw->subdevice << 1) | (pcm->stream & 1),
444 SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD);
446 err = snd_timer_hw_open(&hw->period_timer,
447 "hw-pcm-period-event",
448 SND_TIMER_CLASS_PCM, SND_TIMER_SCLASS_NONE,
449 hw->card, hw->device,
450 (hw->subdevice << 1) | (pcm->stream & 1),
451 SND_TIMER_OPEN_NONBLOCK);
454 if (snd_timer_poll_descriptors_count(hw->period_timer) != 1) {
455 snd_pcm_hw_close_timer(hw);
458 hw->period_timer_pfd.events = POLLIN;
459 hw->period_timer_pfd.revents = 0;
460 snd_timer_poll_descriptors(hw->period_timer,
461 &hw->period_timer_pfd, 1);
462 hw->period_timer_need_poll = 0;
463 suspend = 1<<SND_TIMER_EVENT_MSUSPEND;
464 resume = 1<<SND_TIMER_EVENT_MRESUME;
466 * hacks for older kernel drivers
470 ioctl(hw->period_timer_pfd.fd,
471 SNDRV_TIMER_IOCTL_PVERSION, &ver);
473 * In older versions, check via poll before read() is
474 * needed because of the confliction between
475 * TIMER_START and FIONBIO ioctls.
477 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 4))
478 hw->period_timer_need_poll = 1;
480 * In older versions, timer uses pause events instead
481 * suspend/resume events.
483 if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 5)) {
484 suspend = 1<<SND_TIMER_EVENT_MPAUSE;
485 resume = 1<<SND_TIMER_EVENT_MCONTINUE;
488 snd_timer_params_set_auto_start(¶ms, 1);
489 snd_timer_params_set_ticks(¶ms, 1);
490 INTERNAL(snd_timer_params_set_filter)(¶ms, (1<<SND_TIMER_EVENT_TICK) |
492 err = snd_timer_params(hw->period_timer, ¶ms);
494 snd_pcm_hw_close_timer(hw);
497 err = snd_timer_start(hw->period_timer);
499 snd_pcm_hw_close_timer(hw);
502 pcm->fast_ops = &snd_pcm_hw_fast_ops_timer;
504 snd_pcm_hw_close_timer(hw);
505 pcm->fast_ops = &snd_pcm_hw_fast_ops;
506 hw->period_event = 0;
511 static int snd_pcm_hw_hw_free(snd_pcm_t *pcm)
513 snd_pcm_hw_t *hw = pcm->private_data;
514 int fd = hw->fd, err;
515 snd_pcm_hw_change_timer(pcm, 0);
516 if (ioctl(fd, SNDRV_PCM_IOCTL_HW_FREE) < 0) {
518 SYSMSG("SNDRV_PCM_IOCTL_HW_FREE failed (%i)", err);
524 static int snd_pcm_hw_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
526 snd_pcm_hw_t *hw = pcm->private_data;
527 int fd = hw->fd, err = 0;
528 int old_period_event = sw_get_period_event(params);
529 sw_set_period_event(params, 0);
530 if ((snd_pcm_tstamp_t) params->tstamp_mode == pcm->tstamp_mode &&
531 (snd_pcm_tstamp_type_t) params->tstamp_type == pcm->tstamp_type &&
532 params->period_step == pcm->period_step &&
533 params->start_threshold == pcm->start_threshold &&
534 params->stop_threshold == pcm->stop_threshold &&
535 params->silence_threshold == pcm->silence_threshold &&
536 params->silence_size == pcm->silence_size &&
537 old_period_event == hw->period_event) {
538 hw->mmap_control->avail_min = params->avail_min;
539 err = issue_avail_min(hw);
542 if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW &&
543 hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) {
544 SYSMSG("Kernel doesn't support SND_PCM_TSTAMP_TYPE_MONOTONIC_RAW");
548 if (params->tstamp_type == SND_PCM_TSTAMP_TYPE_MONOTONIC &&
549 hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 5)) {
550 SYSMSG("Kernel doesn't support SND_PCM_TSTAMP_TYPE_MONOTONIC");
554 if (ioctl(fd, SNDRV_PCM_IOCTL_SW_PARAMS, params) < 0) {
556 SYSMSG("SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
559 hw->prepare_reset_sw_params = false;
560 if ((snd_pcm_tstamp_type_t) params->tstamp_type != pcm->tstamp_type) {
561 if (hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 12)) {
562 int on = (snd_pcm_tstamp_type_t) params->tstamp_type ==
563 SND_PCM_TSTAMP_TYPE_MONOTONIC;
564 if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) {
566 SNDMSG("TSTAMP failed");
570 pcm->tstamp_type = params->tstamp_type;
572 hw->mmap_control->avail_min = params->avail_min;
573 if (hw->period_event != old_period_event) {
574 err = snd_pcm_hw_change_timer(pcm, old_period_event);
577 hw->period_event = old_period_event;
580 sw_set_period_event(params, old_period_event);
584 static int snd_pcm_hw_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
586 snd_pcm_hw_t *hw = pcm->private_data;
587 struct snd_pcm_channel_info i;
588 int fd = hw->fd, err;
589 i.channel = info->channel;
590 if (ioctl(fd, SNDRV_PCM_IOCTL_CHANNEL_INFO, &i) < 0) {
592 SYSMSG("SNDRV_PCM_IOCTL_CHANNEL_INFO failed (%i)", err);
595 info->channel = i.channel;
597 info->first = i.first;
599 info->type = SND_PCM_AREA_MMAP;
600 info->u.mmap.fd = fd;
601 info->u.mmap.offset = i.offset;
605 static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
607 snd_pcm_hw_t *hw = pcm->private_data;
608 int fd = hw->fd, err;
609 if (SNDRV_PROTOCOL_VERSION(2, 0, 13) > hw->version) {
610 if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS, status) < 0) {
612 SYSMSG("SNDRV_PCM_IOCTL_STATUS failed (%i)", err);
616 if (ioctl(fd, SNDRV_PCM_IOCTL_STATUS_EXT, status) < 0) {
618 SYSMSG("SNDRV_PCM_IOCTL_STATUS_EXT failed (%i)", err);
622 if (SNDRV_PROTOCOL_VERSION(2, 0, 5) > hw->version) {
623 status->tstamp.tv_nsec *= 1000L;
624 status->trigger_tstamp.tv_nsec *= 1000L;
629 static snd_pcm_state_t snd_pcm_hw_state(snd_pcm_t *pcm)
631 snd_pcm_hw_t *hw = pcm->private_data;
632 /* the -ENODEV may come from the snd_disconnect_ioctl() or
633 snd_power_wait() in kernel */
634 if (query_status_data(hw) == -ENODEV)
635 return SND_PCM_STATE_DISCONNECTED;
636 return (snd_pcm_state_t) hw->mmap_status->state;
639 static int snd_pcm_hw_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
641 snd_pcm_hw_t *hw = pcm->private_data;
642 int fd = hw->fd, err;
643 if (ioctl(fd, SNDRV_PCM_IOCTL_DELAY, delayp) < 0) {
645 SYSMSG("SNDRV_PCM_IOCTL_DELAY failed (%i)", err);
651 static int snd_pcm_hw_hwsync(snd_pcm_t *pcm)
653 snd_pcm_hw_t *hw = pcm->private_data;
654 int fd = hw->fd, err;
655 if (SNDRV_PROTOCOL_VERSION(2, 0, 3) <= hw->version) {
656 if (hw->mmap_status_fallbacked) {
657 err = request_hwsync(hw);
661 if (ioctl(fd, SNDRV_PCM_IOCTL_HWSYNC) < 0) {
663 SYSMSG("SNDRV_PCM_IOCTL_HWSYNC failed (%i)", err);
668 snd_pcm_sframes_t delay;
669 int err = snd_pcm_hw_delay(pcm, &delay);
671 switch (FAST_PCM_STATE(hw)) {
672 case SND_PCM_STATE_PREPARED:
673 case SND_PCM_STATE_SUSPENDED:
683 static int snd_pcm_hw_prepare(snd_pcm_t *pcm)
685 snd_pcm_hw_t *hw = pcm->private_data;
686 snd_pcm_sw_params_t sw_params;
687 int fd = hw->fd, err;
689 if (hw->prepare_reset_sw_params) {
690 snd_pcm_sw_params_current_no_lock(pcm, &sw_params);
691 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sw_params) < 0) {
693 SYSMSG("SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
696 hw->prepare_reset_sw_params = false;
698 if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE) < 0) {
700 SYSMSG("SNDRV_PCM_IOCTL_PREPARE failed (%i)", err);
703 return query_status_and_control_data(hw);
706 static int snd_pcm_hw_reset(snd_pcm_t *pcm)
708 snd_pcm_hw_t *hw = pcm->private_data;
709 int fd = hw->fd, err;
710 if (ioctl(fd, SNDRV_PCM_IOCTL_RESET) < 0) {
712 SYSMSG("SNDRV_PCM_IOCTL_RESET failed (%i)", err);
715 return query_status_and_control_data(hw);
718 static int snd_pcm_hw_start(snd_pcm_t *pcm)
720 snd_pcm_hw_t *hw = pcm->private_data;
723 assert(pcm->stream != SND_PCM_STREAM_PLAYBACK ||
724 snd_pcm_mmap_playback_hw_avail(pcm) > 0);
727 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_START) < 0) {
729 SYSMSG("SNDRV_PCM_IOCTL_START failed (%i)", err);
732 SNDERR("PCM state = %s", snd_pcm_state_name(snd_pcm_hw_state(pcm)));
739 static int snd_pcm_hw_drop(snd_pcm_t *pcm)
741 snd_pcm_hw_t *hw = pcm->private_data;
743 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DROP) < 0) {
745 SYSMSG("SNDRV_PCM_IOCTL_DROP failed (%i)", err);
752 static int snd_pcm_hw_drain(snd_pcm_t *pcm)
754 snd_pcm_hw_t *hw = pcm->private_data;
755 snd_pcm_sw_params_t sw_params;
756 snd_pcm_uframes_t silence_size;
759 if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
761 /* stream probably in SETUP, prevent divide by zero */
762 if (pcm->period_size == 0)
764 if (hw->drain_silence == 0 || hw->perfect_drain)
766 snd_pcm_sw_params_current_no_lock(pcm, &sw_params);
767 if (hw->drain_silence > 0) {
768 silence_size = (pcm->rate * hw->drain_silence) / 1000;
769 goto __manual_silence;
771 /* compute end silence size, align to period size + extra time */
772 if ((pcm->boundary % pcm->period_size) == 0) {
773 silence_size = pcm->period_size - (*pcm->appl.ptr % pcm->period_size);
774 if (silence_size == pcm->period_size)
777 /* it not not easy to compute the period crossing point
778 * in this case because the period is not aligned to the boundary
779 * - use the full range (one period) in this case
781 silence_size = pcm->period_size;
783 silence_size += pcm->rate / 10; /* 1/10th of second */
785 if (sw_params.silence_size < silence_size) {
786 /* fill the silence soon as possible (in the bellow ioctl
787 * or the next period wake up)
789 sw_params.silence_threshold = pcm->buffer_size;
790 if (silence_size > pcm->buffer_size)
791 silence_size = pcm->buffer_size;
792 sw_params.silence_size = silence_size;
793 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sw_params) < 0) {
795 SYSMSG("SNDRV_PCM_IOCTL_SW_PARAMS failed (%i)", err);
798 hw->prepare_reset_sw_params = true;
801 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_DRAIN) < 0) {
803 SYSMSG("SNDRV_PCM_IOCTL_DRAIN failed (%i)", err);
809 static int snd_pcm_hw_pause(snd_pcm_t *pcm, int enable)
811 snd_pcm_hw_t *hw = pcm->private_data;
813 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_PAUSE, enable) < 0) {
815 SYSMSG("SNDRV_PCM_IOCTL_PAUSE failed (%i)", err);
821 static snd_pcm_sframes_t snd_pcm_hw_rewindable(snd_pcm_t *pcm)
823 return snd_pcm_mmap_hw_rewindable(pcm);
826 static snd_pcm_sframes_t snd_pcm_hw_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
828 snd_pcm_hw_t *hw = pcm->private_data;
830 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_REWIND, &frames) < 0) {
832 SYSMSG("SNDRV_PCM_IOCTL_REWIND failed (%i)", err);
835 err = query_status_and_control_data(hw);
841 static snd_pcm_sframes_t snd_pcm_hw_forwardable(snd_pcm_t *pcm)
843 return snd_pcm_mmap_avail(pcm);
846 static snd_pcm_sframes_t snd_pcm_hw_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
848 snd_pcm_hw_t *hw = pcm->private_data;
850 if (SNDRV_PROTOCOL_VERSION(2, 0, 4) <= hw->version) {
851 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_FORWARD, &frames) < 0) {
853 SYSMSG("SNDRV_PCM_IOCTL_FORWARD failed (%i)", err);
856 err = query_status_and_control_data(hw);
861 snd_pcm_sframes_t avail;
863 switch (FAST_PCM_STATE(hw)) {
864 case SNDRV_PCM_STATE_RUNNING:
865 case SNDRV_PCM_STATE_DRAINING:
866 case SNDRV_PCM_STATE_PAUSED:
867 case SNDRV_PCM_STATE_PREPARED:
869 case SNDRV_PCM_STATE_XRUN:
874 avail = snd_pcm_mmap_avail(pcm);
877 if (frames > (snd_pcm_uframes_t)avail)
879 snd_pcm_mmap_appl_forward(pcm, frames);
884 static int snd_pcm_hw_resume(snd_pcm_t *pcm)
886 snd_pcm_hw_t *hw = pcm->private_data;
887 int fd = hw->fd, err;
888 if (ioctl(fd, SNDRV_PCM_IOCTL_RESUME) < 0) {
890 SYSMSG("SNDRV_PCM_IOCTL_RESUME failed (%i)", err);
896 static int hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
898 snd_pcm_hw_t *hw1 = pcm1->private_data;
899 snd_pcm_hw_t *hw2 = pcm2->private_data;
900 if (ioctl(hw1->fd, SNDRV_PCM_IOCTL_LINK, hw2->fd) < 0) {
901 SYSMSG("SNDRV_PCM_IOCTL_LINK failed (%i)", -errno);
907 static int snd_pcm_hw_link_slaves(snd_pcm_t *pcm, snd_pcm_t *master)
909 if (master->type != SND_PCM_TYPE_HW) {
910 SYSMSG("Invalid type for SNDRV_PCM_IOCTL_LINK (%i)", master->type);
913 return hw_link(master, pcm);
916 static int snd_pcm_hw_link(snd_pcm_t *pcm1, snd_pcm_t *pcm2)
918 if (pcm2->type != SND_PCM_TYPE_HW) {
919 if (pcm2->fast_ops->link_slaves)
920 return pcm2->fast_ops->link_slaves(pcm2->fast_op_arg, pcm1);
923 return hw_link(pcm1, pcm2);
926 static int snd_pcm_hw_unlink(snd_pcm_t *pcm)
928 snd_pcm_hw_t *hw = pcm->private_data;
930 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_UNLINK) < 0) {
931 SYSMSG("SNDRV_PCM_IOCTL_UNLINK failed (%i)", -errno);
937 static snd_pcm_sframes_t snd_pcm_hw_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
940 snd_pcm_hw_t *hw = pcm->private_data;
942 struct snd_xferi xferi;
943 xferi.buf = (char*) buffer;
945 xferi.result = 0; /* make valgrind happy */
946 if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi) < 0)
949 err = query_status_and_control_data(hw);
951 fprintf(stderr, "hw_writei: frames = %li, xferi.result = %li, err = %i\n", size, xferi.result, err);
954 return snd_pcm_check_error(pcm, err);
958 static snd_pcm_sframes_t snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
961 snd_pcm_hw_t *hw = pcm->private_data;
963 struct snd_xfern xfern;
964 memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
967 if (ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, &xfern) < 0)
970 err = query_status_and_control_data(hw);
972 fprintf(stderr, "hw_writen: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
975 return snd_pcm_check_error(pcm, err);
979 static snd_pcm_sframes_t snd_pcm_hw_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)
982 snd_pcm_hw_t *hw = pcm->private_data;
984 struct snd_xferi xferi;
987 xferi.result = 0; /* make valgrind happy */
988 if (ioctl(fd, SNDRV_PCM_IOCTL_READI_FRAMES, &xferi) < 0)
991 err = query_status_and_control_data(hw);
993 fprintf(stderr, "hw_readi: frames = %li, result = %li, err = %i\n", size, xferi.result, err);
996 return snd_pcm_check_error(pcm, err);
1000 static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
1003 snd_pcm_hw_t *hw = pcm->private_data;
1005 struct snd_xfern xfern;
1006 memset(&xfern, 0, sizeof(xfern)); /* make valgrind happy */
1008 xfern.frames = size;
1009 if (ioctl(fd, SNDRV_PCM_IOCTL_READN_FRAMES, &xfern) < 0)
1012 err = query_status_and_control_data(hw);
1014 fprintf(stderr, "hw_readn: frames = %li, result = %li, err = %i\n", size, xfern.result, err);
1017 return snd_pcm_check_error(pcm, err);
1018 return xfern.result;
1021 static bool map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr,
1022 bool force_fallback)
1024 struct snd_pcm_mmap_status *mmap_status;
1027 mmap_status = MAP_FAILED;
1028 if (!force_fallback) {
1029 mmap_status = mmap(NULL, page_align(sizeof(*mmap_status)),
1030 PROT_READ, MAP_FILE|MAP_SHARED,
1031 hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
1034 if (mmap_status == MAP_FAILED || mmap_status == NULL) {
1035 mmap_status = &sync_ptr->s.status;
1041 hw->mmap_status = mmap_status;
1046 static bool map_control_data(snd_pcm_hw_t *hw,
1047 struct snd_pcm_sync_ptr *sync_ptr,
1048 bool force_fallback)
1050 struct snd_pcm_mmap_control *mmap_control;
1053 mmap_control = MAP_FAILED;
1054 if (!force_fallback) {
1055 mmap_control = mmap(NULL, page_align(sizeof(*mmap_control)),
1056 PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
1057 hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
1060 if (mmap_control == MAP_FAILED || mmap_control == NULL) {
1061 mmap_control = &sync_ptr->c.control;
1067 hw->mmap_control = mmap_control;
1072 static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback)
1074 snd_pcm_hw_t *hw = pcm->private_data;
1075 struct snd_pcm_sync_ptr *sync_ptr;
1078 /* Preparation for fallback to failure of mmap(2). */
1079 sync_ptr = malloc(sizeof(*sync_ptr));
1080 if (sync_ptr == NULL)
1082 memset(sync_ptr, 0, sizeof(*sync_ptr));
1084 hw->mmap_status_fallbacked =
1085 map_status_data(hw, sync_ptr, force_fallback);
1086 hw->mmap_control_fallbacked =
1087 map_control_data(hw, sync_ptr, force_fallback);
1089 /* Any fallback mode needs to keep the buffer. */
1090 if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked) {
1091 hw->sync_ptr = sync_ptr;
1094 hw->sync_ptr = NULL;
1097 /* do not initialize in case of append and keep the values from the
1100 if (!(pcm->mode & SND_PCM_APPEND)) {
1101 /* Initialize the data. */
1102 hw->mmap_control->appl_ptr = 0;
1103 hw->mmap_control->avail_min = 1;
1105 snd_pcm_set_hw_ptr(pcm, &hw->mmap_status->hw_ptr, hw->fd,
1106 SNDRV_PCM_MMAP_OFFSET_STATUS +
1107 offsetof(struct snd_pcm_mmap_status, hw_ptr));
1108 snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd,
1109 SNDRV_PCM_MMAP_OFFSET_CONTROL);
1110 if (hw->mmap_control_fallbacked) {
1111 unsigned int flags = 0;
1112 /* read appl_ptr and avail_min from kernel when device opened
1113 * with SND_PCM_APPEND flag
1115 if (pcm->mode & SND_PCM_APPEND)
1116 flags = SNDRV_PCM_SYNC_PTR_APPL |
1117 SNDRV_PCM_SYNC_PTR_AVAIL_MIN;
1118 err = sync_ptr1(hw, flags);
1126 static void unmap_status_data(snd_pcm_hw_t *hw)
1128 if (!hw->mmap_status_fallbacked) {
1129 if (munmap((void *)hw->mmap_status,
1130 page_align(sizeof(*hw->mmap_status))) < 0)
1131 SYSMSG("status munmap failed (%u)", errno);
1135 static void unmap_control_data(snd_pcm_hw_t *hw)
1137 if (!hw->mmap_control_fallbacked) {
1138 if (munmap((void *)hw->mmap_control,
1139 page_align(sizeof(*hw->mmap_control))) < 0)
1140 SYSMSG("control munmap failed (%u)", errno);
1144 static void unmap_status_and_control_data(snd_pcm_hw_t *hw)
1146 unmap_status_data(hw);
1147 unmap_control_data(hw);
1149 if (hw->mmap_status_fallbacked || hw->mmap_control_fallbacked)
1152 hw->mmap_status = NULL;
1153 hw->mmap_control = NULL;
1154 hw->mmap_status_fallbacked = false;
1155 hw->mmap_control_fallbacked = false;
1156 hw->sync_ptr = NULL;
1159 static int snd_pcm_hw_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1164 static int snd_pcm_hw_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1169 static int snd_pcm_hw_close(snd_pcm_t *pcm)
1171 snd_pcm_hw_t *hw = pcm->private_data;
1173 if (close(hw->fd)) {
1175 SYSMSG("close failed (%i)", err);
1178 unmap_status_and_control_data(hw);
1184 static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm,
1185 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
1186 snd_pcm_uframes_t size)
1188 snd_pcm_hw_t *hw = pcm->private_data;
1190 snd_pcm_mmap_appl_forward(pcm, size);
1193 fprintf(stderr, "appl_forward: hw_ptr = %li, appl_ptr = %li, size = %li\n", *pcm->hw.ptr, *pcm->appl.ptr, size);
1198 static snd_pcm_sframes_t snd_pcm_hw_avail_update(snd_pcm_t *pcm)
1200 snd_pcm_hw_t *hw = pcm->private_data;
1201 snd_pcm_uframes_t avail;
1203 query_status_data(hw);
1204 avail = snd_pcm_mmap_avail(pcm);
1205 switch (FAST_PCM_STATE(hw)) {
1206 case SNDRV_PCM_STATE_RUNNING:
1207 if (avail >= pcm->stop_threshold) {
1208 /* SNDRV_PCM_IOCTL_XRUN ioctl has been implemented since PCM kernel API 2.0.1 */
1209 if (SNDRV_PROTOCOL_VERSION(2, 0, 1) <= hw->version) {
1210 if (ioctl(hw->fd, SNDRV_PCM_IOCTL_XRUN) < 0)
1213 /* everything is ok, state == SND_PCM_STATE_XRUN at the moment */
1217 case SNDRV_PCM_STATE_XRUN:
1225 static int snd_pcm_hw_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
1226 snd_htimestamp_t *tstamp)
1228 snd_pcm_sframes_t avail1;
1231 /* unfortunately, loop is necessary to ensure valid timestamp */
1233 avail1 = snd_pcm_hw_avail_update(pcm);
1236 if (ok && (snd_pcm_uframes_t)avail1 == *avail)
1239 *tstamp = snd_pcm_hw_fast_tstamp(pcm);
1245 static void __fill_chmap_ctl_id(snd_ctl_elem_id_t *id, int dev, int subdev,
1248 snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_PCM);
1249 if (stream == SND_PCM_STREAM_PLAYBACK)
1250 snd_ctl_elem_id_set_name(id, "Playback Channel Map");
1252 snd_ctl_elem_id_set_name(id, "Capture Channel Map");
1253 snd_ctl_elem_id_set_device(id, dev);
1254 snd_ctl_elem_id_set_index(id, subdev);
1257 static void fill_chmap_ctl_id(snd_pcm_t *pcm, snd_ctl_elem_id_t *id)
1259 snd_pcm_hw_t *hw = pcm->private_data;
1260 __fill_chmap_ctl_id(id, hw->device, hw->subdevice, pcm->stream);
1263 static int is_chmap_type(int type)
1265 return (type >= SND_CTL_TLVT_CHMAP_FIXED &&
1266 type <= SND_CTL_TLVT_CHMAP_PAIRED);
1270 * \!brief Query the available channel maps
1271 * \param card the card number
1272 * \param dev the PCM device number
1273 * \param subdev the PCM substream index
1274 * \param stream the direction of PCM stream
1275 * \return the NULL-terminated array of integer pointers, or NULL at error.
1277 * This function works like snd_pcm_query_chmaps() but it takes the card,
1278 * device, substream and stream numbers instead of the already opened
1279 * snd_pcm_t instance, so that you can query available channel maps of
1280 * a PCM before actually opening it.
1282 * As the parameters stand, the query is performed only to the hw PCM
1283 * devices, not the abstracted PCM object in alsa-lib.
1285 snd_pcm_chmap_query_t **
1286 snd_pcm_query_chmaps_from_hw(int card, int dev, int subdev,
1287 snd_pcm_stream_t stream)
1290 snd_ctl_elem_id_t id = {0};
1291 unsigned int tlv[2048], *start;
1293 snd_pcm_chmap_query_t **map;
1296 ret = snd_ctl_hw_open(&ctl, NULL, card, 0);
1298 SYSMSG("Cannot open the associated CTL");
1302 __fill_chmap_ctl_id(&id, dev, subdev, stream);
1303 ret = snd_ctl_elem_tlv_read(ctl, &id, tlv, sizeof(tlv));
1306 SYSMSG("Cannot read Channel Map TLV");
1311 for (i = 0; i < 32; i++)
1312 fprintf(stderr, "%02x: %08x\n", i, tlv[i]);
1314 /* FIXME: the parser below assumes that the TLV only contains
1315 * chmap-related blocks
1317 type = tlv[SNDRV_CTL_TLVO_TYPE];
1318 if (type != SND_CTL_TLVT_CONTAINER) {
1319 if (!is_chmap_type(type)) {
1320 SYSMSG("Invalid TLV type %d", type);
1329 size = tlv[SNDRV_CTL_TLVO_LEN];
1331 for (p = start; size > 0; ) {
1332 if (!is_chmap_type(p[0])) {
1333 SYSMSG("Invalid TLV type %d", p[0]);
1341 map = calloc(nums + 1, sizeof(int *));
1344 for (i = 0; i < nums; i++) {
1345 map[i] = malloc(start[1] + 8);
1347 snd_pcm_free_chmaps(map);
1350 map[i]->type = start[0] - 0x100;
1351 map[i]->map.channels = start[1] / 4;
1352 memcpy(map[i]->map.pos, start + 2, start[1]);
1353 start += start[1] / 4 + 2;
1358 enum { CHMAP_CTL_QUERY, CHMAP_CTL_GET, CHMAP_CTL_SET };
1360 static int chmap_caps(snd_pcm_hw_t *hw, int type)
1362 if (hw->chmap_caps & (1 << type))
1364 if (hw->chmap_caps & (1 << (type + 8)))
1369 static void chmap_caps_set_ok(snd_pcm_hw_t *hw, int type)
1371 hw->chmap_caps |= (1 << type);
1374 static void chmap_caps_set_error(snd_pcm_hw_t *hw, int type)
1376 hw->chmap_caps |= (1 << (type + 8));
1379 static snd_pcm_chmap_query_t **snd_pcm_hw_query_chmaps(snd_pcm_t *pcm)
1381 snd_pcm_hw_t *hw = pcm->private_data;
1382 snd_pcm_chmap_query_t **map;
1384 if (hw->chmap_override)
1385 return _snd_pcm_copy_chmap_query(hw->chmap_override);
1387 if (!chmap_caps(hw, CHMAP_CTL_QUERY))
1390 map = snd_pcm_query_chmaps_from_hw(hw->card, hw->device,
1391 hw->subdevice, pcm->stream);
1393 chmap_caps_set_ok(hw, CHMAP_CTL_QUERY);
1395 chmap_caps_set_error(hw, CHMAP_CTL_QUERY);
1399 static snd_pcm_chmap_t *snd_pcm_hw_get_chmap(snd_pcm_t *pcm)
1401 snd_pcm_hw_t *hw = pcm->private_data;
1402 snd_pcm_chmap_t *map;
1404 snd_ctl_elem_id_t id = {0};
1405 snd_ctl_elem_value_t val = {0};
1409 if (hw->chmap_override)
1410 return _snd_pcm_choose_fixed_chmap(pcm, hw->chmap_override);
1412 if (!chmap_caps(hw, CHMAP_CTL_GET))
1415 switch (FAST_PCM_STATE(hw)) {
1416 case SNDRV_PCM_STATE_PREPARED:
1417 case SNDRV_PCM_STATE_RUNNING:
1418 case SNDRV_PCM_STATE_XRUN:
1419 case SNDRV_PCM_STATE_DRAINING:
1420 case SNDRV_PCM_STATE_PAUSED:
1421 case SNDRV_PCM_STATE_SUSPENDED:
1424 SYSMSG("Invalid PCM state for chmap_get: %s",
1425 snd_pcm_state_name(FAST_PCM_STATE(hw)));
1428 map = malloc(pcm->channels * sizeof(map->pos[0]) + sizeof(*map));
1431 map->channels = pcm->channels;
1432 ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
1435 SYSMSG("Cannot open the associated CTL");
1436 chmap_caps_set_error(hw, CHMAP_CTL_GET);
1439 fill_chmap_ctl_id(pcm, &id);
1440 snd_ctl_elem_value_set_id(&val, &id);
1441 ret = snd_ctl_elem_read(ctl, &val);
1445 SYSMSG("Cannot read Channel Map ctl");
1446 chmap_caps_set_error(hw, CHMAP_CTL_GET);
1449 for (i = 0; i < pcm->channels; i++)
1450 map->pos[i] = snd_ctl_elem_value_get_integer(&val, i);
1451 chmap_caps_set_ok(hw, CHMAP_CTL_GET);
1455 static int snd_pcm_hw_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
1457 snd_pcm_hw_t *hw = pcm->private_data;
1459 snd_ctl_elem_id_t id = {0};
1460 snd_ctl_elem_value_t val = {0};
1464 if (hw->chmap_override)
1467 if (!chmap_caps(hw, CHMAP_CTL_SET))
1470 if (map->channels > 128) {
1471 SYSMSG("Invalid number of channels %d", map->channels);
1474 if (FAST_PCM_STATE(hw) != SNDRV_PCM_STATE_PREPARED) {
1475 SYSMSG("Invalid PCM state for chmap_set: %s",
1476 snd_pcm_state_name(FAST_PCM_STATE(hw)));
1479 ret = snd_ctl_hw_open(&ctl, NULL, hw->card, 0);
1481 SYSMSG("Cannot open the associated CTL");
1482 chmap_caps_set_error(hw, CHMAP_CTL_SET);
1486 fill_chmap_ctl_id(pcm, &id);
1487 snd_ctl_elem_value_set_id(&val, &id);
1488 for (i = 0; i < map->channels; i++)
1489 snd_ctl_elem_value_set_integer(&val, i, map->pos[i]);
1490 ret = snd_ctl_elem_write(ctl, &val);
1493 chmap_caps_set_ok(hw, CHMAP_CTL_SET);
1494 else if (ret == -ENOENT || ret == -EPERM || ret == -ENXIO) {
1495 chmap_caps_set_error(hw, CHMAP_CTL_SET);
1499 SYSMSG("Cannot write Channel Map ctl");
1503 static void snd_pcm_hw_dump(snd_pcm_t *pcm, snd_output_t *out)
1505 snd_pcm_hw_t *hw = pcm->private_data;
1507 int err = snd_card_get_name(hw->card, &name);
1509 SNDERR("cannot get card name");
1512 snd_output_printf(out, "Hardware PCM card %d '%s' device %d subdevice %d\n",
1513 hw->card, name, hw->device, hw->subdevice);
1516 snd_output_printf(out, "Its setup is:\n");
1517 snd_pcm_dump_setup(pcm, out);
1518 snd_output_printf(out, " appl_ptr : %li\n", hw->mmap_control->appl_ptr);
1519 snd_output_printf(out, " hw_ptr : %li\n", hw->mmap_status->hw_ptr);
1523 static const snd_pcm_ops_t snd_pcm_hw_ops = {
1524 .close = snd_pcm_hw_close,
1525 .info = snd_pcm_hw_info,
1526 .hw_refine = snd_pcm_hw_hw_refine,
1527 .hw_params = snd_pcm_hw_hw_params,
1528 .hw_free = snd_pcm_hw_hw_free,
1529 .sw_params = snd_pcm_hw_sw_params,
1530 .channel_info = snd_pcm_hw_channel_info,
1531 .dump = snd_pcm_hw_dump,
1532 .nonblock = snd_pcm_hw_nonblock,
1533 .async = snd_pcm_hw_async,
1534 .mmap = snd_pcm_hw_mmap,
1535 .munmap = snd_pcm_hw_munmap,
1536 .query_chmaps = snd_pcm_hw_query_chmaps,
1537 .get_chmap = snd_pcm_hw_get_chmap,
1538 .set_chmap = snd_pcm_hw_set_chmap,
1541 static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops = {
1542 .status = snd_pcm_hw_status,
1543 .state = snd_pcm_hw_state,
1544 .hwsync = snd_pcm_hw_hwsync,
1545 .delay = snd_pcm_hw_delay,
1546 .prepare = snd_pcm_hw_prepare,
1547 .reset = snd_pcm_hw_reset,
1548 .start = snd_pcm_hw_start,
1549 .drop = snd_pcm_hw_drop,
1550 .drain = snd_pcm_hw_drain,
1551 .pause = snd_pcm_hw_pause,
1552 .rewindable = snd_pcm_hw_rewindable,
1553 .rewind = snd_pcm_hw_rewind,
1554 .forwardable = snd_pcm_hw_forwardable,
1555 .forward = snd_pcm_hw_forward,
1556 .resume = snd_pcm_hw_resume,
1557 .link = snd_pcm_hw_link,
1558 .link_slaves = snd_pcm_hw_link_slaves,
1559 .unlink = snd_pcm_hw_unlink,
1560 .writei = snd_pcm_hw_writei,
1561 .writen = snd_pcm_hw_writen,
1562 .readi = snd_pcm_hw_readi,
1563 .readn = snd_pcm_hw_readn,
1564 .avail_update = snd_pcm_hw_avail_update,
1565 .mmap_commit = snd_pcm_hw_mmap_commit,
1566 .htimestamp = snd_pcm_hw_htimestamp,
1567 .poll_descriptors = NULL,
1568 .poll_descriptors_count = NULL,
1569 .poll_revents = NULL,
1572 static const snd_pcm_fast_ops_t snd_pcm_hw_fast_ops_timer = {
1573 .status = snd_pcm_hw_status,
1574 .state = snd_pcm_hw_state,
1575 .hwsync = snd_pcm_hw_hwsync,
1576 .delay = snd_pcm_hw_delay,
1577 .prepare = snd_pcm_hw_prepare,
1578 .reset = snd_pcm_hw_reset,
1579 .start = snd_pcm_hw_start,
1580 .drop = snd_pcm_hw_drop,
1581 .drain = snd_pcm_hw_drain,
1582 .pause = snd_pcm_hw_pause,
1583 .rewindable = snd_pcm_hw_rewindable,
1584 .rewind = snd_pcm_hw_rewind,
1585 .forwardable = snd_pcm_hw_forwardable,
1586 .forward = snd_pcm_hw_forward,
1587 .resume = snd_pcm_hw_resume,
1588 .link = snd_pcm_hw_link,
1589 .link_slaves = snd_pcm_hw_link_slaves,
1590 .unlink = snd_pcm_hw_unlink,
1591 .writei = snd_pcm_hw_writei,
1592 .writen = snd_pcm_hw_writen,
1593 .readi = snd_pcm_hw_readi,
1594 .readn = snd_pcm_hw_readn,
1595 .avail_update = snd_pcm_hw_avail_update,
1596 .mmap_commit = snd_pcm_hw_mmap_commit,
1597 .htimestamp = snd_pcm_hw_htimestamp,
1598 .poll_descriptors = snd_pcm_hw_poll_descriptors,
1599 .poll_descriptors_count = snd_pcm_hw_poll_descriptors_count,
1600 .poll_revents = snd_pcm_hw_poll_revents,
1604 * \brief Creates a new hw PCM
1605 * \param pcmp Returns created PCM handle
1606 * \param name Name of PCM
1607 * \param fd File descriptor
1608 * \param sync_ptr_ioctl Boolean flag for sync_ptr ioctl
1609 * \retval zero on success otherwise a negative error code
1610 * \warning Using of this function might be dangerous in the sense
1611 * of compatibility reasons. The prototype might be freely
1612 * changed in future.
1614 int snd_pcm_hw_open_fd(snd_pcm_t **pcmp, const char *name, int fd,
1618 snd_pcm_tstamp_type_t tstamp_type = SND_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
1620 snd_pcm_t *pcm = NULL;
1621 snd_pcm_hw_t *hw = NULL;
1622 snd_pcm_info_t info;
1627 memset(&info, 0, sizeof(info));
1628 if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
1630 SYSMSG("SNDRV_PCM_IOCTL_INFO failed (%i)", ret);
1636 if ((fmode = fcntl(fd, F_GETFL)) < 0) {
1642 if (fmode & O_NONBLOCK)
1643 mode |= SND_PCM_NONBLOCK;
1644 if (fmode & O_ASYNC)
1645 mode |= SND_PCM_ASYNC;
1646 if (fmode & O_APPEND)
1647 mode |= SND_PCM_APPEND;
1649 if (ioctl(fd, SNDRV_PCM_IOCTL_PVERSION, &ver) < 0) {
1651 SYSMSG("SNDRV_PCM_IOCTL_PVERSION failed (%i)", ret);
1655 if (SNDRV_PROTOCOL_INCOMPATIBLE(ver, SNDRV_PCM_VERSION_MAX))
1656 return -SND_ERROR_INCOMPATIBLE_VERSION;
1658 if (SNDRV_PROTOCOL_VERSION(2, 0, 14) <= ver) {
1659 /* inform the protocol version we're supporting */
1660 unsigned int user_ver = SNDRV_PCM_VERSION;
1661 if (ioctl(fd, SNDRV_PCM_IOCTL_USER_PVERSION, &user_ver) < 0) {
1663 SNDMSG("USER_PVERSION failed");
1668 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1669 if (SNDRV_PROTOCOL_VERSION(2, 0, 9) <= ver) {
1670 struct timespec timespec;
1671 if (clock_gettime(CLOCK_MONOTONIC, ×pec) == 0) {
1672 if (!(mode & SND_PCM_APPEND)) {
1673 int on = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
1674 if (ioctl(fd, SNDRV_PCM_IOCTL_TTSTAMP, &on) < 0) {
1676 SNDMSG("TTSTAMP failed");
1680 tstamp_type = SND_PCM_TSTAMP_TYPE_MONOTONIC;
1684 if (SNDRV_PROTOCOL_VERSION(2, 0, 5) <= ver && !(mode & SND_PCM_APPEND)) {
1686 if (ioctl(fd, SNDRV_PCM_IOCTL_TSTAMP, &on) < 0) {
1688 SNDMSG("TSTAMP failed");
1693 hw = calloc(1, sizeof(snd_pcm_hw_t));
1700 hw->card = info.card;
1701 hw->device = info.device;
1702 hw->subdevice = info.subdevice;
1704 /* no restriction */
1705 hw->format = SND_PCM_FORMAT_UNKNOWN;
1706 hw->rates.min = hw->rates.max = 0;
1709 ret = snd_pcm_new(&pcm, SND_PCM_TYPE_HW, name, info.stream, mode);
1716 pcm->ops = &snd_pcm_hw_ops;
1717 pcm->fast_ops = &snd_pcm_hw_fast_ops;
1718 pcm->private_data = hw;
1720 pcm->poll_events = info.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
1721 pcm->tstamp_type = tstamp_type;
1722 #ifdef THREAD_SAFE_API
1723 pcm->need_lock = 0; /* hw plugin is thread-safe */
1725 pcm->own_state_check = 1; /* skip the common state check */
1727 ret = map_status_and_control_data(pcm, !!sync_ptr_ioctl);
1738 * \brief Creates a new hw PCM
1739 * \param pcmp Returns created PCM handle
1740 * \param name Name of PCM
1741 * \param card Number of card
1742 * \param device Number of device
1743 * \param subdevice Number of subdevice
1744 * \param stream PCM Stream
1745 * \param mode PCM Mode
1746 * \param mmap_emulation Obsoleted parameter
1747 * \param sync_ptr_ioctl Use SYNC_PTR ioctl rather than mmap for control structures
1748 * \retval zero on success otherwise a negative error code
1749 * \warning Using of this function might be dangerous in the sense
1750 * of compatibility reasons. The prototype might be freely
1751 * changed in future.
1753 int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
1754 int card, int device, int subdevice,
1755 snd_pcm_stream_t stream, int mode,
1756 int mmap_emulation ATTRIBUTE_UNUSED,
1759 char filename[sizeof(SNDRV_FILE_PCM_STREAM_PLAYBACK) + 20];
1760 const char *filefmt;
1761 int ret = 0, fd = -1;
1763 snd_pcm_info_t info;
1769 if ((ret = snd_ctl_hw_open(&ctl, NULL, card, 0)) < 0)
1773 case SND_PCM_STREAM_PLAYBACK:
1774 filefmt = SNDRV_FILE_PCM_STREAM_PLAYBACK;
1776 case SND_PCM_STREAM_CAPTURE:
1777 filefmt = SNDRV_FILE_PCM_STREAM_CAPTURE;
1780 SNDERR("invalid stream %d", stream);
1783 sprintf(filename, filefmt, card, device);
1786 if (attempt++ > 3) {
1790 ret = snd_ctl_pcm_prefer_subdevice(ctl, subdevice);
1794 if (mode & SND_PCM_NONBLOCK)
1795 fmode |= O_NONBLOCK;
1796 if (mode & SND_PCM_ASYNC)
1798 if (mode & SND_PCM_APPEND)
1800 fd = snd_open_device(filename, fmode);
1803 SYSMSG("open '%s' failed (%i)", filename, ret);
1806 if (subdevice >= 0) {
1807 memset(&info, 0, sizeof(info));
1808 if (ioctl(fd, SNDRV_PCM_IOCTL_INFO, &info) < 0) {
1810 SYSMSG("SNDRV_PCM_IOCTL_INFO failed (%i)", ret);
1813 if (info.subdevice != (unsigned int) subdevice) {
1820 return snd_pcm_hw_open_fd(pcmp, name, fd, sync_ptr_ioctl);
1828 /*! \page pcm_plugins
1830 \section pcm_plugins_hw Plugin: hw
1832 This plugin communicates directly with the ALSA kernel driver. It is a raw
1833 communication without any conversions. The emulation of mmap access can be
1834 optionally enabled, but expect worse latency in the case.
1836 The nonblock option specifies whether the device is opened in a non-blocking
1837 manner. Note that the blocking behavior for read/write access won't be
1838 changed by this option. This influences only on the blocking behavior at
1839 opening the device. If you would like to keep the compatibility with the
1840 older ALSA stuff, turn this option off.
1844 type hw # Kernel PCM
1845 card INT/STR # Card name (string) or number (integer)
1846 [device INT] # Device number (default 0)
1847 [subdevice INT] # Subdevice number (default -1: first available)
1848 [sync_ptr_ioctl BOOL] # Use SYNC_PTR ioctl rather than the direct mmap access for control structures
1849 [nonblock BOOL] # Force non-blocking open mode
1850 [format STR] # Restrict only to the given format
1851 [channels INT] # Restrict only to the given channels
1852 [rate INT] # Restrict only to the given rate
1853 or [rate [INT INT]] # Restrict only to the given rate range (min max)
1854 [chmap MAP] # Override channel maps; MAP is a string array
1855 [drain_silence INT] # Add silence in drain (-1 = auto /default/, 0 = off, > 0 milliseconds)
1859 \subsection pcm_plugins_hw_funcref Function reference
1862 <LI>snd_pcm_hw_open()
1863 <LI>_snd_pcm_hw_open()
1869 * \brief Creates a new hw PCM
1870 * \param pcmp Returns created PCM handle
1871 * \param name Name of PCM
1872 * \param root Root configuration node
1873 * \param conf Configuration node with hw PCM description
1874 * \param stream PCM Stream
1875 * \param mode PCM Mode
1876 * \warning Using of this function might be dangerous in the sense
1877 * of compatibility reasons. The prototype might be freely
1878 * changed in future.
1880 int _snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
1881 snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf,
1882 snd_pcm_stream_t stream, int mode)
1884 snd_config_iterator_t i, next;
1885 long card = -1, device = 0, subdevice = -1;
1887 int err, sync_ptr_ioctl = 0;
1888 int min_rate = 0, max_rate = 0, channels = 0, drain_silence = -1;
1889 snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
1891 int nonblock = 1; /* non-block per default */
1892 snd_pcm_chmap_query_t **chmap = NULL;
1895 /* look for defaults.pcm.nonblock definition */
1896 if (snd_config_search(root, "defaults.pcm.nonblock", &n) >= 0) {
1897 err = snd_config_get_bool(n);
1901 snd_config_for_each(i, next, conf) {
1903 n = snd_config_iterator_entry(i);
1904 if (snd_config_get_id(n, &id) < 0)
1906 if (snd_pcm_conf_generic_id(id))
1908 if (strcmp(id, "card") == 0) {
1909 err = snd_config_get_card(n);
1915 if (strcmp(id, "device") == 0) {
1916 err = snd_config_get_integer(n, &device);
1918 SNDERR("Invalid type for %s", id);
1923 if (strcmp(id, "subdevice") == 0) {
1924 err = snd_config_get_integer(n, &subdevice);
1926 SNDERR("Invalid type for %s", id);
1931 if (strcmp(id, "sync_ptr_ioctl") == 0) {
1932 err = snd_config_get_bool(n);
1935 sync_ptr_ioctl = err;
1938 if (strcmp(id, "nonblock") == 0) {
1939 err = snd_config_get_bool(n);
1945 if (strcmp(id, "rate") == 0) {
1947 if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND &&
1948 snd_config_is_array(n)) {
1950 err = snd_config_search(n, "0", &m);
1952 SNDERR("array expected for rate compound");
1955 err = snd_config_get_integer(m, &val);
1957 SNDERR("Invalid type for rate.0");
1960 min_rate = max_rate = val;
1961 err = snd_config_search(n, "1", &m);
1963 err = snd_config_get_integer(m, &val);
1965 SNDERR("Invalid type for rate.0");
1971 err = snd_config_get_integer(n, &val);
1973 SNDERR("Invalid type for %s", id);
1976 min_rate = max_rate = val;
1980 if (strcmp(id, "min_rate") == 0) {
1982 err = snd_config_get_integer(n, &val);
1984 SNDERR("Invalid type for %s", id);
1990 if (strcmp(id, "max_rate") == 0) {
1992 err = snd_config_get_integer(n, &val);
1994 SNDERR("Invalid type for %s", id);
2000 if (strcmp(id, "format") == 0) {
2001 err = snd_config_get_string(n, &str);
2003 SNDERR("invalid type for %s", id);
2006 format = snd_pcm_format_value(str);
2009 if (strcmp(id, "channels") == 0) {
2011 err = snd_config_get_integer(n, &val);
2013 SNDERR("Invalid type for %s", id);
2019 if (strcmp(id, "chmap") == 0) {
2020 snd_pcm_free_chmaps(chmap);
2021 chmap = _snd_pcm_parse_config_chmaps(n);
2023 SNDERR("Invalid channel map for %s", id);
2029 if (strcmp(id, "drain_silence") == 0) {
2031 err = snd_config_get_integer(n, &val);
2033 SNDERR("Invalid type for %s", id);
2036 drain_silence = val;
2039 SNDERR("Unknown field %s", id);
2044 SNDERR("card is not defined");
2048 if ((min_rate < 0) || (max_rate < min_rate)) {
2049 SNDERR("min_rate - max_rate configuration invalid");
2053 err = snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,
2054 mode | (nonblock ? SND_PCM_NONBLOCK : 0),
2058 if (nonblock && ! (mode & SND_PCM_NONBLOCK)) {
2059 /* revert to blocking mode for read/write access */
2060 snd_pcm_hw_nonblock(*pcmp, 0);
2061 (*pcmp)->mode = mode;
2063 /* make sure the SND_PCM_NO_xxx flags don't get lost on the
2065 (*pcmp)->mode |= mode & (SND_PCM_NO_AUTO_RESAMPLE|
2066 SND_PCM_NO_AUTO_CHANNELS|
2067 SND_PCM_NO_AUTO_FORMAT|
2068 SND_PCM_NO_SOFTVOL);
2070 hw = (*pcmp)->private_data;
2071 if (format != SND_PCM_FORMAT_UNKNOWN)
2072 hw->format = format;
2074 hw->channels = channels;
2076 hw->rates.min = min_rate;
2077 hw->rates.max = max_rate;
2080 hw->chmap_override = chmap;
2081 hw->drain_silence = drain_silence;
2086 snd_pcm_free_chmaps(chmap);
2091 SND_DLSYM_BUILD_VERSION(_snd_pcm_hw_open, SND_PCM_DLSYM_VERSION);
2095 * To be removed helpers, but keep binary compatibility at the time
2099 #define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
2100 #define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
2103 static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params,
2104 struct sndrv_pcm_hw_params_old *oparams)
2108 memset(params, 0, sizeof(*params));
2109 params->flags = oparams->flags;
2110 for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
2111 params->masks[i].bits[0] = oparams->masks[i];
2112 memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
2113 params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
2114 params->cmask = __OLD_TO_NEW_MASK(oparams->cmask);
2115 params->info = oparams->info;
2116 params->msbits = oparams->msbits;
2117 params->rate_num = oparams->rate_num;
2118 params->rate_den = oparams->rate_den;
2119 params->fifo_size = oparams->fifo_size;
2122 static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old *oparams,
2123 snd_pcm_hw_params_t *params,
2124 unsigned int *cmask)
2128 memset(oparams, 0, sizeof(*oparams));
2129 oparams->flags = params->flags;
2130 for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++) {
2131 oparams->masks[i] = params->masks[i].bits[0];
2132 for (j = 1; j < sizeof(params->masks[i].bits) / sizeof(unsigned int); j++)
2133 if (params->masks[i].bits[j]) {
2138 memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
2139 oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
2140 oparams->cmask = __NEW_TO_OLD_MASK(params->cmask);
2141 oparams->info = params->info;
2142 oparams->msbits = params->msbits;
2143 oparams->rate_num = params->rate_num;
2144 oparams->rate_den = params->rate_den;
2145 oparams->fifo_size = params->fifo_size;
2148 static int use_old_hw_params_ioctl(int fd, unsigned int cmd, snd_pcm_hw_params_t *params)
2150 struct sndrv_pcm_hw_params_old oparams;
2151 unsigned int cmask = 0;
2154 snd_pcm_hw_convert_to_old_params(&oparams, params, &cmask);
2155 res = ioctl(fd, cmd, &oparams);
2156 snd_pcm_hw_convert_from_old_params(params, &oparams);
2157 params->cmask |= cmask;