1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <assert.h>
9
10 #include <sys/ioctl.h>
11 #include <linux/cpcap_audio.h>
12 #include <linux/tegra_audio.h>
13
14 #define FAILIF(x, ...) do if (x) { \
15 fprintf(stderr, __VA_ARGS__); \
16 exit(EXIT_FAILURE); \
17 } while (0)
18
19 static char buffer[4096];
20
21 int
main(int argc,char * argv[])22 main(int argc, char *argv[])
23 {
24 int opt, cfd;
25 int output = -4;
26 int input = -3;
27 int volume = -1; /* max 15 */
28 int in_volume = -1; /* max 31 */
29 int record = -1; /* start 1, stop 0 */
30 int use_dma = -1;
31 int in_rate = -1;
32 int in_channels = -1;
33
34 while ((opt = getopt(argc, argv, "o::i::s:c:v::g::d:r:")) != -1) {
35 switch (opt) {
36 case 'o':
37 if (optarg)
38 output = atoi(optarg);
39 else
40 output = -5;
41 break;
42 case 'i':
43 if (optarg)
44 input = atoi(optarg);
45 else
46 input = -4;
47 break;
48 case 'v':
49 if (optarg)
50 volume = atoi(optarg);
51 else
52 volume = -2;
53 break;
54 case 's':
55 in_rate = atoi(optarg);
56 break;
57 case 'c':
58 in_channels = atoi(optarg);
59 break;
60 case 'g':
61 if (optarg)
62 in_volume = atoi(optarg);
63 else
64 in_volume = -2;
65 break;
66 case 'd':
67 use_dma = atoi(optarg);
68 break;
69 case 'r':
70 record = atoi(optarg);
71 break;
72 default: /* '?' */
73 fprintf(stderr, "Unknown option\n");
74 exit(EXIT_FAILURE);
75 }
76 }
77
78 cfd = open("/dev/audio_ctl", O_RDWR);
79
80 printf("cfd opened\n");
81
82 FAILIF(cfd < 0, "could not open control: %s\n", strerror(errno));
83
84 if (output > -4 && output < 4) {
85 struct cpcap_audio_stream cfg;
86 assert(!output); // 1 or 2 or 3 or -1 or -2 or -3
87 if (output < 0) {
88 cfg.id = (-output) - 1;
89 cfg.on = 0;
90 printf("set output %d to OFF\n", cfg.id);
91 }
92 else {
93 cfg.id = output - 1;
94 cfg.on = 1;
95 printf("set output %d to ON\n", cfg.id);
96 }
97 FAILIF(ioctl(cfd, CPCAP_AUDIO_OUT_SET_OUTPUT, &cfg) < 0,
98 "Cannot set output device %d: %s\n", cfg.id, strerror(errno));
99 }
100 else if (output == -5) {
101 struct cpcap_audio_stream cfg;
102 FAILIF(ioctl(cfd, CPCAP_AUDIO_OUT_GET_OUTPUT, &cfg) < 0,
103 "Cannot get output device %d: %s\n", cfg.id, strerror(errno));
104 printf("current output: %d, %s\n", cfg.id, (cfg.on ? "on" : "off"));
105 }
106
107 if (volume >= 0) {
108 printf("set output volume\n");
109 FAILIF(ioctl(cfd, CPCAP_AUDIO_OUT_SET_VOLUME, volume) < 0,
110 "Cannot set volume to %d: %s\n", output, strerror(errno));
111 }
112 else if (volume == -2) {
113 FAILIF(ioctl(cfd, CPCAP_AUDIO_OUT_GET_VOLUME, &volume) < 0,
114 "Cannot get volume: %s\n", strerror(errno));
115 printf("speaker volume: %d\n", volume);
116 }
117
118 if (in_volume >= 0) {
119 printf("set input volume\n");
120 FAILIF(ioctl(cfd, CPCAP_AUDIO_IN_SET_VOLUME, in_volume) < 0,
121 "Cannot set input volume to %d: %s\n", output, strerror(errno));
122 }
123 else if (in_volume == -2) {
124 FAILIF(ioctl(cfd, CPCAP_AUDIO_IN_GET_VOLUME, &in_volume) < 0,
125 "Cannot get input volume: %s\n", strerror(errno));
126 printf("microphone gain: %d\n", in_volume);
127 }
128
129 if (input > -3 && input < 3) {
130 struct cpcap_audio_stream cfg;
131 assert(!input); // 1 or 2 or -1 or -2
132 if (input < 0) {
133 cfg.id = (-input) - 1;
134 cfg.on = 0;
135 printf("set input %d to OFF\n", cfg.id);
136 }
137 else {
138 cfg.id = input - 1;
139 cfg.on = 1;
140 printf("set input %d to ON\n", cfg.id);
141 }
142 FAILIF(ioctl(cfd, CPCAP_AUDIO_IN_SET_INPUT, &cfg) < 0,
143 "Cannot set input device %d: %s\n", cfg.id, strerror(errno));
144 }
145 else if (input == -4) {
146 struct cpcap_audio_stream cfg;
147 FAILIF(ioctl(cfd, CPCAP_AUDIO_IN_GET_INPUT, &cfg) < 0,
148 "Cannot get input device %d: %s\n", cfg.id, strerror(errno));
149 printf("current input: %d, %s\n", cfg.id, (cfg.on ? "on" : "off"));
150 }
151
152 if (in_channels >= 0 || in_rate >= 0) {
153 int recfd;
154 struct tegra_audio_in_config cfg;
155
156 printf("set input config\n");
157
158 printf("opening audio input\n");
159 recfd = open("/dev/audio1_in_ctl", O_RDWR);
160 FAILIF(recfd < 0, "could not open for recording: %s\n", strerror(errno));
161
162 printf("getting audio-input config\n");
163 FAILIF(ioctl(recfd, TEGRA_AUDIO_IN_GET_CONFIG, &cfg) < 0,
164 "could not get input config: %s\n", strerror(errno));
165 if (in_channels >= 0)
166 cfg.stereo = in_channels == 2;
167 if (in_rate >= 0)
168 cfg.rate = in_rate;
169 printf("setting audio-input config (stereo %d, rate %d)\n", cfg.stereo, cfg.rate);
170 FAILIF(ioctl(recfd, TEGRA_AUDIO_IN_SET_CONFIG, &cfg) < 0,
171 "could not set input config: %s\n", strerror(errno));
172 close(recfd);
173 }
174
175 if (use_dma >= 0) {
176 int piofd = open("/sys/kernel/debug/tegra_audio/dma", O_RDWR);
177 FAILIF(piofd < 0, "Could not open DMA/PIO toggle file: %s\n", strerror(errno));
178 if (use_dma)
179 FAILIF(write(piofd, "dma\n", sizeof("dma\n")) < 0,
180 "Could not set to DMA: %s\n", strerror(errno));
181 else
182 FAILIF(write(piofd, "dma\n", sizeof("pio\n")) < 0,
183 "Could not set to PIO: %s\n", strerror(errno));
184 }
185
186 if (record >= 0) {
187 printf("opening audio input\n");
188 int recfd = open("/dev/audio1_in_ctl", O_RDWR);
189 printf("done opening audio input\n");
190 FAILIF(recfd < 0, "could not open for recording: %s\n", strerror(errno));
191 if (record) {
192 printf("start recording\n");
193 FAILIF(ioctl(recfd, TEGRA_AUDIO_IN_START) < 0,
194 "Could not start recording: %s\n", strerror(errno));
195 } else {
196 printf("stop recording\n");
197 FAILIF(ioctl(recfd, TEGRA_AUDIO_IN_STOP) < 0,
198 "Could not stop recording: %s\n", strerror(errno));
199 }
200 }
201
202 return 0;
203 }
204
205