]> git.alsa-project.org Git - alsa-lib.git/commitdiff
pcm: hw: maintain fallback mode for status data mapping
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sun, 25 Jun 2017 04:41:23 +0000 (13:41 +0900)
committerTakashi Iwai <tiwai@suse.de>
Tue, 27 Jun 2017 09:11:46 +0000 (11:11 +0200)
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>
src/pcm/pcm_hw.c

index a3d1f1372f5d4268f8eacbdf596d24d9cd1799c1..788579412904e38aed33fdb3ec3620859f4048d6 100644 (file)
@@ -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;
+
+       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);
+       }
 
-       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;
+       if (mmap_status == MAP_FAILED || mmap_status == NULL) {
+               mmap_status = &sync_ptr->s.status;
+               fallbacked = true;
        } else {
-               hw->mmap_status = ptr;
+               fallbacked = false;
        }
 
-       return 0;
+       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;
 }