1d5ac70f0Sopenharmony_ci/* 2d5ac70f0Sopenharmony_ci * Control - SHM Client 3d5ac70f0Sopenharmony_ci * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> 4d5ac70f0Sopenharmony_ci * 5d5ac70f0Sopenharmony_ci * 6d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 7d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 8d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 9d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 10d5ac70f0Sopenharmony_ci * 11d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 12d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 15d5ac70f0Sopenharmony_ci * 16d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 18d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19d5ac70f0Sopenharmony_ci * 20d5ac70f0Sopenharmony_ci */ 21d5ac70f0Sopenharmony_ci 22d5ac70f0Sopenharmony_ci#include <stdio.h> 23d5ac70f0Sopenharmony_ci#include <stdlib.h> 24d5ac70f0Sopenharmony_ci#include <stddef.h> 25d5ac70f0Sopenharmony_ci#include <unistd.h> 26d5ac70f0Sopenharmony_ci#include <string.h> 27d5ac70f0Sopenharmony_ci#include <fcntl.h> 28d5ac70f0Sopenharmony_ci#include <sys/shm.h> 29d5ac70f0Sopenharmony_ci#include <sys/socket.h> 30d5ac70f0Sopenharmony_ci#include <poll.h> 31d5ac70f0Sopenharmony_ci#include <sys/un.h> 32d5ac70f0Sopenharmony_ci#include <sys/uio.h> 33d5ac70f0Sopenharmony_ci#include <sys/mman.h> 34d5ac70f0Sopenharmony_ci#include <netinet/in.h> 35d5ac70f0Sopenharmony_ci#include <netdb.h> 36d5ac70f0Sopenharmony_ci#include "aserver.h" 37d5ac70f0Sopenharmony_ci 38d5ac70f0Sopenharmony_ci#ifndef PIC 39d5ac70f0Sopenharmony_ci/* entry for static linking */ 40d5ac70f0Sopenharmony_ciconst char *_snd_module_control_shm = ""; 41d5ac70f0Sopenharmony_ci#endif 42d5ac70f0Sopenharmony_ci 43d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 44d5ac70f0Sopenharmony_citypedef struct { 45d5ac70f0Sopenharmony_ci int socket; 46d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl; 47d5ac70f0Sopenharmony_ci} snd_ctl_shm_t; 48d5ac70f0Sopenharmony_ci#endif 49d5ac70f0Sopenharmony_ci 50d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_action(snd_ctl_t *ctl) 51d5ac70f0Sopenharmony_ci{ 52d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 53d5ac70f0Sopenharmony_ci int err; 54d5ac70f0Sopenharmony_ci char buf[1] = {0}; 55d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 56d5ac70f0Sopenharmony_ci err = write(shm->socket, buf, 1); 57d5ac70f0Sopenharmony_ci if (err != 1) 58d5ac70f0Sopenharmony_ci return -EBADFD; 59d5ac70f0Sopenharmony_ci err = read(shm->socket, buf, 1); 60d5ac70f0Sopenharmony_ci if (err != 1) 61d5ac70f0Sopenharmony_ci return -EBADFD; 62d5ac70f0Sopenharmony_ci if (ctrl->cmd) { 63d5ac70f0Sopenharmony_ci SNDERR("Server has not done the cmd"); 64d5ac70f0Sopenharmony_ci return -EBADFD; 65d5ac70f0Sopenharmony_ci } 66d5ac70f0Sopenharmony_ci return ctrl->result; 67d5ac70f0Sopenharmony_ci} 68d5ac70f0Sopenharmony_ci 69d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_action_fd(snd_ctl_t *ctl, int *fd) 70d5ac70f0Sopenharmony_ci{ 71d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 72d5ac70f0Sopenharmony_ci int err; 73d5ac70f0Sopenharmony_ci char buf[1]; 74d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 75d5ac70f0Sopenharmony_ci err = write(shm->socket, buf, 1); 76d5ac70f0Sopenharmony_ci if (err != 1) 77d5ac70f0Sopenharmony_ci return -EBADFD; 78d5ac70f0Sopenharmony_ci err = snd_receive_fd(shm->socket, buf, 1, fd); 79d5ac70f0Sopenharmony_ci if (err != 1) 80d5ac70f0Sopenharmony_ci return -EBADFD; 81d5ac70f0Sopenharmony_ci if (ctrl->cmd) { 82d5ac70f0Sopenharmony_ci SNDERR("Server has not done the cmd"); 83d5ac70f0Sopenharmony_ci return -EBADFD; 84d5ac70f0Sopenharmony_ci } 85d5ac70f0Sopenharmony_ci return ctrl->result; 86d5ac70f0Sopenharmony_ci} 87d5ac70f0Sopenharmony_ci 88d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_close(snd_ctl_t *ctl) 89d5ac70f0Sopenharmony_ci{ 90d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 91d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 92d5ac70f0Sopenharmony_ci int result; 93d5ac70f0Sopenharmony_ci ctrl->cmd = SND_CTL_IOCTL_CLOSE; 94d5ac70f0Sopenharmony_ci result = snd_ctl_shm_action(ctl); 95d5ac70f0Sopenharmony_ci shmdt((void *)ctrl); 96d5ac70f0Sopenharmony_ci close(shm->socket); 97d5ac70f0Sopenharmony_ci free(shm); 98d5ac70f0Sopenharmony_ci return result; 99d5ac70f0Sopenharmony_ci} 100d5ac70f0Sopenharmony_ci 101d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_nonblock(snd_ctl_t *handle ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) 102d5ac70f0Sopenharmony_ci{ 103d5ac70f0Sopenharmony_ci return 0; 104d5ac70f0Sopenharmony_ci} 105d5ac70f0Sopenharmony_ci 106d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_async(snd_ctl_t *ctl, int sig, pid_t pid) 107d5ac70f0Sopenharmony_ci{ 108d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 109d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 110d5ac70f0Sopenharmony_ci ctrl->cmd = SND_CTL_IOCTL_ASYNC; 111d5ac70f0Sopenharmony_ci ctrl->u.async.sig = sig; 112d5ac70f0Sopenharmony_ci if (pid == 0) 113d5ac70f0Sopenharmony_ci pid = getpid(); 114d5ac70f0Sopenharmony_ci ctrl->u.async.pid = pid; 115d5ac70f0Sopenharmony_ci return snd_ctl_shm_action(ctl); 116d5ac70f0Sopenharmony_ci} 117d5ac70f0Sopenharmony_ci 118d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_poll_descriptor(snd_ctl_t *ctl) 119d5ac70f0Sopenharmony_ci{ 120d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 121d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 122d5ac70f0Sopenharmony_ci int fd, err; 123d5ac70f0Sopenharmony_ci ctrl->cmd = SND_CTL_IOCTL_POLL_DESCRIPTOR; 124d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action_fd(ctl, &fd); 125d5ac70f0Sopenharmony_ci if (err < 0) 126d5ac70f0Sopenharmony_ci return err; 127d5ac70f0Sopenharmony_ci return fd; 128d5ac70f0Sopenharmony_ci} 129d5ac70f0Sopenharmony_ci 130d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_subscribe_events(snd_ctl_t *ctl, int subscribe) 131d5ac70f0Sopenharmony_ci{ 132d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 133d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 134d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS; 135d5ac70f0Sopenharmony_ci ctrl->u.subscribe_events = subscribe; 136d5ac70f0Sopenharmony_ci return snd_ctl_shm_action(ctl); 137d5ac70f0Sopenharmony_ci} 138d5ac70f0Sopenharmony_ci 139d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) 140d5ac70f0Sopenharmony_ci{ 141d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 142d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 143d5ac70f0Sopenharmony_ci int err; 144d5ac70f0Sopenharmony_ci// ctrl->u.card_info = *info; 145d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_CARD_INFO; 146d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 147d5ac70f0Sopenharmony_ci if (err < 0) 148d5ac70f0Sopenharmony_ci return err; 149d5ac70f0Sopenharmony_ci *info = ctrl->u.card_info; 150d5ac70f0Sopenharmony_ci return err; 151d5ac70f0Sopenharmony_ci} 152d5ac70f0Sopenharmony_ci 153d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list) 154d5ac70f0Sopenharmony_ci{ 155d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 156d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 157d5ac70f0Sopenharmony_ci size_t maxsize = CTL_SHM_DATA_MAXLEN; 158d5ac70f0Sopenharmony_ci size_t bytes = list->space * sizeof(*list->pids); 159d5ac70f0Sopenharmony_ci int err; 160d5ac70f0Sopenharmony_ci snd_ctl_elem_id_t *pids = list->pids; 161d5ac70f0Sopenharmony_ci if (bytes > maxsize) 162d5ac70f0Sopenharmony_ci return -EINVAL; 163d5ac70f0Sopenharmony_ci ctrl->u.element_list = *list; 164d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_LIST; 165d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 166d5ac70f0Sopenharmony_ci if (err < 0) 167d5ac70f0Sopenharmony_ci return err; 168d5ac70f0Sopenharmony_ci *list = ctrl->u.element_list; 169d5ac70f0Sopenharmony_ci list->pids = pids; 170d5ac70f0Sopenharmony_ci bytes = list->used * sizeof(*list->pids); 171d5ac70f0Sopenharmony_ci memcpy(pids, (void *)ctrl->data, bytes); 172d5ac70f0Sopenharmony_ci return err; 173d5ac70f0Sopenharmony_ci} 174d5ac70f0Sopenharmony_ci 175d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info) 176d5ac70f0Sopenharmony_ci{ 177d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 178d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 179d5ac70f0Sopenharmony_ci int err; 180d5ac70f0Sopenharmony_ci ctrl->u.element_info = *info; 181d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_INFO; 182d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 183d5ac70f0Sopenharmony_ci if (err < 0) 184d5ac70f0Sopenharmony_ci return err; 185d5ac70f0Sopenharmony_ci *info = ctrl->u.element_info; 186d5ac70f0Sopenharmony_ci return err; 187d5ac70f0Sopenharmony_ci} 188d5ac70f0Sopenharmony_ci 189d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *control) 190d5ac70f0Sopenharmony_ci{ 191d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 192d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 193d5ac70f0Sopenharmony_ci int err; 194d5ac70f0Sopenharmony_ci ctrl->u.element_read = *control; 195d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_READ; 196d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 197d5ac70f0Sopenharmony_ci if (err < 0) 198d5ac70f0Sopenharmony_ci return err; 199d5ac70f0Sopenharmony_ci *control = ctrl->u.element_read; 200d5ac70f0Sopenharmony_ci return err; 201d5ac70f0Sopenharmony_ci} 202d5ac70f0Sopenharmony_ci 203d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *control) 204d5ac70f0Sopenharmony_ci{ 205d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 206d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 207d5ac70f0Sopenharmony_ci int err; 208d5ac70f0Sopenharmony_ci ctrl->u.element_write = *control; 209d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_WRITE; 210d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 211d5ac70f0Sopenharmony_ci if (err < 0) 212d5ac70f0Sopenharmony_ci return err; 213d5ac70f0Sopenharmony_ci *control = ctrl->u.element_write; 214d5ac70f0Sopenharmony_ci return err; 215d5ac70f0Sopenharmony_ci} 216d5ac70f0Sopenharmony_ci 217d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_elem_lock(snd_ctl_t *ctl, snd_ctl_elem_id_t *id) 218d5ac70f0Sopenharmony_ci{ 219d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 220d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 221d5ac70f0Sopenharmony_ci int err; 222d5ac70f0Sopenharmony_ci ctrl->u.element_lock = *id; 223d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_LOCK; 224d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 225d5ac70f0Sopenharmony_ci if (err < 0) 226d5ac70f0Sopenharmony_ci return err; 227d5ac70f0Sopenharmony_ci *id = ctrl->u.element_lock; 228d5ac70f0Sopenharmony_ci return err; 229d5ac70f0Sopenharmony_ci} 230d5ac70f0Sopenharmony_ci 231d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_elem_unlock(snd_ctl_t *ctl, snd_ctl_elem_id_t *id) 232d5ac70f0Sopenharmony_ci{ 233d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 234d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 235d5ac70f0Sopenharmony_ci int err; 236d5ac70f0Sopenharmony_ci ctrl->u.element_unlock = *id; 237d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_UNLOCK; 238d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 239d5ac70f0Sopenharmony_ci if (err < 0) 240d5ac70f0Sopenharmony_ci return err; 241d5ac70f0Sopenharmony_ci *id = ctrl->u.element_unlock; 242d5ac70f0Sopenharmony_ci return err; 243d5ac70f0Sopenharmony_ci} 244d5ac70f0Sopenharmony_ci 245d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_hwdep_next_device(snd_ctl_t *ctl, int * device) 246d5ac70f0Sopenharmony_ci{ 247d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 248d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 249d5ac70f0Sopenharmony_ci int err; 250d5ac70f0Sopenharmony_ci ctrl->u.device = *device; 251d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE; 252d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 253d5ac70f0Sopenharmony_ci if (err < 0) 254d5ac70f0Sopenharmony_ci return err; 255d5ac70f0Sopenharmony_ci *device = ctrl->u.device; 256d5ac70f0Sopenharmony_ci return err; 257d5ac70f0Sopenharmony_ci} 258d5ac70f0Sopenharmony_ci 259d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info) 260d5ac70f0Sopenharmony_ci{ 261d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 262d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 263d5ac70f0Sopenharmony_ci int err; 264d5ac70f0Sopenharmony_ci ctrl->u.hwdep_info = *info; 265d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_HWDEP_INFO; 266d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 267d5ac70f0Sopenharmony_ci if (err < 0) 268d5ac70f0Sopenharmony_ci return err; 269d5ac70f0Sopenharmony_ci *info = ctrl->u.hwdep_info; 270d5ac70f0Sopenharmony_ci return err; 271d5ac70f0Sopenharmony_ci} 272d5ac70f0Sopenharmony_ci 273d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_pcm_next_device(snd_ctl_t *ctl, int * device) 274d5ac70f0Sopenharmony_ci{ 275d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 276d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 277d5ac70f0Sopenharmony_ci int err; 278d5ac70f0Sopenharmony_ci ctrl->u.device = *device; 279d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE; 280d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 281d5ac70f0Sopenharmony_ci if (err < 0) 282d5ac70f0Sopenharmony_ci return err; 283d5ac70f0Sopenharmony_ci *device = ctrl->u.device; 284d5ac70f0Sopenharmony_ci return err; 285d5ac70f0Sopenharmony_ci} 286d5ac70f0Sopenharmony_ci 287d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info) 288d5ac70f0Sopenharmony_ci{ 289d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 290d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 291d5ac70f0Sopenharmony_ci int err; 292d5ac70f0Sopenharmony_ci ctrl->u.pcm_info = *info; 293d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_PCM_INFO; 294d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 295d5ac70f0Sopenharmony_ci if (err < 0) 296d5ac70f0Sopenharmony_ci return err; 297d5ac70f0Sopenharmony_ci *info = ctrl->u.pcm_info; 298d5ac70f0Sopenharmony_ci return err; 299d5ac70f0Sopenharmony_ci} 300d5ac70f0Sopenharmony_ci 301d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev) 302d5ac70f0Sopenharmony_ci{ 303d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 304d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 305d5ac70f0Sopenharmony_ci ctrl->u.pcm_prefer_subdevice = subdev; 306d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE; 307d5ac70f0Sopenharmony_ci return snd_ctl_shm_action(ctl); 308d5ac70f0Sopenharmony_ci} 309d5ac70f0Sopenharmony_ci 310d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_rawmidi_next_device(snd_ctl_t *ctl, int * device) 311d5ac70f0Sopenharmony_ci{ 312d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 313d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 314d5ac70f0Sopenharmony_ci int err; 315d5ac70f0Sopenharmony_ci ctrl->u.device = *device; 316d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE; 317d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 318d5ac70f0Sopenharmony_ci if (err < 0) 319d5ac70f0Sopenharmony_ci return err; 320d5ac70f0Sopenharmony_ci *device = ctrl->u.device; 321d5ac70f0Sopenharmony_ci return err; 322d5ac70f0Sopenharmony_ci} 323d5ac70f0Sopenharmony_ci 324d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info) 325d5ac70f0Sopenharmony_ci{ 326d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 327d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 328d5ac70f0Sopenharmony_ci int err; 329d5ac70f0Sopenharmony_ci ctrl->u.rawmidi_info = *info; 330d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_RAWMIDI_INFO; 331d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 332d5ac70f0Sopenharmony_ci if (err < 0) 333d5ac70f0Sopenharmony_ci return err; 334d5ac70f0Sopenharmony_ci *info = ctrl->u.rawmidi_info; 335d5ac70f0Sopenharmony_ci return err; 336d5ac70f0Sopenharmony_ci} 337d5ac70f0Sopenharmony_ci 338d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev) 339d5ac70f0Sopenharmony_ci{ 340d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 341d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 342d5ac70f0Sopenharmony_ci ctrl->u.rawmidi_prefer_subdevice = subdev; 343d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE; 344d5ac70f0Sopenharmony_ci return snd_ctl_shm_action(ctl); 345d5ac70f0Sopenharmony_ci} 346d5ac70f0Sopenharmony_ci 347d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_set_power_state(snd_ctl_t *ctl, unsigned int state) 348d5ac70f0Sopenharmony_ci{ 349d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 350d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 351d5ac70f0Sopenharmony_ci ctrl->u.power_state = state; 352d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_POWER; 353d5ac70f0Sopenharmony_ci return snd_ctl_shm_action(ctl); 354d5ac70f0Sopenharmony_ci} 355d5ac70f0Sopenharmony_ci 356d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_get_power_state(snd_ctl_t *ctl, unsigned int *state) 357d5ac70f0Sopenharmony_ci{ 358d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = ctl->private_data; 359d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 360d5ac70f0Sopenharmony_ci int err; 361d5ac70f0Sopenharmony_ci ctrl->cmd = SNDRV_CTL_IOCTL_POWER_STATE; 362d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 363d5ac70f0Sopenharmony_ci if (err < 0) 364d5ac70f0Sopenharmony_ci return err; 365d5ac70f0Sopenharmony_ci *state = ctrl->u.power_state; 366d5ac70f0Sopenharmony_ci return err; 367d5ac70f0Sopenharmony_ci} 368d5ac70f0Sopenharmony_ci 369d5ac70f0Sopenharmony_cistatic int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event) 370d5ac70f0Sopenharmony_ci{ 371d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm; 372d5ac70f0Sopenharmony_ci volatile snd_ctl_shm_ctrl_t *ctrl; 373d5ac70f0Sopenharmony_ci int err; 374d5ac70f0Sopenharmony_ci err = snd_ctl_wait(ctl, -1); 375d5ac70f0Sopenharmony_ci if (err < 0) 376d5ac70f0Sopenharmony_ci return 0; 377d5ac70f0Sopenharmony_ci shm = ctl->private_data; 378d5ac70f0Sopenharmony_ci ctrl = shm->ctrl; 379d5ac70f0Sopenharmony_ci ctrl->u.read = *event; 380d5ac70f0Sopenharmony_ci ctrl->cmd = SND_CTL_IOCTL_READ; 381d5ac70f0Sopenharmony_ci err = snd_ctl_shm_action(ctl); 382d5ac70f0Sopenharmony_ci if (err < 0) 383d5ac70f0Sopenharmony_ci return err; 384d5ac70f0Sopenharmony_ci *event = ctrl->u.read; 385d5ac70f0Sopenharmony_ci return err; 386d5ac70f0Sopenharmony_ci} 387d5ac70f0Sopenharmony_ci 388d5ac70f0Sopenharmony_cistatic const snd_ctl_ops_t snd_ctl_shm_ops = { 389d5ac70f0Sopenharmony_ci .close = snd_ctl_shm_close, 390d5ac70f0Sopenharmony_ci .nonblock = snd_ctl_shm_nonblock, 391d5ac70f0Sopenharmony_ci .async = snd_ctl_shm_async, 392d5ac70f0Sopenharmony_ci .subscribe_events = snd_ctl_shm_subscribe_events, 393d5ac70f0Sopenharmony_ci .card_info = snd_ctl_shm_card_info, 394d5ac70f0Sopenharmony_ci .element_list = snd_ctl_shm_elem_list, 395d5ac70f0Sopenharmony_ci .element_info = snd_ctl_shm_elem_info, 396d5ac70f0Sopenharmony_ci .element_read = snd_ctl_shm_elem_read, 397d5ac70f0Sopenharmony_ci .element_write = snd_ctl_shm_elem_write, 398d5ac70f0Sopenharmony_ci .element_lock = snd_ctl_shm_elem_lock, 399d5ac70f0Sopenharmony_ci .element_unlock = snd_ctl_shm_elem_unlock, 400d5ac70f0Sopenharmony_ci .hwdep_next_device = snd_ctl_shm_hwdep_next_device, 401d5ac70f0Sopenharmony_ci .hwdep_info = snd_ctl_shm_hwdep_info, 402d5ac70f0Sopenharmony_ci .pcm_next_device = snd_ctl_shm_pcm_next_device, 403d5ac70f0Sopenharmony_ci .pcm_info = snd_ctl_shm_pcm_info, 404d5ac70f0Sopenharmony_ci .pcm_prefer_subdevice = snd_ctl_shm_pcm_prefer_subdevice, 405d5ac70f0Sopenharmony_ci .rawmidi_next_device = snd_ctl_shm_rawmidi_next_device, 406d5ac70f0Sopenharmony_ci .rawmidi_info = snd_ctl_shm_rawmidi_info, 407d5ac70f0Sopenharmony_ci .rawmidi_prefer_subdevice = snd_ctl_shm_rawmidi_prefer_subdevice, 408d5ac70f0Sopenharmony_ci .set_power_state = snd_ctl_shm_set_power_state, 409d5ac70f0Sopenharmony_ci .get_power_state = snd_ctl_shm_get_power_state, 410d5ac70f0Sopenharmony_ci .read = snd_ctl_shm_read, 411d5ac70f0Sopenharmony_ci}; 412d5ac70f0Sopenharmony_ci 413d5ac70f0Sopenharmony_cistatic int make_local_socket(const char *filename) 414d5ac70f0Sopenharmony_ci{ 415d5ac70f0Sopenharmony_ci size_t l = strlen(filename); 416d5ac70f0Sopenharmony_ci size_t size = offsetof(struct sockaddr_un, sun_path) + l; 417d5ac70f0Sopenharmony_ci struct sockaddr_un *addr = alloca(size); 418d5ac70f0Sopenharmony_ci int sock; 419d5ac70f0Sopenharmony_ci 420d5ac70f0Sopenharmony_ci sock = socket(PF_LOCAL, SOCK_STREAM, 0); 421d5ac70f0Sopenharmony_ci if (sock < 0) 422d5ac70f0Sopenharmony_ci return -errno; 423d5ac70f0Sopenharmony_ci 424d5ac70f0Sopenharmony_ci addr->sun_family = AF_LOCAL; 425d5ac70f0Sopenharmony_ci memcpy(addr->sun_path, filename, l); 426d5ac70f0Sopenharmony_ci 427d5ac70f0Sopenharmony_ci if (connect(sock, (struct sockaddr *) addr, size) < 0) { 428d5ac70f0Sopenharmony_ci close(sock); 429d5ac70f0Sopenharmony_ci return -errno; 430d5ac70f0Sopenharmony_ci } 431d5ac70f0Sopenharmony_ci return sock; 432d5ac70f0Sopenharmony_ci} 433d5ac70f0Sopenharmony_ci 434d5ac70f0Sopenharmony_ciint snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname, const char *sname, int mode) 435d5ac70f0Sopenharmony_ci{ 436d5ac70f0Sopenharmony_ci snd_ctl_t *ctl; 437d5ac70f0Sopenharmony_ci snd_ctl_shm_t *shm = NULL; 438d5ac70f0Sopenharmony_ci snd_client_open_request_t *req; 439d5ac70f0Sopenharmony_ci snd_client_open_answer_t ans; 440d5ac70f0Sopenharmony_ci size_t snamelen, reqlen; 441d5ac70f0Sopenharmony_ci int err; 442d5ac70f0Sopenharmony_ci int result; 443d5ac70f0Sopenharmony_ci int sock = -1; 444d5ac70f0Sopenharmony_ci snd_ctl_shm_ctrl_t *ctrl = NULL; 445d5ac70f0Sopenharmony_ci snamelen = strlen(sname); 446d5ac70f0Sopenharmony_ci if (snamelen > 255) 447d5ac70f0Sopenharmony_ci return -EINVAL; 448d5ac70f0Sopenharmony_ci 449d5ac70f0Sopenharmony_ci result = make_local_socket(sockname); 450d5ac70f0Sopenharmony_ci if (result < 0) { 451d5ac70f0Sopenharmony_ci SNDERR("server for socket %s is not running", sockname); 452d5ac70f0Sopenharmony_ci goto _err; 453d5ac70f0Sopenharmony_ci } 454d5ac70f0Sopenharmony_ci sock = result; 455d5ac70f0Sopenharmony_ci 456d5ac70f0Sopenharmony_ci reqlen = sizeof(*req) + snamelen; 457d5ac70f0Sopenharmony_ci req = alloca(reqlen); 458d5ac70f0Sopenharmony_ci memcpy(req->name, sname, snamelen); 459d5ac70f0Sopenharmony_ci req->dev_type = SND_DEV_TYPE_CONTROL; 460d5ac70f0Sopenharmony_ci req->transport_type = SND_TRANSPORT_TYPE_SHM; 461d5ac70f0Sopenharmony_ci req->stream = 0; 462d5ac70f0Sopenharmony_ci req->mode = mode; 463d5ac70f0Sopenharmony_ci req->namelen = snamelen; 464d5ac70f0Sopenharmony_ci err = write(sock, req, reqlen); 465d5ac70f0Sopenharmony_ci if (err < 0) { 466d5ac70f0Sopenharmony_ci SNDERR("write error"); 467d5ac70f0Sopenharmony_ci result = -errno; 468d5ac70f0Sopenharmony_ci goto _err; 469d5ac70f0Sopenharmony_ci } 470d5ac70f0Sopenharmony_ci if ((size_t) err != reqlen) { 471d5ac70f0Sopenharmony_ci SNDERR("write size error"); 472d5ac70f0Sopenharmony_ci result = -EINVAL; 473d5ac70f0Sopenharmony_ci goto _err; 474d5ac70f0Sopenharmony_ci } 475d5ac70f0Sopenharmony_ci err = read(sock, &ans, sizeof(ans)); 476d5ac70f0Sopenharmony_ci if (err < 0) { 477d5ac70f0Sopenharmony_ci SNDERR("read error"); 478d5ac70f0Sopenharmony_ci result = -errno; 479d5ac70f0Sopenharmony_ci goto _err; 480d5ac70f0Sopenharmony_ci } 481d5ac70f0Sopenharmony_ci if (err != sizeof(ans)) { 482d5ac70f0Sopenharmony_ci SNDERR("read size error"); 483d5ac70f0Sopenharmony_ci result = -EINVAL; 484d5ac70f0Sopenharmony_ci goto _err; 485d5ac70f0Sopenharmony_ci } 486d5ac70f0Sopenharmony_ci result = ans.result; 487d5ac70f0Sopenharmony_ci if (result < 0) 488d5ac70f0Sopenharmony_ci goto _err; 489d5ac70f0Sopenharmony_ci 490d5ac70f0Sopenharmony_ci ctrl = shmat(ans.cookie, 0, 0); 491d5ac70f0Sopenharmony_ci if (!ctrl) { 492d5ac70f0Sopenharmony_ci result = -errno; 493d5ac70f0Sopenharmony_ci goto _err; 494d5ac70f0Sopenharmony_ci } 495d5ac70f0Sopenharmony_ci 496d5ac70f0Sopenharmony_ci shm = calloc(1, sizeof(snd_ctl_shm_t)); 497d5ac70f0Sopenharmony_ci if (!shm) { 498d5ac70f0Sopenharmony_ci result = -ENOMEM; 499d5ac70f0Sopenharmony_ci goto _err; 500d5ac70f0Sopenharmony_ci } 501d5ac70f0Sopenharmony_ci 502d5ac70f0Sopenharmony_ci shm->socket = sock; 503d5ac70f0Sopenharmony_ci shm->ctrl = ctrl; 504d5ac70f0Sopenharmony_ci 505d5ac70f0Sopenharmony_ci err = snd_ctl_new(&ctl, SND_CTL_TYPE_SHM, name, mode); 506d5ac70f0Sopenharmony_ci if (err < 0) { 507d5ac70f0Sopenharmony_ci result = err; 508d5ac70f0Sopenharmony_ci goto _err; 509d5ac70f0Sopenharmony_ci } 510d5ac70f0Sopenharmony_ci ctl->ops = &snd_ctl_shm_ops; 511d5ac70f0Sopenharmony_ci ctl->private_data = shm; 512d5ac70f0Sopenharmony_ci err = snd_ctl_shm_poll_descriptor(ctl); 513d5ac70f0Sopenharmony_ci if (err < 0) { 514d5ac70f0Sopenharmony_ci snd_ctl_close(ctl); 515d5ac70f0Sopenharmony_ci return err; 516d5ac70f0Sopenharmony_ci } 517d5ac70f0Sopenharmony_ci ctl->poll_fd = err; 518d5ac70f0Sopenharmony_ci *handlep = ctl; 519d5ac70f0Sopenharmony_ci return 0; 520d5ac70f0Sopenharmony_ci 521d5ac70f0Sopenharmony_ci _err: 522d5ac70f0Sopenharmony_ci close(sock); 523d5ac70f0Sopenharmony_ci if (ctrl) 524d5ac70f0Sopenharmony_ci shmdt(ctrl); 525d5ac70f0Sopenharmony_ci free(shm); 526d5ac70f0Sopenharmony_ci return result; 527d5ac70f0Sopenharmony_ci} 528d5ac70f0Sopenharmony_ci 529d5ac70f0Sopenharmony_ciint _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd_config_t *conf, int mode) 530d5ac70f0Sopenharmony_ci{ 531d5ac70f0Sopenharmony_ci snd_config_iterator_t i, next; 532d5ac70f0Sopenharmony_ci const char *server = NULL; 533d5ac70f0Sopenharmony_ci const char *ctl_name = NULL; 534d5ac70f0Sopenharmony_ci snd_config_t *sconfig; 535d5ac70f0Sopenharmony_ci const char *sockname = NULL; 536d5ac70f0Sopenharmony_ci long port = -1; 537d5ac70f0Sopenharmony_ci int err; 538d5ac70f0Sopenharmony_ci 539d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, conf) { 540d5ac70f0Sopenharmony_ci snd_config_t *n = snd_config_iterator_entry(i); 541d5ac70f0Sopenharmony_ci const char *id; 542d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 543d5ac70f0Sopenharmony_ci continue; 544d5ac70f0Sopenharmony_ci if (_snd_conf_generic_id(id)) 545d5ac70f0Sopenharmony_ci continue; 546d5ac70f0Sopenharmony_ci if (strcmp(id, "server") == 0) { 547d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &server); 548d5ac70f0Sopenharmony_ci if (err < 0) { 549d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 550d5ac70f0Sopenharmony_ci return -EINVAL; 551d5ac70f0Sopenharmony_ci } 552d5ac70f0Sopenharmony_ci continue; 553d5ac70f0Sopenharmony_ci } 554d5ac70f0Sopenharmony_ci if (strcmp(id, "ctl") == 0) { 555d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &ctl_name); 556d5ac70f0Sopenharmony_ci if (err < 0) { 557d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 558d5ac70f0Sopenharmony_ci return -EINVAL; 559d5ac70f0Sopenharmony_ci } 560d5ac70f0Sopenharmony_ci continue; 561d5ac70f0Sopenharmony_ci } 562d5ac70f0Sopenharmony_ci SNDERR("Unknown field %s", id); 563d5ac70f0Sopenharmony_ci return -EINVAL; 564d5ac70f0Sopenharmony_ci } 565d5ac70f0Sopenharmony_ci if (!ctl_name) { 566d5ac70f0Sopenharmony_ci SNDERR("ctl is not defined"); 567d5ac70f0Sopenharmony_ci return -EINVAL; 568d5ac70f0Sopenharmony_ci } 569d5ac70f0Sopenharmony_ci if (!server) { 570d5ac70f0Sopenharmony_ci SNDERR("server is not defined"); 571d5ac70f0Sopenharmony_ci return -EINVAL; 572d5ac70f0Sopenharmony_ci } 573d5ac70f0Sopenharmony_ci err = snd_config_search_definition(root, "server", server, &sconfig); 574d5ac70f0Sopenharmony_ci if (err < 0) { 575d5ac70f0Sopenharmony_ci SNDERR("Unknown server %s", server); 576d5ac70f0Sopenharmony_ci return -EINVAL; 577d5ac70f0Sopenharmony_ci } 578d5ac70f0Sopenharmony_ci if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) { 579d5ac70f0Sopenharmony_ci SNDERR("Invalid type for server %s definition", server); 580d5ac70f0Sopenharmony_ci err = -EINVAL; 581d5ac70f0Sopenharmony_ci goto _err; 582d5ac70f0Sopenharmony_ci } 583d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, sconfig) { 584d5ac70f0Sopenharmony_ci snd_config_t *n = snd_config_iterator_entry(i); 585d5ac70f0Sopenharmony_ci const char *id; 586d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 587d5ac70f0Sopenharmony_ci continue; 588d5ac70f0Sopenharmony_ci if (_snd_conf_generic_id(id)) 589d5ac70f0Sopenharmony_ci continue; 590d5ac70f0Sopenharmony_ci if (strcmp(id, "host") == 0) 591d5ac70f0Sopenharmony_ci continue; 592d5ac70f0Sopenharmony_ci if (strcmp(id, "socket") == 0) { 593d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &sockname); 594d5ac70f0Sopenharmony_ci if (err < 0) { 595d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 596d5ac70f0Sopenharmony_ci goto _err; 597d5ac70f0Sopenharmony_ci } 598d5ac70f0Sopenharmony_ci continue; 599d5ac70f0Sopenharmony_ci } 600d5ac70f0Sopenharmony_ci if (strcmp(id, "port") == 0) { 601d5ac70f0Sopenharmony_ci err = snd_config_get_integer(n, &port); 602d5ac70f0Sopenharmony_ci if (err < 0) { 603d5ac70f0Sopenharmony_ci SNDERR("Invalid type for %s", id); 604d5ac70f0Sopenharmony_ci goto _err; 605d5ac70f0Sopenharmony_ci } 606d5ac70f0Sopenharmony_ci continue; 607d5ac70f0Sopenharmony_ci } 608d5ac70f0Sopenharmony_ci SNDERR("Unknown field %s", id); 609d5ac70f0Sopenharmony_ci err = -EINVAL; 610d5ac70f0Sopenharmony_ci goto _err; 611d5ac70f0Sopenharmony_ci } 612d5ac70f0Sopenharmony_ci 613d5ac70f0Sopenharmony_ci if (!sockname) { 614d5ac70f0Sopenharmony_ci SNDERR("socket is not defined"); 615d5ac70f0Sopenharmony_ci goto _err; 616d5ac70f0Sopenharmony_ci } 617d5ac70f0Sopenharmony_ci err = snd_ctl_shm_open(handlep, name, sockname, ctl_name, mode); 618d5ac70f0Sopenharmony_ci _err: 619d5ac70f0Sopenharmony_ci snd_config_delete(sconfig); 620d5ac70f0Sopenharmony_ci return err; 621d5ac70f0Sopenharmony_ci} 622d5ac70f0Sopenharmony_ciSND_DLSYM_BUILD_VERSION(_snd_ctl_shm_open, SND_CONTROL_DLSYM_VERSION); 623