blob: f19f07b585824608a3f4c77fd3f2a0e20e041f15 [file] [log] [blame]
Bhalchandra Gajarebb40f172019-08-21 15:07:28 -07001/* pcm_hw.c
2**
3** Copyright (c) 2019, The Linux Foundation. All rights reserved.
4**
5** Redistribution and use in source and binary forms, with or without
6** modification, are permitted provided that the following conditions are
7** met:
8** * Redistributions of source code must retain the above copyright
9** notice, this list of conditions and the following disclaimer.
10** * Redistributions in binary form must reproduce the above
11** copyright notice, this list of conditions and the following
12** disclaimer in the documentation and/or other materials provided
13** with the distribution.
14** * Neither the name of The Linux Foundation nor the names of its
15** contributors may be used to endorse or promote products derived
16** from this software without specific prior written permission.
17**
18** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29**/
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <fcntl.h>
34#include <stdarg.h>
35#include <string.h>
36#include <errno.h>
37#include <unistd.h>
38#include <poll.h>
39
40#include <sys/ioctl.h>
Phani Kumar Uppalapati858abf62019-10-23 16:08:08 +053041#include <sys/mman.h>
Bhalchandra Gajarebb40f172019-08-21 15:07:28 -070042#include <linux/ioctl.h>
43#include <sound/asound.h>
44#include <tinyalsa/asoundlib.h>
45
46#include "pcm_io.h"
47
48struct pcm_hw_data {
49 unsigned int card;
50 unsigned int device;
51 unsigned int fd;
52 void *snd_node;
53};
54
55static void pcm_hw_close(void *data)
56{
57 struct pcm_hw_data *hw_data = data;
58
59 if (hw_data->fd >= 0)
60 close(hw_data->fd);
61
62 free(hw_data);
63}
64
65static int pcm_hw_ioctl(void *data, unsigned int cmd, ...)
66{
67 struct pcm_hw_data *hw_data = data;
68 va_list ap;
69 void *arg;
70
71 va_start(ap, cmd);
72 arg = va_arg(ap, void *);
73 va_end(ap);
74
75 return ioctl(hw_data->fd, cmd, arg);
76}
77
Phani Kumar Uppalapati858abf62019-10-23 16:08:08 +053078static int pcm_hw_poll(void *data __attribute__((unused)),
79 struct pollfd *pfd, nfds_t nfds, int timeout)
80{
81 return poll(pfd, nfds, timeout);
82}
83
84static void* pcm_hw_mmap(void *data, void *addr, size_t length, int prot,
85 int flags, off_t offset)
86{
87 struct pcm_hw_data *hw_data = data;
88
89 return mmap(addr, length, prot, flags, hw_data->fd, offset);
90}
91
92static int pcm_hw_munmap(void *data __attribute__((unused)), void *addr, size_t length)
93{
94 return munmap(addr, length);
95}
96
Bhalchandra Gajarebb40f172019-08-21 15:07:28 -070097static int pcm_hw_open(unsigned int card, unsigned int device,
98 unsigned int flags, void **data,
99 __attribute__((unused)) void *node)
100{
101 struct pcm_hw_data *hw_data;
102 char fn[256];
103 int fd;
104
105 hw_data = calloc(1, sizeof(*hw_data));
106 if (!hw_data) {
107 return -ENOMEM;
108 }
109
110 snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
111 flags & PCM_IN ? 'c' : 'p');
112 fd = open(fn, O_RDWR|O_NONBLOCK);
113 if (fd < 0) {
114 printf("%s: cannot open device '%s'", __func__, fn);
115 return fd;
116 }
117
118 if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK) < 0) {
119 printf("%s: failed to reset blocking mode '%s'",
120 __func__, fn);
121 goto err_close;
122 }
123
124 hw_data->snd_node = node;
125 hw_data->card = card;
126 hw_data->device = device;
127 hw_data->fd = fd;
128
129 *data = hw_data;
130
131 return fd;
132
133err_close:
134 close(fd);
135 free(hw_data);
136 return -ENODEV;
137}
138
139struct pcm_ops hw_ops = {
140 .open = pcm_hw_open,
141 .close = pcm_hw_close,
142 .ioctl = pcm_hw_ioctl,
Phani Kumar Uppalapati858abf62019-10-23 16:08:08 +0530143 .mmap = pcm_hw_mmap,
144 .munmap = pcm_hw_munmap,
145 .poll = pcm_hw_poll,
Bhalchandra Gajarebb40f172019-08-21 15:07:28 -0700146};