mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
pcm: hw: maintain fallback mode for status data mapping
In current implementation, results to map status/control data are not maintained separately. It's handled as a fatal error that mapping of status data is successful and mapping of control data is failed. However, it's possible to handle this case by utilizing fallback buffer. This commit adds a member into a local structure to maintain fallback mode just for the mapping of status data as a preparation of later commit, in which mapping results are maintained separately for each of status/control data. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
afadf61e44
commit
9c9e3d0822
1 changed files with 45 additions and 35 deletions
|
|
@ -91,10 +91,12 @@ typedef struct {
|
|||
int version;
|
||||
int fd;
|
||||
int card, device, subdevice;
|
||||
int sync_ptr_ioctl;
|
||||
|
||||
volatile struct snd_pcm_mmap_status * mmap_status;
|
||||
struct snd_pcm_mmap_control *mmap_control;
|
||||
bool mmap_status_fallbacked;
|
||||
struct snd_pcm_sync_ptr *sync_ptr;
|
||||
|
||||
int period_event;
|
||||
snd_timer_t *period_timer;
|
||||
struct pollfd period_timer_pfd;
|
||||
|
|
@ -867,42 +869,53 @@ static snd_pcm_sframes_t snd_pcm_hw_readn(snd_pcm_t *pcm, void **bufs, snd_pcm_u
|
|||
return xfern.result;
|
||||
}
|
||||
|
||||
static int map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr)
|
||||
static bool map_status_data(snd_pcm_hw_t *hw, struct snd_pcm_sync_ptr *sync_ptr,
|
||||
bool force_fallback)
|
||||
{
|
||||
void *ptr;
|
||||
struct snd_pcm_mmap_status *mmap_status;
|
||||
bool fallbacked;
|
||||
|
||||
ptr = MAP_FAILED;
|
||||
if (hw->sync_ptr_ioctl == 0)
|
||||
ptr = mmap(NULL, page_align(sizeof(struct snd_pcm_mmap_status)),
|
||||
PROT_READ, MAP_FILE|MAP_SHARED,
|
||||
hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
|
||||
if (ptr == MAP_FAILED || ptr == NULL) {
|
||||
hw->mmap_status = &sync_ptr->s.status;
|
||||
hw->mmap_control = &sync_ptr->c.control;
|
||||
hw->sync_ptr_ioctl = 1;
|
||||
} else {
|
||||
hw->mmap_status = ptr;
|
||||
mmap_status = MAP_FAILED;
|
||||
if (!force_fallback) {
|
||||
mmap_status = mmap(NULL, page_align(sizeof(*mmap_status)),
|
||||
PROT_READ, MAP_FILE|MAP_SHARED,
|
||||
hw->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (mmap_status == MAP_FAILED || mmap_status == NULL) {
|
||||
mmap_status = &sync_ptr->s.status;
|
||||
fallbacked = true;
|
||||
} else {
|
||||
fallbacked = false;
|
||||
}
|
||||
|
||||
hw->mmap_status = mmap_status;
|
||||
|
||||
return fallbacked;
|
||||
}
|
||||
|
||||
static int map_control_data(snd_pcm_hw_t *hw)
|
||||
static bool map_control_data(snd_pcm_hw_t *hw,
|
||||
struct snd_pcm_sync_ptr *sync_ptr,
|
||||
bool force_fallback)
|
||||
{
|
||||
void *ptr;
|
||||
struct snd_pcm_mmap_control *mmap_control;
|
||||
int err;
|
||||
if (hw->sync_ptr_ioctl == 0) {
|
||||
ptr = mmap(NULL, page_align(sizeof(struct snd_pcm_mmap_control)),
|
||||
PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
|
||||
hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
|
||||
if (ptr == MAP_FAILED || ptr == NULL) {
|
||||
|
||||
if (!force_fallback) {
|
||||
mmap_control = mmap(NULL, page_align(sizeof(*mmap_control)),
|
||||
PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
|
||||
hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
|
||||
if (mmap_control == MAP_FAILED || mmap_control == NULL) {
|
||||
err = -errno;
|
||||
SYSMSG("control mmap failed (%i)", err);
|
||||
return err;
|
||||
}
|
||||
hw->mmap_control = ptr;
|
||||
} else {
|
||||
mmap_control = &sync_ptr->c.control;
|
||||
}
|
||||
|
||||
hw->mmap_control = mmap_control;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -918,18 +931,14 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback)
|
|||
return -ENOMEM;
|
||||
memset(sync_ptr, 0, sizeof(*sync_ptr));
|
||||
|
||||
hw->sync_ptr_ioctl = (int)force_fallback;
|
||||
|
||||
err = map_status_data(hw, sync_ptr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = map_control_data(hw);
|
||||
hw->mmap_status_fallbacked =
|
||||
map_status_data(hw, sync_ptr, force_fallback);
|
||||
err = map_control_data(hw, sync_ptr, hw->mmap_status_fallbacked);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Any fallback mode needs to keep the buffer. */
|
||||
if (hw->sync_ptr_ioctl == 0) {
|
||||
if (hw->mmap_status_fallbacked == 0) {
|
||||
hw->sync_ptr = sync_ptr;
|
||||
} else {
|
||||
free(sync_ptr);
|
||||
|
|
@ -944,7 +953,7 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback)
|
|||
offsetof(struct snd_pcm_mmap_status, hw_ptr));
|
||||
snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd,
|
||||
SNDRV_PCM_MMAP_OFFSET_CONTROL);
|
||||
if (hw->sync_ptr_ioctl) {
|
||||
if (hw->mmap_status_fallbacked) {
|
||||
if (ioctl(hw->fd, SNDRV_PCM_IOCTL_SYNC_PTR, hw->sync_ptr) < 0) {
|
||||
err = -errno;
|
||||
SYSMSG("SNDRV_PCM_IOCTL_SYNC_PTR failed (%i)", err);
|
||||
|
|
@ -957,7 +966,7 @@ static int map_status_and_control_data(snd_pcm_t *pcm, bool force_fallback)
|
|||
|
||||
static void unmap_status_data(snd_pcm_hw_t *hw)
|
||||
{
|
||||
if (!hw->sync_ptr) {
|
||||
if (!hw->mmap_status_fallbacked) {
|
||||
if (munmap((void *)hw->mmap_status,
|
||||
page_align(sizeof(*hw->mmap_status))) < 0)
|
||||
SYSMSG("status munmap failed (%u)", errno);
|
||||
|
|
@ -966,7 +975,7 @@ static void unmap_status_data(snd_pcm_hw_t *hw)
|
|||
|
||||
static void unmap_control_data(snd_pcm_hw_t *hw)
|
||||
{
|
||||
if (!hw->sync_ptr) {
|
||||
if (!hw->mmap_status_fallbacked) {
|
||||
if (munmap((void *)hw->mmap_control,
|
||||
page_align(sizeof(*hw->mmap_control))) < 0)
|
||||
SYSMSG("control munmap failed (%u)", errno);
|
||||
|
|
@ -978,11 +987,12 @@ static void unmap_status_and_control_data(snd_pcm_hw_t *hw)
|
|||
unmap_status_data(hw);
|
||||
unmap_control_data(hw);
|
||||
|
||||
if (hw->sync_ptr)
|
||||
if (hw->mmap_status_fallbacked)
|
||||
free(hw->sync_ptr);
|
||||
|
||||
hw->mmap_status = NULL;
|
||||
hw->mmap_control = NULL;
|
||||
hw->mmap_status_fallbacked = false;
|
||||
hw->sync_ptr = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue