• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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