1d5ac70f0Sopenharmony_ci/** 2d5ac70f0Sopenharmony_ci * \file pcm/pcm_shm.c 3d5ac70f0Sopenharmony_ci * \ingroup PCM_Plugins 4d5ac70f0Sopenharmony_ci * \brief PCM Shared Memory Plugin Interface 5d5ac70f0Sopenharmony_ci * \author Abramo Bagnara <abramo@alsa-project.org> 6d5ac70f0Sopenharmony_ci * \date 2000-2001 7d5ac70f0Sopenharmony_ci */ 8d5ac70f0Sopenharmony_ci/* 9d5ac70f0Sopenharmony_ci * PCM - Shared Memory Client 10d5ac70f0Sopenharmony_ci * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> 11d5ac70f0Sopenharmony_ci * 12d5ac70f0Sopenharmony_ci * 13d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 14d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 15d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 16d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 17d5ac70f0Sopenharmony_ci * 18d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 19d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 20d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 22d5ac70f0Sopenharmony_ci * 23d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 24d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 25d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26d5ac70f0Sopenharmony_ci * 27d5ac70f0Sopenharmony_ci */ 28d5ac70f0Sopenharmony_ci 29d5ac70f0Sopenharmony_ci#include "pcm_local.h" 30d5ac70f0Sopenharmony_ci#include <stdio.h> 31d5ac70f0Sopenharmony_ci#include <stdlib.h> 32d5ac70f0Sopenharmony_ci#include <stddef.h> 33d5ac70f0Sopenharmony_ci#include <limits.h> 34d5ac70f0Sopenharmony_ci#include <unistd.h> 35d5ac70f0Sopenharmony_ci#include <string.h> 36d5ac70f0Sopenharmony_ci#include <fcntl.h> 37d5ac70f0Sopenharmony_ci#include <sys/ioctl.h> 38d5ac70f0Sopenharmony_ci#include <sys/shm.h> 39d5ac70f0Sopenharmony_ci#include <sys/socket.h> 40d5ac70f0Sopenharmony_ci#include <poll.h> 41d5ac70f0Sopenharmony_ci#include <sys/un.h> 42d5ac70f0Sopenharmony_ci#include <sys/mman.h> 43d5ac70f0Sopenharmony_ci#include <netinet/in.h> 44d5ac70f0Sopenharmony_ci#include <arpa/inet.h> 45d5ac70f0Sopenharmony_ci#include <net/if.h> 46d5ac70f0Sopenharmony_ci#include <netdb.h> 47d5ac70f0Sopenharmony_ci#include "aserver.h" 48d5ac70f0Sopenharmony_ci 49d5ac70f0Sopenharmony_ci#ifndef PIC 50d5ac70f0Sopenharmony_ci/* entry for static linking */ 51d5ac70f0Sopenharmony_ciconst char *_snd_module_pcm_shm = ""; 52d5ac70f0Sopenharmony_ci#endif 53d5ac70f0Sopenharmony_ci 54d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 55d5ac70f0Sopenharmony_citypedef struct { 56d5ac70f0Sopenharmony_ci int socket; 57d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl; 58d5ac70f0Sopenharmony_ci} snd_pcm_shm_t; 59d5ac70f0Sopenharmony_ci#endif 60d5ac70f0Sopenharmony_ci 61d5ac70f0Sopenharmony_cistatic long snd_pcm_shm_action_fd0(snd_pcm_t *pcm, int *fd) 62d5ac70f0Sopenharmony_ci{ 63d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 64d5ac70f0Sopenharmony_ci int err; 65d5ac70f0Sopenharmony_ci char buf[1] = ""; 66d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 67d5ac70f0Sopenharmony_ci 68d5ac70f0Sopenharmony_ci err = write(shm->socket, buf, 1); 69d5ac70f0Sopenharmony_ci if (err != 1) 70d5ac70f0Sopenharmony_ci return -EBADFD; 71d5ac70f0Sopenharmony_ci err = snd_receive_fd(shm->socket, buf, 1, fd); 72d5ac70f0Sopenharmony_ci if (err != 1) 73d5ac70f0Sopenharmony_ci return -EBADFD; 74d5ac70f0Sopenharmony_ci if (ctrl->cmd) { 75d5ac70f0Sopenharmony_ci SNDERR("Server has not done the cmd"); 76d5ac70f0Sopenharmony_ci return -EBADFD; 77d5ac70f0Sopenharmony_ci } 78d5ac70f0Sopenharmony_ci return ctrl->result; 79d5ac70f0Sopenharmony_ci} 80d5ac70f0Sopenharmony_ci 81d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_new_rbptr(snd_pcm_t *pcm, snd_pcm_shm_t *shm, 82d5ac70f0Sopenharmony_ci snd_pcm_rbptr_t *rbptr, volatile snd_pcm_shm_rbptr_t *shm_rbptr) 83d5ac70f0Sopenharmony_ci{ 84d5ac70f0Sopenharmony_ci if (!shm_rbptr->use_mmap) { 85d5ac70f0Sopenharmony_ci if (&pcm->hw == rbptr) 86d5ac70f0Sopenharmony_ci snd_pcm_set_hw_ptr(pcm, &shm_rbptr->ptr, -1, 0); 87d5ac70f0Sopenharmony_ci else 88d5ac70f0Sopenharmony_ci snd_pcm_set_appl_ptr(pcm, &shm_rbptr->ptr, -1, 0); 89d5ac70f0Sopenharmony_ci } else { 90d5ac70f0Sopenharmony_ci void *ptr; 91d5ac70f0Sopenharmony_ci size_t mmap_size, mmap_offset, offset; 92d5ac70f0Sopenharmony_ci int fd; 93d5ac70f0Sopenharmony_ci long result; 94d5ac70f0Sopenharmony_ci 95d5ac70f0Sopenharmony_ci shm->ctrl->cmd = &pcm->hw == rbptr ? SND_PCM_IOCTL_HW_PTR_FD : SND_PCM_IOCTL_APPL_PTR_FD; 96d5ac70f0Sopenharmony_ci result = snd_pcm_shm_action_fd0(pcm, &fd); 97d5ac70f0Sopenharmony_ci if (result < 0) 98d5ac70f0Sopenharmony_ci return result; 99d5ac70f0Sopenharmony_ci mmap_size = page_ptr(shm_rbptr->offset, sizeof(snd_pcm_uframes_t), &offset, &mmap_offset); 100d5ac70f0Sopenharmony_ci ptr = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, mmap_offset); 101d5ac70f0Sopenharmony_ci if (ptr == MAP_FAILED || ptr == NULL) { 102d5ac70f0Sopenharmony_ci SYSERR("shm rbptr mmap failed"); 103d5ac70f0Sopenharmony_ci return -errno; 104d5ac70f0Sopenharmony_ci } 105d5ac70f0Sopenharmony_ci if (&pcm->hw == rbptr) 106d5ac70f0Sopenharmony_ci snd_pcm_set_hw_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset); 107d5ac70f0Sopenharmony_ci else 108d5ac70f0Sopenharmony_ci snd_pcm_set_appl_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset); 109d5ac70f0Sopenharmony_ci } 110d5ac70f0Sopenharmony_ci return 0; 111d5ac70f0Sopenharmony_ci} 112d5ac70f0Sopenharmony_ci 113d5ac70f0Sopenharmony_cistatic long snd_pcm_shm_action(snd_pcm_t *pcm) 114d5ac70f0Sopenharmony_ci{ 115d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 116d5ac70f0Sopenharmony_ci int err, result; 117d5ac70f0Sopenharmony_ci char buf[1] = ""; 118d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 119d5ac70f0Sopenharmony_ci 120d5ac70f0Sopenharmony_ci if (ctrl->hw.changed || ctrl->appl.changed) 121d5ac70f0Sopenharmony_ci return -EBADFD; 122d5ac70f0Sopenharmony_ci err = write(shm->socket, buf, 1); 123d5ac70f0Sopenharmony_ci if (err != 1) 124d5ac70f0Sopenharmony_ci return -EBADFD; 125d5ac70f0Sopenharmony_ci err = read(shm->socket, buf, 1); 126d5ac70f0Sopenharmony_ci if (err != 1) 127d5ac70f0Sopenharmony_ci return -EBADFD; 128d5ac70f0Sopenharmony_ci if (ctrl->cmd) { 129d5ac70f0Sopenharmony_ci SNDERR("Server has not done the cmd"); 130d5ac70f0Sopenharmony_ci return -EBADFD; 131d5ac70f0Sopenharmony_ci } 132d5ac70f0Sopenharmony_ci result = ctrl->result; 133d5ac70f0Sopenharmony_ci if (ctrl->hw.changed) { 134d5ac70f0Sopenharmony_ci err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw); 135d5ac70f0Sopenharmony_ci if (err < 0) 136d5ac70f0Sopenharmony_ci return err; 137d5ac70f0Sopenharmony_ci ctrl->hw.changed = 0; 138d5ac70f0Sopenharmony_ci } 139d5ac70f0Sopenharmony_ci if (ctrl->appl.changed) { 140d5ac70f0Sopenharmony_ci err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl); 141d5ac70f0Sopenharmony_ci if (err < 0) 142d5ac70f0Sopenharmony_ci return err; 143d5ac70f0Sopenharmony_ci ctrl->appl.changed = 0; 144d5ac70f0Sopenharmony_ci } 145d5ac70f0Sopenharmony_ci return result; 146d5ac70f0Sopenharmony_ci} 147d5ac70f0Sopenharmony_ci 148d5ac70f0Sopenharmony_cistatic long snd_pcm_shm_action_fd(snd_pcm_t *pcm, int *fd) 149d5ac70f0Sopenharmony_ci{ 150d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 151d5ac70f0Sopenharmony_ci int err; 152d5ac70f0Sopenharmony_ci char buf[1] = ""; 153d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 154d5ac70f0Sopenharmony_ci 155d5ac70f0Sopenharmony_ci if (ctrl->hw.changed || ctrl->appl.changed) 156d5ac70f0Sopenharmony_ci return -EBADFD; 157d5ac70f0Sopenharmony_ci err = write(shm->socket, buf, 1); 158d5ac70f0Sopenharmony_ci if (err != 1) 159d5ac70f0Sopenharmony_ci return -EBADFD; 160d5ac70f0Sopenharmony_ci err = snd_receive_fd(shm->socket, buf, 1, fd); 161d5ac70f0Sopenharmony_ci if (err != 1) 162d5ac70f0Sopenharmony_ci return -EBADFD; 163d5ac70f0Sopenharmony_ci if (ctrl->cmd) { 164d5ac70f0Sopenharmony_ci SNDERR("Server has not done the cmd"); 165d5ac70f0Sopenharmony_ci return -EBADFD; 166d5ac70f0Sopenharmony_ci } 167d5ac70f0Sopenharmony_ci if (ctrl->hw.changed) { 168d5ac70f0Sopenharmony_ci err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw); 169d5ac70f0Sopenharmony_ci if (err < 0) 170d5ac70f0Sopenharmony_ci return err; 171d5ac70f0Sopenharmony_ci ctrl->hw.changed = 0; 172d5ac70f0Sopenharmony_ci } 173d5ac70f0Sopenharmony_ci if (ctrl->appl.changed) { 174d5ac70f0Sopenharmony_ci err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl); 175d5ac70f0Sopenharmony_ci if (err < 0) 176d5ac70f0Sopenharmony_ci return err; 177d5ac70f0Sopenharmony_ci ctrl->appl.changed = 0; 178d5ac70f0Sopenharmony_ci } 179d5ac70f0Sopenharmony_ci return ctrl->result; 180d5ac70f0Sopenharmony_ci} 181d5ac70f0Sopenharmony_ci 182d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) 183d5ac70f0Sopenharmony_ci{ 184d5ac70f0Sopenharmony_ci return 0; 185d5ac70f0Sopenharmony_ci} 186d5ac70f0Sopenharmony_ci 187d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_async(snd_pcm_t *pcm, int sig, pid_t pid) 188d5ac70f0Sopenharmony_ci{ 189d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 190d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 191d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_ASYNC; 192d5ac70f0Sopenharmony_ci ctrl->u.async.sig = sig; 193d5ac70f0Sopenharmony_ci ctrl->u.async.pid = pid; 194d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 195d5ac70f0Sopenharmony_ci} 196d5ac70f0Sopenharmony_ci 197d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info) 198d5ac70f0Sopenharmony_ci{ 199d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 200d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 201d5ac70f0Sopenharmony_ci int err; 202d5ac70f0Sopenharmony_ci// ctrl->u.info = *info; 203d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_INFO; 204d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 205d5ac70f0Sopenharmony_ci if (err < 0) 206d5ac70f0Sopenharmony_ci return err; 207d5ac70f0Sopenharmony_ci *info = ctrl->u.info; 208d5ac70f0Sopenharmony_ci return err; 209d5ac70f0Sopenharmony_ci} 210d5ac70f0Sopenharmony_ci 211d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED) 212d5ac70f0Sopenharmony_ci{ 213d5ac70f0Sopenharmony_ci return 0; 214d5ac70f0Sopenharmony_ci} 215d5ac70f0Sopenharmony_ci 216d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams) 217d5ac70f0Sopenharmony_ci{ 218d5ac70f0Sopenharmony_ci snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP }; 219d5ac70f0Sopenharmony_ci _snd_pcm_hw_params_any(sparams); 220d5ac70f0Sopenharmony_ci _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS, 221d5ac70f0Sopenharmony_ci &saccess_mask); 222d5ac70f0Sopenharmony_ci return 0; 223d5ac70f0Sopenharmony_ci} 224d5ac70f0Sopenharmony_ci 225d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params, 226d5ac70f0Sopenharmony_ci snd_pcm_hw_params_t *sparams) 227d5ac70f0Sopenharmony_ci{ 228d5ac70f0Sopenharmony_ci int err; 229d5ac70f0Sopenharmony_ci unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS; 230d5ac70f0Sopenharmony_ci const snd_pcm_access_mask_t *access_mask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS); 231d5ac70f0Sopenharmony_ci if (!snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) && 232d5ac70f0Sopenharmony_ci !snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) { 233d5ac70f0Sopenharmony_ci err = _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS, 234d5ac70f0Sopenharmony_ci access_mask); 235d5ac70f0Sopenharmony_ci if (err < 0) 236d5ac70f0Sopenharmony_ci return err; 237d5ac70f0Sopenharmony_ci } 238d5ac70f0Sopenharmony_ci err = _snd_pcm_hw_params_refine(sparams, links, params); 239d5ac70f0Sopenharmony_ci if (err < 0) 240d5ac70f0Sopenharmony_ci return err; 241d5ac70f0Sopenharmony_ci return 0; 242d5ac70f0Sopenharmony_ci} 243d5ac70f0Sopenharmony_ci 244d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params, 245d5ac70f0Sopenharmony_ci snd_pcm_hw_params_t *sparams) 246d5ac70f0Sopenharmony_ci{ 247d5ac70f0Sopenharmony_ci int err; 248d5ac70f0Sopenharmony_ci unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS; 249d5ac70f0Sopenharmony_ci snd_pcm_access_mask_t access_mask; 250d5ac70f0Sopenharmony_ci snd_mask_copy(&access_mask, snd_pcm_hw_param_get_mask(sparams, SND_PCM_HW_PARAM_ACCESS)); 251d5ac70f0Sopenharmony_ci snd_pcm_access_mask_set(&access_mask, SND_PCM_ACCESS_RW_INTERLEAVED); 252d5ac70f0Sopenharmony_ci snd_pcm_access_mask_set(&access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED); 253d5ac70f0Sopenharmony_ci err = _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS, 254d5ac70f0Sopenharmony_ci &access_mask); 255d5ac70f0Sopenharmony_ci if (err < 0) 256d5ac70f0Sopenharmony_ci return err; 257d5ac70f0Sopenharmony_ci err = _snd_pcm_hw_params_refine(params, links, sparams); 258d5ac70f0Sopenharmony_ci if (err < 0) 259d5ac70f0Sopenharmony_ci return err; 260d5ac70f0Sopenharmony_ci return 0; 261d5ac70f0Sopenharmony_ci} 262d5ac70f0Sopenharmony_ci 263d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_refine_slave(snd_pcm_t *pcm, 264d5ac70f0Sopenharmony_ci snd_pcm_hw_params_t *params) 265d5ac70f0Sopenharmony_ci{ 266d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 267d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 268d5ac70f0Sopenharmony_ci int err; 269d5ac70f0Sopenharmony_ci ctrl->u.hw_refine = *params; 270d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_HW_REFINE; 271d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 272d5ac70f0Sopenharmony_ci *params = ctrl->u.hw_refine; 273d5ac70f0Sopenharmony_ci return err; 274d5ac70f0Sopenharmony_ci} 275d5ac70f0Sopenharmony_ci 276d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) 277d5ac70f0Sopenharmony_ci{ 278d5ac70f0Sopenharmony_ci return snd_pcm_hw_refine_slave(pcm, params, 279d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_cprepare, 280d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_cchange, 281d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_sprepare, 282d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_schange, 283d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_slave); 284d5ac70f0Sopenharmony_ci} 285d5ac70f0Sopenharmony_ci 286d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_params_slave(snd_pcm_t *pcm, 287d5ac70f0Sopenharmony_ci snd_pcm_hw_params_t *params) 288d5ac70f0Sopenharmony_ci{ 289d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 290d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 291d5ac70f0Sopenharmony_ci int err; 292d5ac70f0Sopenharmony_ci params->flags |= SND_PCM_HW_PARAMS_EXPORT_BUFFER; 293d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_HW_PARAMS; 294d5ac70f0Sopenharmony_ci ctrl->u.hw_params = *params; 295d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 296d5ac70f0Sopenharmony_ci *params = ctrl->u.hw_params; 297d5ac70f0Sopenharmony_ci return err; 298d5ac70f0Sopenharmony_ci} 299d5ac70f0Sopenharmony_ci 300d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params) 301d5ac70f0Sopenharmony_ci{ 302d5ac70f0Sopenharmony_ci return snd_pcm_hw_params_slave(pcm, params, 303d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_cchange, 304d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_sprepare, 305d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_refine_schange, 306d5ac70f0Sopenharmony_ci snd_pcm_shm_hw_params_slave); 307d5ac70f0Sopenharmony_ci} 308d5ac70f0Sopenharmony_ci 309d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hw_free(snd_pcm_t *pcm) 310d5ac70f0Sopenharmony_ci{ 311d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 312d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 313d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_HW_FREE; 314d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 315d5ac70f0Sopenharmony_ci} 316d5ac70f0Sopenharmony_ci 317d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) 318d5ac70f0Sopenharmony_ci{ 319d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 320d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 321d5ac70f0Sopenharmony_ci int err; 322d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_SW_PARAMS; 323d5ac70f0Sopenharmony_ci ctrl->u.sw_params = *params; 324d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 325d5ac70f0Sopenharmony_ci *params = ctrl->u.sw_params; 326d5ac70f0Sopenharmony_ci if (err < 0) 327d5ac70f0Sopenharmony_ci return err; 328d5ac70f0Sopenharmony_ci return err; 329d5ac70f0Sopenharmony_ci} 330d5ac70f0Sopenharmony_ci 331d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 332d5ac70f0Sopenharmony_ci{ 333d5ac70f0Sopenharmony_ci return 0; 334d5ac70f0Sopenharmony_ci} 335d5ac70f0Sopenharmony_ci 336d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_munmap(snd_pcm_t *pcm) 337d5ac70f0Sopenharmony_ci{ 338d5ac70f0Sopenharmony_ci unsigned int c; 339d5ac70f0Sopenharmony_ci for (c = 0; c < pcm->channels; ++c) { 340d5ac70f0Sopenharmony_ci snd_pcm_channel_info_t *i = &pcm->mmap_channels[c]; 341d5ac70f0Sopenharmony_ci unsigned int c1; 342d5ac70f0Sopenharmony_ci int err; 343d5ac70f0Sopenharmony_ci if (i->type != SND_PCM_AREA_MMAP) 344d5ac70f0Sopenharmony_ci continue; 345d5ac70f0Sopenharmony_ci if (i->u.mmap.fd < 0) 346d5ac70f0Sopenharmony_ci continue; 347d5ac70f0Sopenharmony_ci for (c1 = c + 1; c1 < pcm->channels; ++c1) { 348d5ac70f0Sopenharmony_ci snd_pcm_channel_info_t *i1 = &pcm->mmap_channels[c1]; 349d5ac70f0Sopenharmony_ci if (i1->type != SND_PCM_AREA_MMAP) 350d5ac70f0Sopenharmony_ci continue; 351d5ac70f0Sopenharmony_ci if (i1->u.mmap.fd != i->u.mmap.fd) 352d5ac70f0Sopenharmony_ci continue; 353d5ac70f0Sopenharmony_ci i1->u.mmap.fd = -1; 354d5ac70f0Sopenharmony_ci } 355d5ac70f0Sopenharmony_ci err = close(i->u.mmap.fd); 356d5ac70f0Sopenharmony_ci if (err < 0) { 357d5ac70f0Sopenharmony_ci SYSERR("close failed"); 358d5ac70f0Sopenharmony_ci return -errno; 359d5ac70f0Sopenharmony_ci } 360d5ac70f0Sopenharmony_ci } 361d5ac70f0Sopenharmony_ci return 0; 362d5ac70f0Sopenharmony_ci} 363d5ac70f0Sopenharmony_ci 364d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info) 365d5ac70f0Sopenharmony_ci{ 366d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 367d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 368d5ac70f0Sopenharmony_ci int err; 369d5ac70f0Sopenharmony_ci int fd; 370d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_CHANNEL_INFO; 371d5ac70f0Sopenharmony_ci ctrl->u.channel_info = *info; 372d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action_fd(pcm, &fd); 373d5ac70f0Sopenharmony_ci if (err < 0) 374d5ac70f0Sopenharmony_ci return err; 375d5ac70f0Sopenharmony_ci *info = ctrl->u.channel_info; 376d5ac70f0Sopenharmony_ci info->addr = 0; 377d5ac70f0Sopenharmony_ci switch (info->type) { 378d5ac70f0Sopenharmony_ci case SND_PCM_AREA_MMAP: 379d5ac70f0Sopenharmony_ci info->u.mmap.fd = fd; 380d5ac70f0Sopenharmony_ci break; 381d5ac70f0Sopenharmony_ci case SND_PCM_AREA_SHM: 382d5ac70f0Sopenharmony_ci break; 383d5ac70f0Sopenharmony_ci default: 384d5ac70f0Sopenharmony_ci assert(0); 385d5ac70f0Sopenharmony_ci break; 386d5ac70f0Sopenharmony_ci } 387d5ac70f0Sopenharmony_ci return err; 388d5ac70f0Sopenharmony_ci} 389d5ac70f0Sopenharmony_ci 390d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_status(snd_pcm_t *pcm, snd_pcm_status_t * status) 391d5ac70f0Sopenharmony_ci{ 392d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 393d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 394d5ac70f0Sopenharmony_ci int err; 395d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_STATUS; 396d5ac70f0Sopenharmony_ci // ctrl->u.status = *status; 397d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 398d5ac70f0Sopenharmony_ci if (err < 0) 399d5ac70f0Sopenharmony_ci return err; 400d5ac70f0Sopenharmony_ci *status = ctrl->u.status; 401d5ac70f0Sopenharmony_ci return err; 402d5ac70f0Sopenharmony_ci} 403d5ac70f0Sopenharmony_ci 404d5ac70f0Sopenharmony_cistatic snd_pcm_state_t snd_pcm_shm_state(snd_pcm_t *pcm) 405d5ac70f0Sopenharmony_ci{ 406d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 407d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 408d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_STATE; 409d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 410d5ac70f0Sopenharmony_ci} 411d5ac70f0Sopenharmony_ci 412d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_hwsync(snd_pcm_t *pcm) 413d5ac70f0Sopenharmony_ci{ 414d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 415d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 416d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_HWSYNC; 417d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 418d5ac70f0Sopenharmony_ci} 419d5ac70f0Sopenharmony_ci 420d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp) 421d5ac70f0Sopenharmony_ci{ 422d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 423d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 424d5ac70f0Sopenharmony_ci int err; 425d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_DELAY; 426d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 427d5ac70f0Sopenharmony_ci if (err < 0) 428d5ac70f0Sopenharmony_ci return err; 429d5ac70f0Sopenharmony_ci *delayp = ctrl->u.delay.frames; 430d5ac70f0Sopenharmony_ci return err; 431d5ac70f0Sopenharmony_ci} 432d5ac70f0Sopenharmony_ci 433d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_shm_avail_update(snd_pcm_t *pcm) 434d5ac70f0Sopenharmony_ci{ 435d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 436d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 437d5ac70f0Sopenharmony_ci int err; 438d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_AVAIL_UPDATE; 439d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 440d5ac70f0Sopenharmony_ci if (err < 0) 441d5ac70f0Sopenharmony_ci return err; 442d5ac70f0Sopenharmony_ci return err; 443d5ac70f0Sopenharmony_ci} 444d5ac70f0Sopenharmony_ci 445d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_htimestamp(snd_pcm_t *pcm ATTRIBUTE_UNUSED, 446d5ac70f0Sopenharmony_ci snd_pcm_uframes_t *avail ATTRIBUTE_UNUSED, 447d5ac70f0Sopenharmony_ci snd_htimestamp_t *tstamp ATTRIBUTE_UNUSED) 448d5ac70f0Sopenharmony_ci{ 449d5ac70f0Sopenharmony_ci return -EIO; /* not implemented yet */ 450d5ac70f0Sopenharmony_ci} 451d5ac70f0Sopenharmony_ci 452d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_prepare(snd_pcm_t *pcm) 453d5ac70f0Sopenharmony_ci{ 454d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 455d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 456d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_PREPARE; 457d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 458d5ac70f0Sopenharmony_ci} 459d5ac70f0Sopenharmony_ci 460d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_reset(snd_pcm_t *pcm) 461d5ac70f0Sopenharmony_ci{ 462d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 463d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 464d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_RESET; 465d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 466d5ac70f0Sopenharmony_ci} 467d5ac70f0Sopenharmony_ci 468d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_start(snd_pcm_t *pcm) 469d5ac70f0Sopenharmony_ci{ 470d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 471d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 472d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_START; 473d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 474d5ac70f0Sopenharmony_ci} 475d5ac70f0Sopenharmony_ci 476d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_drop(snd_pcm_t *pcm) 477d5ac70f0Sopenharmony_ci{ 478d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 479d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 480d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_DROP; 481d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 482d5ac70f0Sopenharmony_ci} 483d5ac70f0Sopenharmony_ci 484d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_drain(snd_pcm_t *pcm) 485d5ac70f0Sopenharmony_ci{ 486d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 487d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 488d5ac70f0Sopenharmony_ci int err; 489d5ac70f0Sopenharmony_ci do { 490d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_DRAIN; 491d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action(pcm); 492d5ac70f0Sopenharmony_ci if (err != -EAGAIN) 493d5ac70f0Sopenharmony_ci break; 494d5ac70f0Sopenharmony_ci usleep(10000); 495d5ac70f0Sopenharmony_ci } while (1); 496d5ac70f0Sopenharmony_ci if (err < 0) 497d5ac70f0Sopenharmony_ci return err; 498d5ac70f0Sopenharmony_ci if (!(pcm->mode & SND_PCM_NONBLOCK)) 499d5ac70f0Sopenharmony_ci snd_pcm_wait(pcm, SND_PCM_WAIT_DRAIN); 500d5ac70f0Sopenharmony_ci return err; 501d5ac70f0Sopenharmony_ci} 502d5ac70f0Sopenharmony_ci 503d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_pause(snd_pcm_t *pcm, int enable) 504d5ac70f0Sopenharmony_ci{ 505d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 506d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 507d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_PAUSE; 508d5ac70f0Sopenharmony_ci ctrl->u.pause.enable = enable; 509d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 510d5ac70f0Sopenharmony_ci} 511d5ac70f0Sopenharmony_ci 512d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_shm_rewindable(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 513d5ac70f0Sopenharmony_ci{ 514d5ac70f0Sopenharmony_ci return 0; /* FIX ME */ 515d5ac70f0Sopenharmony_ci} 516d5ac70f0Sopenharmony_ci 517d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames) 518d5ac70f0Sopenharmony_ci{ 519d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 520d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 521d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_REWIND; 522d5ac70f0Sopenharmony_ci ctrl->u.rewind.frames = frames; 523d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 524d5ac70f0Sopenharmony_ci} 525d5ac70f0Sopenharmony_ci 526d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_shm_forwardable(snd_pcm_t *pcm ATTRIBUTE_UNUSED) 527d5ac70f0Sopenharmony_ci{ 528d5ac70f0Sopenharmony_ci return 0; /* FIX ME */ 529d5ac70f0Sopenharmony_ci} 530d5ac70f0Sopenharmony_ci 531d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_shm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames) 532d5ac70f0Sopenharmony_ci{ 533d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 534d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 535d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_FORWARD; 536d5ac70f0Sopenharmony_ci ctrl->u.forward.frames = frames; 537d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 538d5ac70f0Sopenharmony_ci} 539d5ac70f0Sopenharmony_ci 540d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_resume(snd_pcm_t *pcm) 541d5ac70f0Sopenharmony_ci{ 542d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 543d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 544d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_PCM_IOCTL_RESUME; 545d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 546d5ac70f0Sopenharmony_ci} 547d5ac70f0Sopenharmony_ci 548d5ac70f0Sopenharmony_cistatic snd_pcm_sframes_t snd_pcm_shm_mmap_commit(snd_pcm_t *pcm, 549d5ac70f0Sopenharmony_ci snd_pcm_uframes_t offset ATTRIBUTE_UNUSED, 550d5ac70f0Sopenharmony_ci snd_pcm_uframes_t size) 551d5ac70f0Sopenharmony_ci{ 552d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 553d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 554d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_MMAP_COMMIT; 555d5ac70f0Sopenharmony_ci ctrl->u.mmap_commit.offset = offset; 556d5ac70f0Sopenharmony_ci ctrl->u.mmap_commit.frames = size; 557d5ac70f0Sopenharmony_ci return snd_pcm_shm_action(pcm); 558d5ac70f0Sopenharmony_ci} 559d5ac70f0Sopenharmony_ci 560d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_poll_descriptor(snd_pcm_t *pcm) 561d5ac70f0Sopenharmony_ci{ 562d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 563d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 564d5ac70f0Sopenharmony_ci int fd, err; 565d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_POLL_DESCRIPTOR; 566d5ac70f0Sopenharmony_ci err = snd_pcm_shm_action_fd(pcm, &fd); 567d5ac70f0Sopenharmony_ci if (err < 0) 568d5ac70f0Sopenharmony_ci return err; 569d5ac70f0Sopenharmony_ci return fd; 570d5ac70f0Sopenharmony_ci} 571d5ac70f0Sopenharmony_ci 572d5ac70f0Sopenharmony_cistatic int snd_pcm_shm_close(snd_pcm_t *pcm) 573d5ac70f0Sopenharmony_ci{ 574d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = pcm->private_data; 575d5ac70f0Sopenharmony_ci volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; 576d5ac70f0Sopenharmony_ci int result; 577d5ac70f0Sopenharmony_ci ctrl->cmd = SND_PCM_IOCTL_CLOSE; 578d5ac70f0Sopenharmony_ci result = snd_pcm_shm_action(pcm); 579d5ac70f0Sopenharmony_ci shmdt((void *)ctrl); 580d5ac70f0Sopenharmony_ci close(shm->socket); 581d5ac70f0Sopenharmony_ci close(pcm->poll_fd); 582d5ac70f0Sopenharmony_ci free(shm); 583d5ac70f0Sopenharmony_ci return result; 584d5ac70f0Sopenharmony_ci} 585d5ac70f0Sopenharmony_ci 586d5ac70f0Sopenharmony_cistatic void snd_pcm_shm_dump(snd_pcm_t *pcm, snd_output_t *out) 587d5ac70f0Sopenharmony_ci{ 588d5ac70f0Sopenharmony_ci snd_output_printf(out, "Shm PCM\n"); 589d5ac70f0Sopenharmony_ci if (pcm->setup) { 590d5ac70f0Sopenharmony_ci snd_output_printf(out, "Its setup is:\n"); 591d5ac70f0Sopenharmony_ci snd_pcm_dump_setup(pcm, out); 592d5ac70f0Sopenharmony_ci } 593d5ac70f0Sopenharmony_ci} 594d5ac70f0Sopenharmony_ci 595d5ac70f0Sopenharmony_cistatic const snd_pcm_ops_t snd_pcm_shm_ops = { 596d5ac70f0Sopenharmony_ci .close = snd_pcm_shm_close, 597d5ac70f0Sopenharmony_ci .info = snd_pcm_shm_info, 598d5ac70f0Sopenharmony_ci .hw_refine = snd_pcm_shm_hw_refine, 599d5ac70f0Sopenharmony_ci .hw_params = snd_pcm_shm_hw_params, 600d5ac70f0Sopenharmony_ci .hw_free = snd_pcm_shm_hw_free, 601d5ac70f0Sopenharmony_ci .sw_params = snd_pcm_shm_sw_params, 602d5ac70f0Sopenharmony_ci .channel_info = snd_pcm_shm_channel_info, 603d5ac70f0Sopenharmony_ci .dump = snd_pcm_shm_dump, 604d5ac70f0Sopenharmony_ci .nonblock = snd_pcm_shm_nonblock, 605d5ac70f0Sopenharmony_ci .async = snd_pcm_shm_async, 606d5ac70f0Sopenharmony_ci .mmap = snd_pcm_shm_mmap, 607d5ac70f0Sopenharmony_ci .munmap = snd_pcm_shm_munmap, 608d5ac70f0Sopenharmony_ci}; 609d5ac70f0Sopenharmony_ci 610d5ac70f0Sopenharmony_cistatic const snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = { 611d5ac70f0Sopenharmony_ci .status = snd_pcm_shm_status, 612d5ac70f0Sopenharmony_ci .state = snd_pcm_shm_state, 613d5ac70f0Sopenharmony_ci .hwsync = snd_pcm_shm_hwsync, 614d5ac70f0Sopenharmony_ci .delay = snd_pcm_shm_delay, 615d5ac70f0Sopenharmony_ci .prepare = snd_pcm_shm_prepare, 616d5ac70f0Sopenharmony_ci .reset = snd_pcm_shm_reset, 617d5ac70f0Sopenharmony_ci .start = snd_pcm_shm_start, 618d5ac70f0Sopenharmony_ci .drop = snd_pcm_shm_drop, 619d5ac70f0Sopenharmony_ci .drain = snd_pcm_shm_drain, 620d5ac70f0Sopenharmony_ci .pause = snd_pcm_shm_pause, 621d5ac70f0Sopenharmony_ci .rewindable = snd_pcm_shm_rewindable, 622d5ac70f0Sopenharmony_ci .rewind = snd_pcm_shm_rewind, 623d5ac70f0Sopenharmony_ci .forwardable = snd_pcm_shm_forwardable, 624d5ac70f0Sopenharmony_ci .forward = snd_pcm_shm_forward, 625d5ac70f0Sopenharmony_ci .resume = snd_pcm_shm_resume, 626d5ac70f0Sopenharmony_ci .writei = snd_pcm_mmap_writei, 627d5ac70f0Sopenharmony_ci .writen = snd_pcm_mmap_writen, 628d5ac70f0Sopenharmony_ci .readi = snd_pcm_mmap_readi, 629d5ac70f0Sopenharmony_ci .readn = snd_pcm_mmap_readn, 630d5ac70f0Sopenharmony_ci .avail_update = snd_pcm_shm_avail_update, 631d5ac70f0Sopenharmony_ci .mmap_commit = snd_pcm_shm_mmap_commit, 632d5ac70f0Sopenharmony_ci .htimestamp = snd_pcm_shm_htimestamp, 633d5ac70f0Sopenharmony_ci}; 634d5ac70f0Sopenharmony_ci 635d5ac70f0Sopenharmony_cistatic int make_local_socket(const char *filename) 636d5ac70f0Sopenharmony_ci{ 637d5ac70f0Sopenharmony_ci size_t l = strlen(filename); 638d5ac70f0Sopenharmony_ci size_t size = offsetof(struct sockaddr_un, sun_path) + l; 639d5ac70f0Sopenharmony_ci struct sockaddr_un *addr = alloca(size); 640d5ac70f0Sopenharmony_ci int sock; 641d5ac70f0Sopenharmony_ci 642d5ac70f0Sopenharmony_ci sock = socket(PF_LOCAL, SOCK_STREAM, 0); 643d5ac70f0Sopenharmony_ci if (sock < 0) { 644d5ac70f0Sopenharmony_ci SYSERR("socket failed"); 645d5ac70f0Sopenharmony_ci return -errno; 646d5ac70f0Sopenharmony_ci } 647d5ac70f0Sopenharmony_ci 648d5ac70f0Sopenharmony_ci addr->sun_family = AF_LOCAL; 649d5ac70f0Sopenharmony_ci memcpy(addr->sun_path, filename, l); 650d5ac70f0Sopenharmony_ci 651d5ac70f0Sopenharmony_ci if (connect(sock, (struct sockaddr *) addr, size) < 0) { 652d5ac70f0Sopenharmony_ci SYSERR("connect failed"); 653d5ac70f0Sopenharmony_ci return -errno; 654d5ac70f0Sopenharmony_ci } 655d5ac70f0Sopenharmony_ci return sock; 656d5ac70f0Sopenharmony_ci} 657d5ac70f0Sopenharmony_ci 658d5ac70f0Sopenharmony_ci/** 659d5ac70f0Sopenharmony_ci * \brief Creates a new shared memory PCM 660d5ac70f0Sopenharmony_ci * \param pcmp Returns created PCM handle 661d5ac70f0Sopenharmony_ci * \param name Name of PCM 662d5ac70f0Sopenharmony_ci * \param sockname Unix socket name 663d5ac70f0Sopenharmony_ci * \param sname Server name 664d5ac70f0Sopenharmony_ci * \param stream PCM Stream 665d5ac70f0Sopenharmony_ci * \param mode PCM Mode 666d5ac70f0Sopenharmony_ci * \retval zero on success otherwise a negative error code 667d5ac70f0Sopenharmony_ci * \warning Using of this function might be dangerous in the sense 668d5ac70f0Sopenharmony_ci * of compatibility reasons. The prototype might be freely 669d5ac70f0Sopenharmony_ci * changed in future. 670d5ac70f0Sopenharmony_ci */ 671d5ac70f0Sopenharmony_ciint snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, 672d5ac70f0Sopenharmony_ci const char *sockname, const char *sname, 673d5ac70f0Sopenharmony_ci snd_pcm_stream_t stream, int mode) 674d5ac70f0Sopenharmony_ci{ 675d5ac70f0Sopenharmony_ci snd_pcm_t *pcm; 676d5ac70f0Sopenharmony_ci snd_pcm_shm_t *shm = NULL; 677d5ac70f0Sopenharmony_ci snd_client_open_request_t *req; 678d5ac70f0Sopenharmony_ci snd_client_open_answer_t ans; 679d5ac70f0Sopenharmony_ci size_t snamelen, reqlen; 680d5ac70f0Sopenharmony_ci int err; 681d5ac70f0Sopenharmony_ci int result; 682d5ac70f0Sopenharmony_ci snd_pcm_shm_ctrl_t *ctrl = NULL; 683d5ac70f0Sopenharmony_ci int sock = -1; 684d5ac70f0Sopenharmony_ci snamelen = strlen(sname); 685d5ac70f0Sopenharmony_ci if (snamelen > 255) 686d5ac70f0Sopenharmony_ci return -EINVAL; 687d5ac70f0Sopenharmony_ci 688d5ac70f0Sopenharmony_ci result = make_local_socket(sockname); 689d5ac70f0Sopenharmony_ci if (result < 0) { 690d5ac70f0Sopenharmony_ci SNDERR("server for socket %s is not running", sockname); 691d5ac70f0Sopenharmony_ci goto _err; 692d5ac70f0Sopenharmony_ci } 693d5ac70f0Sopenharmony_ci sock = result; 694d5ac70f0Sopenharmony_ci 695d5ac70f0Sopenharmony_ci reqlen = sizeof(*req) + snamelen; 696d5ac70f0Sopenharmony_ci req = alloca(reqlen); 697d5ac70f0Sopenharmony_ci memcpy(req->name, sname, snamelen); 698d5ac70f0Sopenharmony_ci req->dev_type = SND_DEV_TYPE_PCM; 699d5ac70f0Sopenharmony_ci req->transport_type = SND_TRANSPORT_TYPE_SHM; 700d5ac70f0Sopenharmony_ci req->stream = stream; 701d5ac70f0Sopenharmony_ci req->mode = mode; 702d5ac70f0Sopenharmony_ci req->namelen = snamelen; 703d5ac70f0Sopenharmony_ci err = write(sock, req, reqlen); 704d5ac70f0Sopenharmony_ci if (err < 0) { 705d5ac70f0Sopenharmony_ci SYSERR("write error"); 706d5ac70f0Sopenharmony_ci result = -errno; 707d5ac70f0Sopenharmony_ci goto _err; 708d5ac70f0Sopenharmony_ci } 709d5ac70f0Sopenharmony_ci if ((size_t) err != reqlen) { 710d5ac70f0Sopenharmony_ci SNDERR("write size error"); 711d5ac70f0Sopenharmony_ci result = -EINVAL; 712d5ac70f0Sopenharmony_ci goto _err; 713d5ac70f0Sopenharmony_ci } 714d5ac70f0Sopenharmony_ci err = read(sock, &ans, sizeof(ans)); 715d5ac70f0Sopenharmony_ci if (err < 0) { 716d5ac70f0Sopenharmony_ci SYSERR("read error"); 717d5ac70f0Sopenharmony_ci result = -errno; 718d5ac70f0Sopenharmony_ci goto _err; 719d5ac70f0Sopenharmony_ci } 720d5ac70f0Sopenharmony_ci if (err != sizeof(ans)) { 721d5ac70f0Sopenharmony_ci SNDERR("read size error"); 722d5ac70f0Sopenharmony_ci result = -EINVAL; 723d5ac70f0Sopenharmony_ci goto _err; 724d5ac70f0Sopenharmony_ci } 725d5ac70f0Sopenharmony_ci result = ans.result; 726d5ac70f0Sopenharmony_ci if (result < 0) 727d5ac70f0Sopenharmony_ci goto _err; 728d5ac70f0Sopenharmony_ci 729d5ac70f0Sopenharmony_ci ctrl = shmat(ans.cookie, 0, 0); 730d5ac70f0Sopenharmony_ci if (!ctrl) { 731d5ac70f0Sopenharmony_ci SYSERR("shmat error"); 732d5ac70f0Sopenharmony_ci result = -errno; 733d5ac70f0Sopenharmony_ci goto _err; 734d5ac70f0Sopenharmony_ci } 735d5ac70f0Sopenharmony_ci 736d5ac70f0Sopenharmony_ci shm = calloc(1, sizeof(snd_pcm_shm_t)); 737d5ac70f0Sopenharmony_ci if (!shm) { 738d5ac70f0Sopenharmony_ci result = -ENOMEM; 739d5ac70f0Sopenharmony_ci goto _err; 740d5ac70f0Sopenharmony_ci } 741d5ac70f0Sopenharmony_ci 742d5ac70f0Sopenharmony_ci shm->socket = sock; 743d5ac70f0Sopenharmony_ci shm->ctrl = ctrl; 744d5ac70f0Sopenharmony_ci 745d5ac70f0Sopenharmony_ci err = snd_pcm_new(&pcm, SND_PCM_TYPE_SHM, name, stream, mode); 746d5ac70f0Sopenharmony_ci if (err < 0) { 747d5ac70f0Sopenharmony_ci result = err; 748d5ac70f0Sopenharmony_ci goto _err; 749d5ac70f0Sopenharmony_ci } 750d5ac70f0Sopenharmony_ci pcm->mmap_rw = 1; 751d5ac70f0Sopenharmony_ci pcm->ops = &snd_pcm_shm_ops; 752d5ac70f0Sopenharmony_ci pcm->fast_ops = &snd_pcm_shm_fast_ops; 753d5ac70f0Sopenharmony_ci pcm->private_data = shm; 754d5ac70f0Sopenharmony_ci err = snd_pcm_shm_poll_descriptor(pcm); 755d5ac70f0Sopenharmony_ci if (err < 0) { 756d5ac70f0Sopenharmony_ci snd_pcm_close(pcm); 757d5ac70f0Sopenharmony_ci return err; 758d5ac70f0Sopenharmony_ci } 759d5ac70f0Sopenharmony_ci pcm->poll_fd = err; 760d5ac70f0Sopenharmony_ci pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN; 761d5ac70f0Sopenharmony_ci snd_pcm_set_hw_ptr(pcm, &ctrl->hw.ptr, -1, 0); 762d5ac70f0Sopenharmony_ci snd_pcm_set_appl_ptr(pcm, &ctrl->appl.ptr, -1, 0); 763d5ac70f0Sopenharmony_ci *pcmp = pcm; 764d5ac70f0Sopenharmony_ci return 0; 765d5ac70f0Sopenharmony_ci 766d5ac70f0Sopenharmony_ci _err: 767d5ac70f0Sopenharmony_ci close(sock); 768d5ac70f0Sopenharmony_ci if (ctrl) 769d5ac70f0Sopenharmony_ci shmdt(ctrl); 770d5ac70f0Sopenharmony_ci free(shm); 771d5ac70f0Sopenharmony_ci return result; 772d5ac70f0Sopenharmony_ci} 773d5ac70f0Sopenharmony_ci 774d5ac70f0Sopenharmony_ci/*! \page pcm_plugins 775d5ac70f0Sopenharmony_ci 776d5ac70f0Sopenharmony_ci\section pcm_plugins_shm Plugin: shm 777d5ac70f0Sopenharmony_ci 778d5ac70f0Sopenharmony_ciThis plugin communicates with aserver via shared memory. It is a raw 779d5ac70f0Sopenharmony_cicommunication without any conversions, but it can be expected worse 780d5ac70f0Sopenharmony_ciperformance. 781d5ac70f0Sopenharmony_ci 782d5ac70f0Sopenharmony_ci\code 783d5ac70f0Sopenharmony_cipcm.name { 784d5ac70f0Sopenharmony_ci type shm # Shared memory PCM 785d5ac70f0Sopenharmony_ci server STR # Server name 786d5ac70f0Sopenharmony_ci pcm STR # PCM name 787d5ac70f0Sopenharmony_ci} 788d5ac70f0Sopenharmony_ci\endcode 789d5ac70f0Sopenharmony_ci 790d5ac70f0Sopenharmony_ci\subsection pcm_plugins_shm_funcref Function reference 791d5ac70f0Sopenharmony_ci 792d5ac70f0Sopenharmony_ci<UL> 793d5ac70f0Sopenharmony_ci <LI>snd_pcm_shm_open() 794d5ac70f0Sopenharmony_ci <LI>_snd_pcm_shm_open() 795d5ac70f0Sopenharmony_ci</UL> 796d5ac70f0Sopenharmony_ci 797d5ac70f0Sopenharmony_ci*/ 798d5ac70f0Sopenharmony_ci 799d5ac70f0Sopenharmony_ci/** 800d5ac70f0Sopenharmony_ci * \brief Creates a new shm PCM 801d5ac70f0Sopenharmony_ci * \param pcmp Returns created PCM handle 802d5ac70f0Sopenharmony_ci * \param name Name of PCM 803d5ac70f0Sopenharmony_ci * \param root Root configuration node 804d5ac70f0Sopenharmony_ci * \param conf Configuration node with hw PCM description 805d5ac70f0Sopenharmony_ci * \param stream PCM Stream 806d5ac70f0Sopenharmony_ci * \param mode PCM Mode 807d5ac70f0Sopenharmony_ci * \warning Using of this function might be dangerous in the sense 808d5ac70f0Sopenharmony_ci * of compatibility reasons. The prototype might be freely 809d5ac70f0Sopenharmony_ci * changed in future. 810d5ac70f0Sopenharmony_ci */ 811d5ac70f0Sopenharmony_ciint _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name, 812d5ac70f0Sopenharmony_ci snd_config_t *root, snd_config_t *conf, 813d5ac70f0Sopenharmony_ci snd_pcm_stream_t stream, int mode) 814d5ac70f0Sopenharmony_ci{ 815d5ac70f0Sopenharmony_ci snd_config_iterator_t i, next; 816d5ac70f0Sopenharmony_ci const char *server = NULL; 817d5ac70f0Sopenharmony_ci const char *pcm_name = NULL; 818d5ac70f0Sopenharmony_ci snd_config_t *sconfig; 819d5ac70f0Sopenharmony_ci const char *sockname = NULL; 820d5ac70f0Sopenharmony_ci long port = -1; 821d5ac70f0Sopenharmony_ci int err; 822d5ac70f0Sopenharmony_ci 823d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, conf) { 824d5ac70f0Sopenharmony_ci snd_config_t *n = snd_config_iterator_entry(i); 825d5ac70f0Sopenharmony_ci const char *id; 826d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 827d5ac70f0Sopenharmony_ci continue; 828d5ac70f0Sopenharmony_ci if (snd_pcm_conf_generic_id(id)) 829d5ac70f0Sopenharmony_ci continue; 830d5ac70f0Sopenharmony_ci if (strcmp(id, "server") == 0) { 831d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &server); 832d5ac70f0Sopenharmony_ci if (err < 0) { 833d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 834d5ac70f0Sopenharmony_ci return -EINVAL; 835d5ac70f0Sopenharmony_ci } 836d5ac70f0Sopenharmony_ci continue; 837d5ac70f0Sopenharmony_ci } 838d5ac70f0Sopenharmony_ci if (strcmp(id, "pcm") == 0) { 839d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &pcm_name); 840d5ac70f0Sopenharmony_ci if (err < 0) { 841d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 842d5ac70f0Sopenharmony_ci return -EINVAL; 843d5ac70f0Sopenharmony_ci } 844d5ac70f0Sopenharmony_ci continue; 845d5ac70f0Sopenharmony_ci } 846d5ac70f0Sopenharmony_ci SNDERR("Unknown field %s", id); 847d5ac70f0Sopenharmony_ci return -EINVAL; 848d5ac70f0Sopenharmony_ci } 849d5ac70f0Sopenharmony_ci if (!pcm_name) { 850d5ac70f0Sopenharmony_ci SNDERR("pcm is not defined"); 851d5ac70f0Sopenharmony_ci return -EINVAL; 852d5ac70f0Sopenharmony_ci } 853d5ac70f0Sopenharmony_ci if (!server) { 854d5ac70f0Sopenharmony_ci SNDERR("server is not defined"); 855d5ac70f0Sopenharmony_ci return -EINVAL; 856d5ac70f0Sopenharmony_ci } 857d5ac70f0Sopenharmony_ci err = snd_config_search_definition(root, "server", server, &sconfig); 858d5ac70f0Sopenharmony_ci if (err < 0) { 859d5ac70f0Sopenharmony_ci SNDERR("Unknown server %s", server); 860d5ac70f0Sopenharmony_ci return -EINVAL; 861d5ac70f0Sopenharmony_ci } 862d5ac70f0Sopenharmony_ci if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) { 863d5ac70f0Sopenharmony_ci SNDERR("Invalid type for server %s definition", server); 864d5ac70f0Sopenharmony_ci goto _err; 865d5ac70f0Sopenharmony_ci } 866d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, sconfig) { 867d5ac70f0Sopenharmony_ci snd_config_t *n = snd_config_iterator_entry(i); 868d5ac70f0Sopenharmony_ci const char *id; 869d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 870d5ac70f0Sopenharmony_ci continue; 871d5ac70f0Sopenharmony_ci if (strcmp(id, "comment") == 0) 872d5ac70f0Sopenharmony_ci continue; 873d5ac70f0Sopenharmony_ci if (strcmp(id, "host") == 0) 874d5ac70f0Sopenharmony_ci continue; 875d5ac70f0Sopenharmony_ci if (strcmp(id, "socket") == 0) { 876d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &sockname); 877d5ac70f0Sopenharmony_ci if (err < 0) { 878d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 879d5ac70f0Sopenharmony_ci goto _err; 880d5ac70f0Sopenharmony_ci } 881d5ac70f0Sopenharmony_ci continue; 882d5ac70f0Sopenharmony_ci } 883d5ac70f0Sopenharmony_ci if (strcmp(id, "port") == 0) { 884d5ac70f0Sopenharmony_ci err = snd_config_get_integer(n, &port); 885d5ac70f0Sopenharmony_ci if (err < 0) { 886d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 887d5ac70f0Sopenharmony_ci goto _err; 888d5ac70f0Sopenharmony_ci } 889d5ac70f0Sopenharmony_ci continue; 890d5ac70f0Sopenharmony_ci } 891d5ac70f0Sopenharmony_ci SNDERR("Unknown field %s", id); 892d5ac70f0Sopenharmony_ci _err: 893d5ac70f0Sopenharmony_ci err = -EINVAL; 894d5ac70f0Sopenharmony_ci goto __error; 895d5ac70f0Sopenharmony_ci } 896d5ac70f0Sopenharmony_ci 897d5ac70f0Sopenharmony_ci if (!sockname) { 898d5ac70f0Sopenharmony_ci SNDERR("socket is not defined"); 899d5ac70f0Sopenharmony_ci goto _err; 900d5ac70f0Sopenharmony_ci } 901d5ac70f0Sopenharmony_ci err = snd_pcm_shm_open(pcmp, name, sockname, pcm_name, stream, mode); 902d5ac70f0Sopenharmony_ci __error: 903d5ac70f0Sopenharmony_ci snd_config_delete(sconfig); 904d5ac70f0Sopenharmony_ci return err; 905d5ac70f0Sopenharmony_ci} 906d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 907d5ac70f0Sopenharmony_ciSND_DLSYM_BUILD_VERSION(_snd_pcm_shm_open, SND_PCM_DLSYM_VERSION); 908d5ac70f0Sopenharmony_ci#endif 909