mirror of
https://github.com/openharmony/third_party_tinyalsa.git
synced 2026-07-18 21:34:26 -04:00
Merge pull request #174 from rohkkumar/mmap_plugin_support
Mmap plugin support
This commit is contained in:
@@ -95,6 +95,16 @@
|
||||
* */
|
||||
#define PCM_NONBLOCK 0x00000010
|
||||
|
||||
/** Means a PCM is opened
|
||||
* @ingroup libtinyalsa-pcm
|
||||
*/
|
||||
#define PCM_STATE_OPEN 0x00
|
||||
|
||||
/** Means a PCM HW_PARAMS is set
|
||||
* @ingroup libtinyalsa-pcm
|
||||
*/
|
||||
#define PCM_STATE_SETUP 0x01
|
||||
|
||||
/** Means a PCM is prepared
|
||||
* @ingroup libtinyalsa-pcm
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#ifndef TINYALSA_PLUGIN_H
|
||||
#define TINYALSA_PLUGIN_H
|
||||
|
||||
#include <poll.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
@@ -128,6 +129,11 @@ struct pcm_plugin_ops {
|
||||
/** Any custom or alsa specific ioctl implementation */
|
||||
int (*ioctl) (struct pcm_plugin *plugin,
|
||||
int cmd, void *arg);
|
||||
void *(*mmap) (struct pcm_plugin *plugin, void *addr, size_t length,
|
||||
int prot, int flags, off_t offset);
|
||||
int (*munmap) (struct pcm_plugin *plugin, void *addr, size_t length);
|
||||
int (*poll) (struct pcm_plugin *plugin, struct pollfd *pfd, nfds_t nfds,
|
||||
int timeout);
|
||||
};
|
||||
|
||||
/** Minimum and maximum values for hardware parameter constraints.
|
||||
|
||||
@@ -404,8 +404,8 @@ int pcm_set_config(struct pcm *pcm, const struct pcm_config *config)
|
||||
pcm->buffer_size = config->period_count * config->period_size;
|
||||
|
||||
if (pcm->flags & PCM_MMAP) {
|
||||
pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size),
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, pcm->fd, 0);
|
||||
pcm->mmap_buffer = pcm->ops->mmap(pcm->data, NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size),
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, 0);
|
||||
if (pcm->mmap_buffer == MAP_FAILED) {
|
||||
int errno_copy = errno;
|
||||
oops(pcm, errno, "failed to mmap buffer %d bytes\n",
|
||||
@@ -544,19 +544,19 @@ static int pcm_hw_mmap_status(struct pcm *pcm)
|
||||
return 0;
|
||||
|
||||
int page_size = sysconf(_SC_PAGE_SIZE);
|
||||
pcm->mmap_status = mmap(NULL, page_size, PROT_READ, MAP_SHARED,
|
||||
pcm->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
|
||||
pcm->mmap_status = pcm->ops->mmap(pcm->data, NULL, page_size, PROT_READ, MAP_SHARED,
|
||||
SNDRV_PCM_MMAP_OFFSET_STATUS);
|
||||
if (pcm->mmap_status == MAP_FAILED)
|
||||
pcm->mmap_status = NULL;
|
||||
if (!pcm->mmap_status)
|
||||
goto mmap_error;
|
||||
|
||||
pcm->mmap_control = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, pcm->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
|
||||
pcm->mmap_control = pcm->ops->mmap(pcm->data, NULL, page_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, SNDRV_PCM_MMAP_OFFSET_CONTROL);
|
||||
if (pcm->mmap_control == MAP_FAILED)
|
||||
pcm->mmap_control = NULL;
|
||||
if (!pcm->mmap_control) {
|
||||
munmap(pcm->mmap_status, page_size);
|
||||
pcm->ops->munmap(pcm->data, pcm->mmap_status, page_size);
|
||||
pcm->mmap_status = NULL;
|
||||
goto mmap_error;
|
||||
}
|
||||
@@ -581,9 +581,9 @@ static void pcm_hw_munmap_status(struct pcm *pcm) {
|
||||
} else {
|
||||
int page_size = sysconf(_SC_PAGE_SIZE);
|
||||
if (pcm->mmap_status)
|
||||
munmap(pcm->mmap_status, page_size);
|
||||
pcm->ops->munmap(pcm->data, pcm->mmap_status, page_size);
|
||||
if (pcm->mmap_control)
|
||||
munmap(pcm->mmap_control, page_size);
|
||||
pcm->ops->munmap(pcm->data, pcm->mmap_control, page_size);
|
||||
}
|
||||
pcm->mmap_status = NULL;
|
||||
pcm->mmap_control = NULL;
|
||||
@@ -813,7 +813,7 @@ int pcm_close(struct pcm *pcm)
|
||||
|
||||
if (pcm->flags & PCM_MMAP) {
|
||||
pcm_stop(pcm);
|
||||
munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
|
||||
pcm->ops->munmap(pcm->data, pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
|
||||
}
|
||||
|
||||
snd_utils_close_dev_node(pcm->snd_node);
|
||||
@@ -948,7 +948,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,
|
||||
fail:
|
||||
pcm_hw_munmap_status(pcm);
|
||||
if (flags & PCM_MMAP)
|
||||
munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
|
||||
pcm->ops->munmap(pcm->data, pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
|
||||
fail_close:
|
||||
pcm->ops->close(pcm->data);
|
||||
fail_close_dev_node:
|
||||
@@ -1264,7 +1264,7 @@ int pcm_wait(struct pcm *pcm, int timeout)
|
||||
|
||||
do {
|
||||
/* let's wait for avail or timeout */
|
||||
err = poll(&pfd, 1, timeout);
|
||||
err = pcm->ops->poll(pcm->data, &pfd, 1, timeout);
|
||||
if (err < 0)
|
||||
return -errno;
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <poll.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <sound/asound.h>
|
||||
#include <tinyalsa/asoundlib.h>
|
||||
@@ -77,6 +78,25 @@ static int pcm_hw_ioctl(void *data, unsigned int cmd, ...)
|
||||
return ioctl(hw_data->fd, cmd, arg);
|
||||
}
|
||||
|
||||
static int pcm_hw_poll(void *data __attribute__((unused)),
|
||||
struct pollfd *pfd, nfds_t nfds, int timeout)
|
||||
{
|
||||
return poll(pfd, nfds, timeout);
|
||||
}
|
||||
|
||||
static void *pcm_hw_mmap(void *data, void *addr, size_t length, int prot,
|
||||
int flags, off_t offset)
|
||||
{
|
||||
struct pcm_hw_data *hw_data = data;
|
||||
|
||||
return mmap(addr, length, prot, flags, hw_data->fd, offset);
|
||||
}
|
||||
|
||||
static int pcm_hw_munmap(void *data __attribute__((unused)), void *addr, size_t length)
|
||||
{
|
||||
return munmap(addr, length);
|
||||
}
|
||||
|
||||
static int pcm_hw_open(unsigned int card, unsigned int device,
|
||||
unsigned int flags, void **data, struct snd_node *node)
|
||||
{
|
||||
@@ -115,5 +135,8 @@ const struct pcm_ops hw_ops = {
|
||||
.open = pcm_hw_open,
|
||||
.close = pcm_hw_close,
|
||||
.ioctl = pcm_hw_ioctl,
|
||||
.mmap = pcm_hw_mmap,
|
||||
.munmap = pcm_hw_munmap,
|
||||
.poll = pcm_hw_poll,
|
||||
};
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#ifndef TINYALSA_SRC_PCM_IO_H
|
||||
#define TINYALSA_SRC_PCM_IO_H
|
||||
|
||||
#include <poll.h>
|
||||
#include <sound/asound.h>
|
||||
|
||||
struct snd_node;
|
||||
@@ -39,6 +40,10 @@ struct pcm_ops {
|
||||
unsigned int flags, void **data, struct snd_node *node);
|
||||
void (*close) (void *data);
|
||||
int (*ioctl) (void *data, unsigned int cmd, ...);
|
||||
void *(*mmap) (void *data, void *addr, size_t length, int prot, int flags,
|
||||
off_t offset);
|
||||
int (*munmap) (void *data, void *addr, size_t length);
|
||||
int (*poll) (void *data, struct pollfd *pfd, nfds_t nfds, int timeout);
|
||||
};
|
||||
|
||||
extern const struct pcm_ops hw_ops;
|
||||
|
||||
+62
-2
@@ -89,6 +89,24 @@ static unsigned int param_list[] = {
|
||||
SNDRV_PCM_HW_PARAM_PERIODS,
|
||||
};
|
||||
|
||||
static int convert_plugin_to_pcm_state(int plugin_state)
|
||||
{
|
||||
switch (plugin_state) {
|
||||
case PCM_PLUG_STATE_SETUP:
|
||||
return PCM_STATE_SETUP;
|
||||
case PCM_PLUG_STATE_RUNNING:
|
||||
return PCM_STATE_RUNNING;
|
||||
case PCM_PLUG_STATE_PREPARED:
|
||||
return PCM_STATE_PREPARED;
|
||||
case PCM_PLUG_STATE_OPEN:
|
||||
return PCM_STATE_OPEN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return PCM_STATE_OPEN;
|
||||
}
|
||||
|
||||
static void pcm_plug_close(void *data)
|
||||
{
|
||||
struct pcm_plug_data *plug_data = data;
|
||||
@@ -513,8 +531,15 @@ static int pcm_plug_sync_ptr(struct pcm_plug_data *plug_data,
|
||||
struct snd_pcm_sync_ptr *sync_ptr)
|
||||
{
|
||||
struct pcm_plugin *plugin = plug_data->plugin;
|
||||
int ret = -EBADFD;
|
||||
|
||||
return plug_data->ops->sync_ptr(plugin, sync_ptr);
|
||||
if (plugin->state >= PCM_PLUG_STATE_SETUP) {
|
||||
ret = plug_data->ops->sync_ptr(plugin, sync_ptr);
|
||||
if (ret == 0)
|
||||
sync_ptr->s.status.state = convert_plugin_to_pcm_state(plugin->state);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pcm_plug_writei_frames(struct pcm_plug_data *plug_data,
|
||||
@@ -545,7 +570,7 @@ static int pcm_plug_ttstamp(struct pcm_plug_data *plug_data,
|
||||
{
|
||||
struct pcm_plugin *plugin = plug_data->plugin;
|
||||
|
||||
if (plugin->state != PCM_PLUG_STATE_RUNNING)
|
||||
if (plugin->state < PCM_PLUG_STATE_SETUP)
|
||||
return -EBADFD;
|
||||
|
||||
return plug_data->ops->ttstamp(plugin, tstamp);
|
||||
@@ -647,6 +672,38 @@ static int pcm_plug_ioctl(void *data, unsigned int cmd, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pcm_plug_poll(void *data, struct pollfd *pfd, nfds_t nfds,
|
||||
int timeout)
|
||||
{
|
||||
struct pcm_plug_data *plug_data = data;
|
||||
struct pcm_plugin *plugin = plug_data->plugin;
|
||||
|
||||
return plug_data->ops->poll(plugin, pfd, nfds, timeout);
|
||||
}
|
||||
|
||||
static void *pcm_plug_mmap(void *data, void *addr, size_t length, int prot,
|
||||
int flags, off_t offset)
|
||||
{
|
||||
struct pcm_plug_data *plug_data = data;
|
||||
struct pcm_plugin *plugin = plug_data->plugin;
|
||||
|
||||
if (plugin->state != PCM_PLUG_STATE_SETUP)
|
||||
return NULL;
|
||||
|
||||
return plug_data->ops->mmap(plugin, addr, length, prot, flags, offset);
|
||||
}
|
||||
|
||||
static int pcm_plug_munmap(void *data, void *addr, size_t length)
|
||||
{
|
||||
struct pcm_plug_data *plug_data = data;
|
||||
struct pcm_plugin *plugin = plug_data->plugin;
|
||||
|
||||
if (plugin->state != PCM_PLUG_STATE_SETUP)
|
||||
return -EBADFD;
|
||||
|
||||
return plug_data->ops->munmap(plugin, addr, length);
|
||||
}
|
||||
|
||||
static int pcm_plug_open(unsigned int card, unsigned int device,
|
||||
unsigned int flags, void **data, struct snd_node *pcm_node)
|
||||
{
|
||||
@@ -715,4 +772,7 @@ const struct pcm_ops plug_ops = {
|
||||
.open = pcm_plug_open,
|
||||
.close = pcm_plug_close,
|
||||
.ioctl = pcm_plug_ioctl,
|
||||
.mmap = pcm_plug_mmap,
|
||||
.munmap = pcm_plug_munmap,
|
||||
.poll = pcm_plug_poll,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user