xref: /aosp_15_r20/external/tinyalsa/mixer_hw.c (revision d0c94b832dfb3062bf15d9baaf64123fc670b06c)
1*d0c94b83SXin Li /* mixer_hw.c
2*d0c94b83SXin Li **
3*d0c94b83SXin Li ** Copyright (c) 2019, The Linux Foundation. All rights reserved.
4*d0c94b83SXin Li **
5*d0c94b83SXin Li ** Redistribution and use in source and binary forms, with or without
6*d0c94b83SXin Li ** modification, are permitted provided that the following conditions are
7*d0c94b83SXin Li ** met:
8*d0c94b83SXin Li **   * Redistributions of source code must retain the above copyright
9*d0c94b83SXin Li **     notice, this list of conditions and the following disclaimer.
10*d0c94b83SXin Li **   * Redistributions in binary form must reproduce the above
11*d0c94b83SXin Li **     copyright notice, this list of conditions and the following
12*d0c94b83SXin Li **     disclaimer in the documentation and/or other materials provided
13*d0c94b83SXin Li **     with the distribution.
14*d0c94b83SXin Li **   * Neither the name of The Linux Foundation nor the names of its
15*d0c94b83SXin Li **     contributors may be used to endorse or promote products derived
16*d0c94b83SXin Li **     from this software without specific prior written permission.
17*d0c94b83SXin Li **
18*d0c94b83SXin Li ** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19*d0c94b83SXin Li ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20*d0c94b83SXin Li ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21*d0c94b83SXin Li ** ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22*d0c94b83SXin Li ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*d0c94b83SXin Li ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*d0c94b83SXin Li ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25*d0c94b83SXin Li ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26*d0c94b83SXin Li ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27*d0c94b83SXin Li ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28*d0c94b83SXin Li ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*d0c94b83SXin Li **/
30*d0c94b83SXin Li 
31*d0c94b83SXin Li #include <stdio.h>
32*d0c94b83SXin Li #include <stdlib.h>
33*d0c94b83SXin Li #include <stdarg.h>
34*d0c94b83SXin Li #include <stdint.h>
35*d0c94b83SXin Li #include <stdbool.h>
36*d0c94b83SXin Li #include <string.h>
37*d0c94b83SXin Li #include <unistd.h>
38*d0c94b83SXin Li #include <fcntl.h>
39*d0c94b83SXin Li #include <errno.h>
40*d0c94b83SXin Li #include <ctype.h>
41*d0c94b83SXin Li #include <poll.h>
42*d0c94b83SXin Li 
43*d0c94b83SXin Li #include <sys/ioctl.h>
44*d0c94b83SXin Li 
45*d0c94b83SXin Li #include <linux/ioctl.h>
46*d0c94b83SXin Li #include <sound/asound.h>
47*d0c94b83SXin Li 
48*d0c94b83SXin Li #include "mixer_io.h"
49*d0c94b83SXin Li 
50*d0c94b83SXin Li struct mixer_hw_data {
51*d0c94b83SXin Li     unsigned int card;
52*d0c94b83SXin Li     int fd;
53*d0c94b83SXin Li };
54*d0c94b83SXin Li 
mixer_hw_close(void * data)55*d0c94b83SXin Li static void mixer_hw_close(void *data)
56*d0c94b83SXin Li {
57*d0c94b83SXin Li     struct mixer_hw_data *hw_data = data;
58*d0c94b83SXin Li 
59*d0c94b83SXin Li     if (!hw_data)
60*d0c94b83SXin Li         return;
61*d0c94b83SXin Li 
62*d0c94b83SXin Li     if (hw_data->fd >= 0)
63*d0c94b83SXin Li         close(hw_data->fd);
64*d0c94b83SXin Li 
65*d0c94b83SXin Li     hw_data->fd = -1;
66*d0c94b83SXin Li     free(hw_data);
67*d0c94b83SXin Li     hw_data = NULL;
68*d0c94b83SXin Li }
69*d0c94b83SXin Li 
mixer_hw_ioctl(void * data,unsigned int cmd,...)70*d0c94b83SXin Li static int mixer_hw_ioctl(void *data, unsigned int cmd, ...)
71*d0c94b83SXin Li {
72*d0c94b83SXin Li     struct mixer_hw_data *hw_data = data;
73*d0c94b83SXin Li     va_list ap;
74*d0c94b83SXin Li     void *arg;
75*d0c94b83SXin Li 
76*d0c94b83SXin Li     va_start(ap, cmd);
77*d0c94b83SXin Li     arg = va_arg(ap, void *);
78*d0c94b83SXin Li     va_end(ap);
79*d0c94b83SXin Li 
80*d0c94b83SXin Li     return ioctl(hw_data->fd, cmd, arg);
81*d0c94b83SXin Li }
82*d0c94b83SXin Li 
mixer_hw_read_event(void * data,struct snd_ctl_event * ev,size_t size)83*d0c94b83SXin Li static ssize_t mixer_hw_read_event(void *data, struct snd_ctl_event *ev,
84*d0c94b83SXin Li                                    size_t size)
85*d0c94b83SXin Li {
86*d0c94b83SXin Li     struct mixer_hw_data *hw_data = data;
87*d0c94b83SXin Li 
88*d0c94b83SXin Li     return read(hw_data->fd, ev, size);
89*d0c94b83SXin Li }
90*d0c94b83SXin Li 
91*d0c94b83SXin Li static struct mixer_ops mixer_hw_ops = {
92*d0c94b83SXin Li     .close = mixer_hw_close,
93*d0c94b83SXin Li     .get_poll_fd = NULL,
94*d0c94b83SXin Li     .read_event = mixer_hw_read_event,
95*d0c94b83SXin Li     .ioctl = mixer_hw_ioctl,
96*d0c94b83SXin Li };
97*d0c94b83SXin Li 
mixer_hw_open(unsigned int card,void ** data,struct mixer_ops ** ops)98*d0c94b83SXin Li int mixer_hw_open(unsigned int card, void **data,
99*d0c94b83SXin Li                   struct mixer_ops **ops)
100*d0c94b83SXin Li {
101*d0c94b83SXin Li     struct mixer_hw_data *hw_data;
102*d0c94b83SXin Li     int fd;
103*d0c94b83SXin Li     char fn[256];
104*d0c94b83SXin Li 
105*d0c94b83SXin Li     snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
106*d0c94b83SXin Li     fd = open(fn, O_RDWR);
107*d0c94b83SXin Li     if (fd < 0)
108*d0c94b83SXin Li         return fd;
109*d0c94b83SXin Li 
110*d0c94b83SXin Li     hw_data = calloc(1, sizeof(*hw_data));
111*d0c94b83SXin Li     if (!hw_data) {
112*d0c94b83SXin Li         close(fd);
113*d0c94b83SXin Li         return -1;
114*d0c94b83SXin Li     }
115*d0c94b83SXin Li 
116*d0c94b83SXin Li     hw_data->card = card;
117*d0c94b83SXin Li     hw_data->fd = fd;
118*d0c94b83SXin Li     *data = hw_data;
119*d0c94b83SXin Li     *ops = &mixer_hw_ops;
120*d0c94b83SXin Li 
121*d0c94b83SXin Li     return fd;
122*d0c94b83SXin Li }
123