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 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