1 /* 2 ** Copyright 2010, The Android Open-Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 #define LOG_TAG "alsa_pcm" 18 //#define LOG_NDEBUG 0 19 #include <cutils/log.h> 20 #include <cutils/config_utils.h> 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <fcntl.h> 25 #include <stdarg.h> 26 #include <string.h> 27 #include <errno.h> 28 #include <unistd.h> 29 30 #include <sys/ioctl.h> 31 #include <sys/mman.h> 32 #include <sys/time.h> 33 34 #include <linux/ioctl.h> 35 36 #include "alsa_audio.h" 37 38 #define __force 39 #define __bitwise 40 #define __user 41 #include "asound.h" 42 43 #define DEBUG 0 44 45 /* alsa parameter manipulation cruft */ 46 47 #define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL 48 49 static inline int param_is_mask(int p) 50 { 51 return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && 52 (p <= SNDRV_PCM_HW_PARAM_LAST_MASK); 53 } 54 55 static inline int param_is_interval(int p) 56 { 57 return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) && 58 (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL); 59 } 60 61 static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n) 62 { 63 return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]); 64 } 65 66 static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n) 67 { 68 return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]); 69 } 70 71 static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit) 72 { 73 if (bit >= SNDRV_MASK_MAX) 74 return; 75 if (param_is_mask(n)) { 76 struct snd_mask *m = param_to_mask(p, n); 77 m->bits[0] = 0; 78 m->bits[1] = 0; 79 m->bits[bit >> 5] |= (1 << (bit & 31)); 80 } 81 } 82 83 static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned val) 84 { 85 if (param_is_interval(n)) { 86 struct snd_interval *i = param_to_interval(p, n); 87 i->min = val; 88 } 89 } 90 91 static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned val) 92 { 93 if (param_is_interval(n)) { 94 struct snd_interval *i = param_to_interval(p, n); 95 i->max = val; 96 } 97 } 98 99 static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned val) 100 { 101 if (param_is_interval(n)) { 102 struct snd_interval *i = param_to_interval(p, n); 103 i->min = val; 104 i->max = val; 105 i->integer = 1; 106 } 107 } 108 109 static void param_init(struct snd_pcm_hw_params *p) 110 { 111 int n; 112 memset(p, 0, sizeof(*p)); 113 for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK; 114 n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) { 115 struct snd_mask *m = param_to_mask(p, n); 116 m->bits[0] = ~0; 117 m->bits[1] = ~0; 118 } 119 for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; 120 n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) { 121 struct snd_interval *i = param_to_interval(p, n); 122 i->min = 0; 123 i->max = ~0; 124 } 125 } 126 127 /* debugging gunk */ 128 129 #if DEBUG 130 static const char *param_name[PARAM_MAX+1] = { 131 [SNDRV_PCM_HW_PARAM_ACCESS] = "access", 132 [SNDRV_PCM_HW_PARAM_FORMAT] = "format", 133 [SNDRV_PCM_HW_PARAM_SUBFORMAT] = "subformat", 134 135 [SNDRV_PCM_HW_PARAM_SAMPLE_BITS] = "sample_bits", 136 [SNDRV_PCM_HW_PARAM_FRAME_BITS] = "frame_bits", 137 [SNDRV_PCM_HW_PARAM_CHANNELS] = "channels", 138 [SNDRV_PCM_HW_PARAM_RATE] = "rate", 139 [SNDRV_PCM_HW_PARAM_PERIOD_TIME] = "period_time", 140 [SNDRV_PCM_HW_PARAM_PERIOD_SIZE] = "period_size", 141 [SNDRV_PCM_HW_PARAM_PERIOD_BYTES] = "period_bytes", 142 [SNDRV_PCM_HW_PARAM_PERIODS] = "periods", 143 [SNDRV_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time", 144 [SNDRV_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size", 145 [SNDRV_PCM_HW_PARAM_BUFFER_BYTES] = "buffer_bytes", 146 [SNDRV_PCM_HW_PARAM_TICK_TIME] = "tick_time", 147 }; 148 149 static void param_dump(struct snd_pcm_hw_params *p) 150 { 151 int n; 152 153 for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK; 154 n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) { 155 struct snd_mask *m = param_to_mask(p, n); 156 LOGV("%s = %08x%08x\n", param_name[n], 157 m->bits[1], m->bits[0]); 158 } 159 for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; 160 n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) { 161 struct snd_interval *i = param_to_interval(p, n); 162 LOGV("%s = (%d,%d) omin=%d omax=%d int=%d empty=%d\n", 163 param_name[n], i->min, i->max, i->openmin, 164 i->openmax, i->integer, i->empty); 165 } 166 LOGV("info = %08x\n", p->info); 167 LOGV("msbits = %d\n", p->msbits); 168 LOGV("rate = %d/%d\n", p->rate_num, p->rate_den); 169 LOGV("fifo = %d\n", (int) p->fifo_size); 170 } 171 172 static void info_dump(struct snd_pcm_info *info) 173 { 174 LOGV("device = %d\n", info->device); 175 LOGV("subdevice = %d\n", info->subdevice); 176 LOGV("stream = %d\n", info->stream); 177 LOGV("card = %d\n", info->card); 178 LOGV("id = '%s'\n", info->id); 179 LOGV("name = '%s'\n", info->name); 180 LOGV("subname = '%s'\n", info->subname); 181 LOGV("dev_class = %d\n", info->dev_class); 182 LOGV("dev_subclass = %d\n", info->dev_subclass); 183 LOGV("subdevices_count = %d\n", info->subdevices_count); 184 LOGV("subdevices_avail = %d\n", info->subdevices_avail); 185 } 186 #else 187 static void param_dump(struct snd_pcm_hw_params *p) {} 188 static void info_dump(struct snd_pcm_info *info) {} 189 #endif 190 191 #define PCM_ERROR_MAX 128 192 193 struct pcm { 194 int fd; 195 unsigned flags; 196 int running:1; 197 int underruns; 198 unsigned buffer_size; 199 char error[PCM_ERROR_MAX]; 200 }; 201 202 unsigned pcm_buffer_size(struct pcm *pcm) 203 { 204 return pcm->buffer_size; 205 } 206 207 const char* pcm_error(struct pcm *pcm) 208 { 209 return pcm->error; 210 } 211 212 static int oops(struct pcm *pcm, int e, const char *fmt, ...) 213 { 214 va_list ap; 215 int sz; 216 217 va_start(ap, fmt); 218 vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap); 219 va_end(ap); 220 sz = strlen(pcm->error); 221 222 if (errno) 223 snprintf(pcm->error + sz, PCM_ERROR_MAX - sz, 224 ": %s", strerror(e)); 225 return -1; 226 } 227 228 int pcm_write(struct pcm *pcm, void *data, unsigned count) 229 { 230 struct snd_xferi x; 231 232 if (pcm->flags & PCM_IN) 233 return -EINVAL; 234 235 x.buf = data; 236 x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4); 237 238 for (;;) { 239 if (!pcm->running) { 240 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE)) 241 return oops(pcm, errno, "cannot prepare channel"); 242 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) 243 return oops(pcm, errno, "cannot write initial data"); 244 pcm->running = 1; 245 return 0; 246 } 247 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) { 248 pcm->running = 0; 249 if (errno == EPIPE) { 250 /* we failed to make our window -- try to restart */ 251 pcm->underruns++; 252 continue; 253 } 254 return oops(pcm, errno, "cannot write stream data"); 255 } 256 return 0; 257 } 258 } 259 260 int pcm_read(struct pcm *pcm, void *data, unsigned count) 261 { 262 struct snd_xferi x; 263 264 if (!(pcm->flags & PCM_IN)) 265 return -EINVAL; 266 267 x.buf = data; 268 x.frames = (pcm->flags & PCM_MONO) ? (count / 2) : (count / 4); 269 270 // LOGV("read() %d frames", x.frames); 271 for (;;) { 272 if (!pcm->running) { 273 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE)) 274 return oops(pcm, errno, "cannot prepare channel"); 275 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START)) 276 return oops(pcm, errno, "cannot start channel"); 277 pcm->running = 1; 278 } 279 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) { 280 pcm->running = 0; 281 if (errno == EPIPE) { 282 /* we failed to make our window -- try to restart */ 283 pcm->underruns++; 284 continue; 285 } 286 return oops(pcm, errno, "cannot read stream data"); 287 } 288 // LOGV("read() got %d frames", x.frames); 289 return 0; 290 } 291 } 292 293 static struct pcm bad_pcm = { 294 .fd = -1, 295 }; 296 297 int pcm_close(struct pcm *pcm) 298 { 299 if (pcm == &bad_pcm) 300 return 0; 301 302 if (pcm->fd >= 0) 303 close(pcm->fd); 304 pcm->running = 0; 305 pcm->buffer_size = 0; 306 pcm->fd = -1; 307 return 0; 308 } 309 310 struct pcm *pcm_open(unsigned flags) 311 { 312 const char *dname; 313 struct pcm *pcm; 314 struct snd_pcm_info info; 315 struct snd_pcm_hw_params params; 316 struct snd_pcm_sw_params sparams; 317 unsigned period_sz; 318 unsigned period_cnt; 319 320 LOGV("pcm_open(0x%08x)",flags); 321 322 pcm = calloc(1, sizeof(struct pcm)); 323 if (!pcm) 324 return &bad_pcm; 325 326 if (flags & PCM_IN) { 327 dname = "/dev/snd/pcmC0D0c"; 328 } else { 329 dname = "/dev/snd/pcmC0D0p"; 330 } 331 332 LOGV("pcm_open() period sz multiplier %d", 333 ((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1); 334 period_sz = 128 * (((flags & PCM_PERIOD_SZ_MASK) >> PCM_PERIOD_SZ_SHIFT) + 1); 335 LOGV("pcm_open() period cnt %d", 336 ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN); 337 period_cnt = ((flags & PCM_PERIOD_CNT_MASK) >> PCM_PERIOD_CNT_SHIFT) + PCM_PERIOD_CNT_MIN; 338 339 pcm->flags = flags; 340 pcm->fd = open(dname, O_RDWR); 341 if (pcm->fd < 0) { 342 oops(pcm, errno, "cannot open device '%s'"); 343 return pcm; 344 } 345 346 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) { 347 oops(pcm, errno, "cannot get info - %s"); 348 goto fail; 349 } 350 info_dump(&info); 351 352 LOGV("pcm_open() period_cnt %d period_sz %d channels %d", 353 period_cnt, period_sz, (flags & PCM_MONO) ? 1 : 2); 354 355 param_init(¶ms); 356 param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_ACCESS, 357 SNDRV_PCM_ACCESS_RW_INTERLEAVED); 358 param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_FORMAT, 359 SNDRV_PCM_FORMAT_S16_LE); 360 param_set_mask(¶ms, SNDRV_PCM_HW_PARAM_SUBFORMAT, 361 SNDRV_PCM_SUBFORMAT_STD); 362 param_set_min(¶ms, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, period_sz); 363 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16); 364 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_FRAME_BITS, 365 (flags & PCM_MONO) ? 16 : 32); 366 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_CHANNELS, 367 (flags & PCM_MONO) ? 1 : 2); 368 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_PERIODS, period_cnt); 369 param_set_int(¶ms, SNDRV_PCM_HW_PARAM_RATE, 44100); 370 371 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms)) { 372 oops(pcm, errno, "cannot set hw params"); 373 goto fail; 374 } 375 param_dump(¶ms); 376 377 memset(&sparams, 0, sizeof(sparams)); 378 sparams.tstamp_mode = SNDRV_PCM_TSTAMP_NONE; 379 sparams.period_step = 1; 380 sparams.avail_min = 1; 381 sparams.start_threshold = period_cnt * period_sz; 382 sparams.stop_threshold = period_cnt * period_sz; 383 sparams.xfer_align = period_sz / 2; /* needed for old kernels */ 384 sparams.silence_size = 0; 385 sparams.silence_threshold = 0; 386 387 if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) { 388 oops(pcm, errno, "cannot set sw params"); 389 goto fail; 390 } 391 392 pcm->buffer_size = period_cnt * period_sz; 393 pcm->underruns = 0; 394 return pcm; 395 396 fail: 397 close(pcm->fd); 398 pcm->fd = -1; 399 return pcm; 400 } 401 402 int pcm_ready(struct pcm *pcm) 403 { 404 return pcm->fd >= 0; 405 } 406