1 /* 2 * Digital Audio (PCM) abstract layer / OSS compatible 3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 4 * 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #if 0 23 #define PLUGIN_DEBUG 24 #endif 25 #if 0 26 #define OSS_DEBUG 27 #endif 28 29 #include <sound/driver.h> 30 #include <linux/init.h> 31 #include <linux/smp_lock.h> 32 #include <linux/slab.h> 33 #include <linux/time.h> 34 #include <linux/vmalloc.h> 35 #include <linux/moduleparam.h> 36 #include <linux/string.h> 37 #include <sound/core.h> 38 #include <sound/minors.h> 39 #include <sound/pcm.h> 40 #include <sound/pcm_params.h> 41 #include "pcm_plugin.h" 42 #include <sound/info.h> 43 #include <linux/soundcard.h> 44 #include <sound/initval.h> 45 46 #define OSS_ALSAEMULVER _SIOR ('M', 249, int) 47 48 static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; 49 static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; 50 static int nonblock_open = 1; 51 52 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-project.org>"); 53 MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); 54 MODULE_LICENSE("GPL"); 55 module_param_array(dsp_map, int, NULL, 0444); 56 MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device."); 57 module_param_array(adsp_map, int, NULL, 0444); 58 MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device."); 59 module_param(nonblock_open, bool, 0644); 60 MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices."); 61 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM); 62 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1); 63 64 extern int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg); 65 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); 66 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); 67 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); 68 69 static inline mm_segment_t snd_enter_user(void) 70 { 71 mm_segment_t fs = get_fs(); 72 set_fs(get_ds()); 73 return fs; 74 } 75 76 static inline void snd_leave_user(mm_segment_t fs) 77 { 78 set_fs(fs); 79 } 80 81 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 82 static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) 83 { 84 struct snd_pcm_runtime *runtime = substream->runtime; 85 struct snd_pcm_plugin *plugin, *next; 86 87 plugin = runtime->oss.plugin_first; 88 while (plugin) { 89 next = plugin->next; 90 snd_pcm_plugin_free(plugin); 91 plugin = next; 92 } 93 runtime->oss.plugin_first = runtime->oss.plugin_last = NULL; 94 return 0; 95 } 96 97 static int snd_pcm_plugin_insert(struct snd_pcm_plugin *plugin) 98 { 99 struct snd_pcm_runtime *runtime = plugin->plug->runtime; 100 plugin->next = runtime->oss.plugin_first; 101 plugin->prev = NULL; 102 if (runtime->oss.plugin_first) { 103 runtime->oss.plugin_first->prev = plugin; 104 runtime->oss.plugin_first = plugin; 105 } else { 106 runtime->oss.plugin_last = 107 runtime->oss.plugin_first = plugin; 108 } 109 return 0; 110 } 111 112 int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin) 113 { 114 struct snd_pcm_runtime *runtime = plugin->plug->runtime; 115 plugin->next = NULL; 116 plugin->prev = runtime->oss.plugin_last; 117 if (runtime->oss.plugin_last) { 118 runtime->oss.plugin_last->next = plugin; 119 runtime->oss.plugin_last = plugin; 120 } else { 121 runtime->oss.plugin_last = 122 runtime->oss.plugin_first = plugin; 123 } 124 return 0; 125 } 126 #endif /* CONFIG_SND_PCM_OSS_PLUGINS */ 127 128 static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) 129 { 130 struct snd_pcm_runtime *runtime = substream->runtime; 131 long buffer_size = snd_pcm_lib_buffer_bytes(substream); 132 long bytes = frames_to_bytes(runtime, frames); 133 if (buffer_size == runtime->oss.buffer_bytes) 134 return bytes; 135 #if BITS_PER_LONG >= 64 136 return runtime->oss.buffer_bytes * bytes / buffer_size; 137 #else 138 { 139 u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; 140 u32 rem; 141 div64_32(&bsize, buffer_size, &rem); 142 return (long)bsize; 143 } 144 #endif 145 } 146 147 static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes) 148 { 149 struct snd_pcm_runtime *runtime = substream->runtime; 150 long buffer_size = snd_pcm_lib_buffer_bytes(substream); 151 if (buffer_size == runtime->oss.buffer_bytes) 152 return bytes_to_frames(runtime, bytes); 153 return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); 154 } 155 156 static int snd_pcm_oss_format_from(int format) 157 { 158 switch (format) { 159 case AFMT_MU_LAW: return SNDRV_PCM_FORMAT_MU_LAW; 160 case AFMT_A_LAW: return SNDRV_PCM_FORMAT_A_LAW; 161 case AFMT_IMA_ADPCM: return SNDRV_PCM_FORMAT_IMA_ADPCM; 162 case AFMT_U8: return SNDRV_PCM_FORMAT_U8; 163 case AFMT_S16_LE: return SNDRV_PCM_FORMAT_S16_LE; 164 case AFMT_S16_BE: return SNDRV_PCM_FORMAT_S16_BE; 165 case AFMT_S8: return SNDRV_PCM_FORMAT_S8; 166 case AFMT_U16_LE: return SNDRV_PCM_FORMAT_U16_LE; 167 case AFMT_U16_BE: return SNDRV_PCM_FORMAT_U16_BE; 168 case AFMT_MPEG: return SNDRV_PCM_FORMAT_MPEG; 169 default: return SNDRV_PCM_FORMAT_U8; 170 } 171 } 172 173 static int snd_pcm_oss_format_to(int format) 174 { 175 switch (format) { 176 case SNDRV_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; 177 case SNDRV_PCM_FORMAT_A_LAW: return AFMT_A_LAW; 178 case SNDRV_PCM_FORMAT_IMA_ADPCM: return AFMT_IMA_ADPCM; 179 case SNDRV_PCM_FORMAT_U8: return AFMT_U8; 180 case SNDRV_PCM_FORMAT_S16_LE: return AFMT_S16_LE; 181 case SNDRV_PCM_FORMAT_S16_BE: return AFMT_S16_BE; 182 case SNDRV_PCM_FORMAT_S8: return AFMT_S8; 183 case SNDRV_PCM_FORMAT_U16_LE: return AFMT_U16_LE; 184 case SNDRV_PCM_FORMAT_U16_BE: return AFMT_U16_BE; 185 case SNDRV_PCM_FORMAT_MPEG: return AFMT_MPEG; 186 default: return -EINVAL; 187 } 188 } 189 190 static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, 191 struct snd_pcm_hw_params *oss_params, 192 struct snd_pcm_hw_params *slave_params) 193 { 194 size_t s; 195 size_t oss_buffer_size, oss_period_size, oss_periods; 196 size_t min_period_size, max_period_size; 197 struct snd_pcm_runtime *runtime = substream->runtime; 198 size_t oss_frame_size; 199 200 oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * 201 params_channels(oss_params) / 8; 202 203 oss_buffer_size = snd_pcm_plug_client_size(substream, 204 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; 205 oss_buffer_size = 1 << ld2(oss_buffer_size); 206 if (atomic_read(&runtime->mmap_count)) { 207 if (oss_buffer_size > runtime->oss.mmap_bytes) 208 oss_buffer_size = runtime->oss.mmap_bytes; 209 } 210 211 if (substream->oss.setup && 212 substream->oss.setup->period_size > 16) 213 oss_period_size = substream->oss.setup->period_size; 214 else if (runtime->oss.fragshift) { 215 oss_period_size = 1 << runtime->oss.fragshift; 216 if (oss_period_size > oss_buffer_size / 2) 217 oss_period_size = oss_buffer_size / 2; 218 } else { 219 int sd; 220 size_t bytes_per_sec = params_rate(oss_params) * snd_pcm_format_physical_width(params_format(oss_params)) * params_channels(oss_params) / 8; 221 222 oss_period_size = oss_buffer_size; 223 do { 224 oss_period_size /= 2; 225 } while (oss_period_size > bytes_per_sec); 226 if (runtime->oss.subdivision == 0) { 227 sd = 4; 228 if (oss_period_size / sd > 4096) 229 sd *= 2; 230 if (oss_period_size / sd < 4096) 231 sd = 1; 232 } else 233 sd = runtime->oss.subdivision; 234 oss_period_size /= sd; 235 if (oss_period_size < 16) 236 oss_period_size = 16; 237 } 238 239 min_period_size = snd_pcm_plug_client_size(substream, 240 snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); 241 min_period_size *= oss_frame_size; 242 min_period_size = 1 << (ld2(min_period_size - 1) + 1); 243 if (oss_period_size < min_period_size) 244 oss_period_size = min_period_size; 245 246 max_period_size = snd_pcm_plug_client_size(substream, 247 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); 248 max_period_size *= oss_frame_size; 249 max_period_size = 1 << ld2(max_period_size); 250 if (oss_period_size > max_period_size) 251 oss_period_size = max_period_size; 252 253 oss_periods = oss_buffer_size / oss_period_size; 254 255 if (substream->oss.setup) { 256 if (substream->oss.setup->periods > 1) 257 oss_periods = substream->oss.setup->periods; 258 } 259 260 s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); 261 if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) 262 s = runtime->oss.maxfrags; 263 if (oss_periods > s) 264 oss_periods = s; 265 266 s = snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); 267 if (s < 2) 268 s = 2; 269 if (oss_periods < s) 270 oss_periods = s; 271 272 while (oss_period_size * oss_periods > oss_buffer_size) 273 oss_period_size /= 2; 274 275 snd_assert(oss_period_size >= 16, return -EINVAL); 276 runtime->oss.period_bytes = oss_period_size; 277 runtime->oss.period_frames = 1; 278 runtime->oss.periods = oss_periods; 279 return 0; 280 } 281 282 static int choose_rate(struct snd_pcm_substream *substream, 283 struct snd_pcm_hw_params *params, unsigned int best_rate) 284 { 285 struct snd_interval *it; 286 struct snd_pcm_hw_params *save; 287 unsigned int rate, prev; 288 289 save = kmalloc(sizeof(*save), GFP_KERNEL); 290 if (save == NULL) 291 return -ENOMEM; 292 *save = *params; 293 it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE); 294 295 /* try multiples of the best rate */ 296 rate = best_rate; 297 for (;;) { 298 if (it->max < rate || (it->max == rate && it->openmax)) 299 break; 300 if (it->min < rate || (it->min == rate && !it->openmin)) { 301 int ret; 302 ret = snd_pcm_hw_param_set(substream, params, 303 SNDRV_PCM_HW_PARAM_RATE, 304 rate, 0); 305 if (ret == (int)rate) { 306 kfree(save); 307 return rate; 308 } 309 *params = *save; 310 } 311 prev = rate; 312 rate += best_rate; 313 if (rate <= prev) 314 break; 315 } 316 317 /* not found, use the nearest rate */ 318 kfree(save); 319 return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); 320 } 321 322 static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) 323 { 324 struct snd_pcm_runtime *runtime = substream->runtime; 325 struct snd_pcm_hw_params *params, *sparams; 326 struct snd_pcm_sw_params *sw_params; 327 ssize_t oss_buffer_size, oss_period_size; 328 size_t oss_frame_size; 329 int err; 330 int direct; 331 int format, sformat, n; 332 struct snd_mask sformat_mask; 333 struct snd_mask mask; 334 335 sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); 336 params = kmalloc(sizeof(*params), GFP_KERNEL); 337 sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); 338 if (!sw_params || !params || !sparams) { 339 snd_printd("No memory\n"); 340 err = -ENOMEM; 341 goto failure; 342 } 343 344 if (atomic_read(&runtime->mmap_count)) { 345 direct = 1; 346 } else { 347 struct snd_pcm_oss_setup *setup = substream->oss.setup; 348 direct = (setup != NULL && setup->direct); 349 } 350 351 _snd_pcm_hw_params_any(sparams); 352 _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); 353 _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); 354 snd_mask_none(&mask); 355 if (atomic_read(&runtime->mmap_count)) 356 snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); 357 else { 358 snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); 359 if (!direct) 360 snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); 361 } 362 err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask); 363 if (err < 0) { 364 snd_printd("No usable accesses\n"); 365 err = -EINVAL; 366 goto failure; 367 } 368 choose_rate(substream, sparams, runtime->oss.rate); 369 snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); 370 371 format = snd_pcm_oss_format_from(runtime->oss.format); 372 373 sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT); 374 if (direct) 375 sformat = format; 376 else 377 sformat = snd_pcm_plug_slave_format(format, &sformat_mask); 378 379 if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) { 380 for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) { 381 if (snd_mask_test(&sformat_mask, sformat) && 382 snd_pcm_oss_format_to(sformat) >= 0) 383 break; 384 } 385 if (sformat > SNDRV_PCM_FORMAT_LAST) { 386 snd_printd("Cannot find a format!!!\n"); 387 err = -EINVAL; 388 goto failure; 389 } 390 } 391 err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0); 392 snd_assert(err >= 0, goto failure); 393 394 if (direct) { 395 memcpy(params, sparams, sizeof(*params)); 396 } else { 397 _snd_pcm_hw_params_any(params); 398 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, 399 SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0); 400 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, 401 snd_pcm_oss_format_from(runtime->oss.format), 0); 402 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, 403 runtime->oss.channels, 0); 404 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, 405 runtime->oss.rate, 0); 406 pdprintf("client: access = %i, format = %i, channels = %i, rate = %i\n", 407 params_access(params), params_format(params), 408 params_channels(params), params_rate(params)); 409 } 410 pdprintf("slave: access = %i, format = %i, channels = %i, rate = %i\n", 411 params_access(sparams), params_format(sparams), 412 params_channels(sparams), params_rate(sparams)); 413 414 oss_frame_size = snd_pcm_format_physical_width(params_format(params)) * 415 params_channels(params) / 8; 416 417 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 418 snd_pcm_oss_plugin_clear(substream); 419 if (!direct) { 420 /* add necessary plugins */ 421 snd_pcm_oss_plugin_clear(substream); 422 if ((err = snd_pcm_plug_format_plugins(substream, 423 params, 424 sparams)) < 0) { 425 snd_printd("snd_pcm_plug_format_plugins failed: %i\n", err); 426 snd_pcm_oss_plugin_clear(substream); 427 goto failure; 428 } 429 if (runtime->oss.plugin_first) { 430 struct snd_pcm_plugin *plugin; 431 if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) { 432 snd_printd("snd_pcm_plugin_build_io failed: %i\n", err); 433 snd_pcm_oss_plugin_clear(substream); 434 goto failure; 435 } 436 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 437 err = snd_pcm_plugin_append(plugin); 438 } else { 439 err = snd_pcm_plugin_insert(plugin); 440 } 441 if (err < 0) { 442 snd_pcm_oss_plugin_clear(substream); 443 goto failure; 444 } 445 } 446 } 447 #endif 448 449 err = snd_pcm_oss_period_size(substream, params, sparams); 450 if (err < 0) 451 goto failure; 452 453 n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size); 454 err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL); 455 snd_assert(err >= 0, goto failure); 456 457 err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS, 458 runtime->oss.periods, NULL); 459 snd_assert(err >= 0, goto failure); 460 461 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 462 463 if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams)) < 0) { 464 snd_printd("HW_PARAMS failed: %i\n", err); 465 goto failure; 466 } 467 468 memset(sw_params, 0, sizeof(*sw_params)); 469 if (runtime->oss.trigger) { 470 sw_params->start_threshold = 1; 471 } else { 472 sw_params->start_threshold = runtime->boundary; 473 } 474 if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE) 475 sw_params->stop_threshold = runtime->boundary; 476 else 477 sw_params->stop_threshold = runtime->buffer_size; 478 sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; 479 sw_params->period_step = 1; 480 sw_params->sleep_min = 0; 481 sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 482 1 : runtime->period_size; 483 sw_params->xfer_align = 1; 484 if (atomic_read(&runtime->mmap_count) || 485 (substream->oss.setup && substream->oss.setup->nosilence)) { 486 sw_params->silence_threshold = 0; 487 sw_params->silence_size = 0; 488 } else { 489 snd_pcm_uframes_t frames; 490 frames = runtime->period_size + 16; 491 if (frames > runtime->buffer_size) 492 frames = runtime->buffer_size; 493 sw_params->silence_threshold = frames; 494 sw_params->silence_size = frames; 495 } 496 497 if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { 498 snd_printd("SW_PARAMS failed: %i\n", err); 499 goto failure; 500 } 501 502 runtime->oss.periods = params_periods(sparams); 503 oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams)); 504 snd_assert(oss_period_size >= 0, err = -EINVAL; goto failure); 505 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 506 if (runtime->oss.plugin_first) { 507 err = snd_pcm_plug_alloc(substream, oss_period_size); 508 if (err < 0) 509 goto failure; 510 } 511 #endif 512 oss_period_size *= oss_frame_size; 513 514 oss_buffer_size = oss_period_size * runtime->oss.periods; 515 snd_assert(oss_buffer_size >= 0, err = -EINVAL; goto failure); 516 517 runtime->oss.period_bytes = oss_period_size; 518 runtime->oss.buffer_bytes = oss_buffer_size; 519 520 pdprintf("oss: period bytes = %i, buffer bytes = %i\n", 521 runtime->oss.period_bytes, 522 runtime->oss.buffer_bytes); 523 pdprintf("slave: period_size = %i, buffer_size = %i\n", 524 params_period_size(sparams), 525 params_buffer_size(sparams)); 526 527 runtime->oss.format = snd_pcm_oss_format_to(params_format(params)); 528 runtime->oss.channels = params_channels(params); 529 runtime->oss.rate = params_rate(params); 530 531 runtime->oss.params = 0; 532 runtime->oss.prepare = 1; 533 vfree(runtime->oss.buffer); 534 runtime->oss.buffer = vmalloc(runtime->oss.period_bytes); 535 runtime->oss.buffer_used = 0; 536 if (runtime->dma_area) 537 snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes)); 538 539 runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size); 540 541 err = 0; 542 failure: 543 kfree(sw_params); 544 kfree(params); 545 kfree(sparams); 546 return err; 547 } 548 549 static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream) 550 { 551 int idx, err; 552 struct snd_pcm_substream *asubstream = NULL, *substream; 553 554 for (idx = 0; idx < 2; idx++) { 555 substream = pcm_oss_file->streams[idx]; 556 if (substream == NULL) 557 continue; 558 if (asubstream == NULL) 559 asubstream = substream; 560 if (substream->runtime->oss.params) { 561 err = snd_pcm_oss_change_params(substream); 562 if (err < 0) 563 return err; 564 } 565 } 566 snd_assert(asubstream != NULL, return -EIO); 567 if (r_substream) 568 *r_substream = asubstream; 569 return 0; 570 } 571 572 static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) 573 { 574 int err; 575 struct snd_pcm_runtime *runtime = substream->runtime; 576 577 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); 578 if (err < 0) { 579 snd_printd("snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n"); 580 return err; 581 } 582 runtime->oss.prepare = 0; 583 runtime->oss.prev_hw_ptr_interrupt = 0; 584 runtime->oss.period_ptr = 0; 585 runtime->oss.buffer_used = 0; 586 587 return 0; 588 } 589 590 static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream) 591 { 592 struct snd_pcm_runtime *runtime; 593 int err; 594 595 if (substream == NULL) 596 return 0; 597 runtime = substream->runtime; 598 if (runtime->oss.params) { 599 err = snd_pcm_oss_change_params(substream); 600 if (err < 0) 601 return err; 602 } 603 if (runtime->oss.prepare) { 604 err = snd_pcm_oss_prepare(substream); 605 if (err < 0) 606 return err; 607 } 608 return 0; 609 } 610 611 static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay) 612 { 613 struct snd_pcm_runtime *runtime; 614 snd_pcm_uframes_t frames; 615 int err = 0; 616 617 while (1) { 618 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay); 619 if (err < 0) 620 break; 621 runtime = substream->runtime; 622 if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size) 623 break; 624 /* in case of overrun, skip whole periods like OSS/Linux driver does */ 625 /* until avail(delay) <= buffer_size */ 626 frames = (*delay - runtime->buffer_size) + runtime->period_size - 1; 627 frames /= runtime->period_size; 628 frames *= runtime->period_size; 629 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames); 630 if (err < 0) 631 break; 632 } 633 return err; 634 } 635 636 snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel) 637 { 638 struct snd_pcm_runtime *runtime = substream->runtime; 639 int ret; 640 while (1) { 641 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 642 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 643 #ifdef OSS_DEBUG 644 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 645 printk("pcm_oss: write: recovering from XRUN\n"); 646 else 647 printk("pcm_oss: write: recovering from SUSPEND\n"); 648 #endif 649 ret = snd_pcm_oss_prepare(substream); 650 if (ret < 0) 651 break; 652 } 653 if (in_kernel) { 654 mm_segment_t fs; 655 fs = snd_enter_user(); 656 ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); 657 snd_leave_user(fs); 658 } else { 659 ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); 660 } 661 if (ret != -EPIPE && ret != -ESTRPIPE) 662 break; 663 /* test, if we can't store new data, because the stream */ 664 /* has not been started */ 665 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) 666 return -EAGAIN; 667 } 668 return ret; 669 } 670 671 snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel) 672 { 673 struct snd_pcm_runtime *runtime = substream->runtime; 674 snd_pcm_sframes_t delay; 675 int ret; 676 while (1) { 677 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 678 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 679 #ifdef OSS_DEBUG 680 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 681 printk("pcm_oss: read: recovering from XRUN\n"); 682 else 683 printk("pcm_oss: read: recovering from SUSPEND\n"); 684 #endif 685 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 686 if (ret < 0) 687 break; 688 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { 689 ret = snd_pcm_oss_prepare(substream); 690 if (ret < 0) 691 break; 692 } 693 ret = snd_pcm_oss_capture_position_fixup(substream, &delay); 694 if (ret < 0) 695 break; 696 if (in_kernel) { 697 mm_segment_t fs; 698 fs = snd_enter_user(); 699 ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); 700 snd_leave_user(fs); 701 } else { 702 ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); 703 } 704 if (ret == -EPIPE) { 705 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { 706 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 707 if (ret < 0) 708 break; 709 } 710 continue; 711 } 712 if (ret != -ESTRPIPE) 713 break; 714 } 715 return ret; 716 } 717 718 snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) 719 { 720 struct snd_pcm_runtime *runtime = substream->runtime; 721 int ret; 722 while (1) { 723 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 724 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 725 #ifdef OSS_DEBUG 726 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 727 printk("pcm_oss: writev: recovering from XRUN\n"); 728 else 729 printk("pcm_oss: writev: recovering from SUSPEND\n"); 730 #endif 731 ret = snd_pcm_oss_prepare(substream); 732 if (ret < 0) 733 break; 734 } 735 if (in_kernel) { 736 mm_segment_t fs; 737 fs = snd_enter_user(); 738 ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); 739 snd_leave_user(fs); 740 } else { 741 ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); 742 } 743 if (ret != -EPIPE && ret != -ESTRPIPE) 744 break; 745 746 /* test, if we can't store new data, because the stream */ 747 /* has not been started */ 748 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) 749 return -EAGAIN; 750 } 751 return ret; 752 } 753 754 snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) 755 { 756 struct snd_pcm_runtime *runtime = substream->runtime; 757 int ret; 758 while (1) { 759 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 760 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 761 #ifdef OSS_DEBUG 762 if (runtime->status->state == SNDRV_PCM_STATE_XRUN) 763 printk("pcm_oss: readv: recovering from XRUN\n"); 764 else 765 printk("pcm_oss: readv: recovering from SUSPEND\n"); 766 #endif 767 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 768 if (ret < 0) 769 break; 770 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { 771 ret = snd_pcm_oss_prepare(substream); 772 if (ret < 0) 773 break; 774 } 775 if (in_kernel) { 776 mm_segment_t fs; 777 fs = snd_enter_user(); 778 ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); 779 snd_leave_user(fs); 780 } else { 781 ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); 782 } 783 if (ret != -EPIPE && ret != -ESTRPIPE) 784 break; 785 } 786 return ret; 787 } 788 789 static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) 790 { 791 struct snd_pcm_runtime *runtime = substream->runtime; 792 snd_pcm_sframes_t frames, frames1; 793 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 794 if (runtime->oss.plugin_first) { 795 struct snd_pcm_plugin_channel *channels; 796 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; 797 if (!in_kernel) { 798 if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes)) 799 return -EFAULT; 800 buf = runtime->oss.buffer; 801 } 802 frames = bytes / oss_frame_bytes; 803 frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels); 804 if (frames1 < 0) 805 return frames1; 806 frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1); 807 if (frames1 <= 0) 808 return frames1; 809 bytes = frames1 * oss_frame_bytes; 810 } else 811 #endif 812 { 813 frames = bytes_to_frames(runtime, bytes); 814 frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel); 815 if (frames1 <= 0) 816 return frames1; 817 bytes = frames_to_bytes(runtime, frames1); 818 } 819 return bytes; 820 } 821 822 static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes) 823 { 824 size_t xfer = 0; 825 ssize_t tmp; 826 struct snd_pcm_runtime *runtime = substream->runtime; 827 828 if (atomic_read(&runtime->mmap_count)) 829 return -ENXIO; 830 831 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) 832 return tmp; 833 while (bytes > 0) { 834 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { 835 tmp = bytes; 836 if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) 837 tmp = runtime->oss.period_bytes - runtime->oss.buffer_used; 838 if (tmp > 0) { 839 if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) 840 return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT; 841 } 842 runtime->oss.buffer_used += tmp; 843 buf += tmp; 844 bytes -= tmp; 845 xfer += tmp; 846 if ((substream->oss.setup != NULL && substream->oss.setup->partialfrag) || 847 runtime->oss.buffer_used == runtime->oss.period_bytes) { 848 tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, 849 runtime->oss.buffer_used - runtime->oss.period_ptr, 1); 850 if (tmp <= 0) 851 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 852 runtime->oss.bytes += tmp; 853 runtime->oss.period_ptr += tmp; 854 runtime->oss.period_ptr %= runtime->oss.period_bytes; 855 if (runtime->oss.period_ptr == 0 || 856 runtime->oss.period_ptr == runtime->oss.buffer_used) 857 runtime->oss.buffer_used = 0; 858 else if ((substream->ffile->f_flags & O_NONBLOCK) != 0) 859 return xfer > 0 ? xfer : -EAGAIN; 860 } 861 } else { 862 tmp = snd_pcm_oss_write2(substream, 863 (const char __force *)buf, 864 runtime->oss.period_bytes, 0); 865 if (tmp <= 0) 866 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 867 runtime->oss.bytes += tmp; 868 buf += tmp; 869 bytes -= tmp; 870 xfer += tmp; 871 if ((substream->ffile->f_flags & O_NONBLOCK) != 0 && 872 tmp != runtime->oss.period_bytes) 873 break; 874 } 875 } 876 return xfer; 877 } 878 879 static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel) 880 { 881 struct snd_pcm_runtime *runtime = substream->runtime; 882 snd_pcm_sframes_t frames, frames1; 883 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 884 char __user *final_dst = (char __user *)buf; 885 if (runtime->oss.plugin_first) { 886 struct snd_pcm_plugin_channel *channels; 887 size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; 888 if (!in_kernel) 889 buf = runtime->oss.buffer; 890 frames = bytes / oss_frame_bytes; 891 frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels); 892 if (frames1 < 0) 893 return frames1; 894 frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1); 895 if (frames1 <= 0) 896 return frames1; 897 bytes = frames1 * oss_frame_bytes; 898 if (!in_kernel && copy_to_user(final_dst, buf, bytes)) 899 return -EFAULT; 900 } else 901 #endif 902 { 903 frames = bytes_to_frames(runtime, bytes); 904 frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel); 905 if (frames1 <= 0) 906 return frames1; 907 bytes = frames_to_bytes(runtime, frames1); 908 } 909 return bytes; 910 } 911 912 static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes) 913 { 914 size_t xfer = 0; 915 ssize_t tmp; 916 struct snd_pcm_runtime *runtime = substream->runtime; 917 918 if (atomic_read(&runtime->mmap_count)) 919 return -ENXIO; 920 921 if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) 922 return tmp; 923 while (bytes > 0) { 924 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { 925 if (runtime->oss.buffer_used == 0) { 926 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); 927 if (tmp <= 0) 928 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 929 runtime->oss.bytes += tmp; 930 runtime->oss.period_ptr = tmp; 931 runtime->oss.buffer_used = tmp; 932 } 933 tmp = bytes; 934 if ((size_t) tmp > runtime->oss.buffer_used) 935 tmp = runtime->oss.buffer_used; 936 if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) 937 return xfer > 0 ? (snd_pcm_sframes_t)xfer : -EFAULT; 938 buf += tmp; 939 bytes -= tmp; 940 xfer += tmp; 941 runtime->oss.buffer_used -= tmp; 942 } else { 943 tmp = snd_pcm_oss_read2(substream, (char __force *)buf, 944 runtime->oss.period_bytes, 0); 945 if (tmp <= 0) 946 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 947 runtime->oss.bytes += tmp; 948 buf += tmp; 949 bytes -= tmp; 950 xfer += tmp; 951 } 952 } 953 return xfer; 954 } 955 956 static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) 957 { 958 struct snd_pcm_substream *substream; 959 960 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 961 if (substream != NULL) { 962 snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 963 substream->runtime->oss.prepare = 1; 964 } 965 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 966 if (substream != NULL) { 967 snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 968 substream->runtime->oss.prepare = 1; 969 } 970 return 0; 971 } 972 973 static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) 974 { 975 struct snd_pcm_substream *substream; 976 int err; 977 978 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 979 if (substream != NULL) { 980 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 981 return err; 982 snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); 983 } 984 /* note: all errors from the start action are ignored */ 985 /* OSS apps do not know, how to handle them */ 986 return 0; 987 } 988 989 static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) 990 { 991 struct snd_pcm_runtime *runtime; 992 ssize_t result = 0; 993 long res; 994 wait_queue_t wait; 995 996 runtime = substream->runtime; 997 init_waitqueue_entry(&wait, current); 998 add_wait_queue(&runtime->sleep, &wait); 999 #ifdef OSS_DEBUG 1000 printk("sync1: size = %li\n", size); 1001 #endif 1002 while (1) { 1003 result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); 1004 if (result > 0) { 1005 runtime->oss.buffer_used = 0; 1006 result = 0; 1007 break; 1008 } 1009 if (result != 0 && result != -EAGAIN) 1010 break; 1011 result = 0; 1012 set_current_state(TASK_INTERRUPTIBLE); 1013 snd_pcm_stream_lock_irq(substream); 1014 res = runtime->status->state; 1015 snd_pcm_stream_unlock_irq(substream); 1016 if (res != SNDRV_PCM_STATE_RUNNING) { 1017 set_current_state(TASK_RUNNING); 1018 break; 1019 } 1020 res = schedule_timeout(10 * HZ); 1021 if (signal_pending(current)) { 1022 result = -ERESTARTSYS; 1023 break; 1024 } 1025 if (res == 0) { 1026 snd_printk(KERN_ERR "OSS sync error - DMA timeout\n"); 1027 result = -EIO; 1028 break; 1029 } 1030 } 1031 remove_wait_queue(&runtime->sleep, &wait); 1032 return result; 1033 } 1034 1035 static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) 1036 { 1037 int err = 0; 1038 unsigned int saved_f_flags; 1039 struct snd_pcm_substream *substream; 1040 struct snd_pcm_runtime *runtime; 1041 snd_pcm_format_t format; 1042 unsigned long width; 1043 size_t size; 1044 1045 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1046 if (substream != NULL) { 1047 runtime = substream->runtime; 1048 if (atomic_read(&runtime->mmap_count)) 1049 goto __direct; 1050 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1051 return err; 1052 format = snd_pcm_oss_format_from(runtime->oss.format); 1053 width = snd_pcm_format_physical_width(format); 1054 if (runtime->oss.buffer_used > 0) { 1055 #ifdef OSS_DEBUG 1056 printk("sync: buffer_used\n"); 1057 #endif 1058 size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; 1059 snd_pcm_format_set_silence(format, 1060 runtime->oss.buffer + runtime->oss.buffer_used, 1061 size); 1062 err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes); 1063 if (err < 0) 1064 return err; 1065 } else if (runtime->oss.period_ptr > 0) { 1066 #ifdef OSS_DEBUG 1067 printk("sync: period_ptr\n"); 1068 #endif 1069 size = runtime->oss.period_bytes - runtime->oss.period_ptr; 1070 snd_pcm_format_set_silence(format, 1071 runtime->oss.buffer, 1072 size * 8 / width); 1073 err = snd_pcm_oss_sync1(substream, size); 1074 if (err < 0) 1075 return err; 1076 } 1077 /* 1078 * The ALSA's period might be a bit large than OSS one. 1079 * Fill the remain portion of ALSA period with zeros. 1080 */ 1081 size = runtime->control->appl_ptr % runtime->period_size; 1082 if (size > 0) { 1083 size = runtime->period_size - size; 1084 if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { 1085 size = (runtime->frame_bits * size) / 8; 1086 while (size > 0) { 1087 mm_segment_t fs; 1088 size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; 1089 size -= size1; 1090 size1 *= 8; 1091 size1 /= runtime->sample_bits; 1092 snd_pcm_format_set_silence(runtime->format, 1093 runtime->oss.buffer, 1094 size1); 1095 fs = snd_enter_user(); 1096 snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1); 1097 snd_leave_user(fs); 1098 } 1099 } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { 1100 void __user *buffers[runtime->channels]; 1101 memset(buffers, 0, runtime->channels * sizeof(void *)); 1102 snd_pcm_lib_writev(substream, buffers, size); 1103 } 1104 } 1105 /* 1106 * finish sync: drain the buffer 1107 */ 1108 __direct: 1109 saved_f_flags = substream->ffile->f_flags; 1110 substream->ffile->f_flags &= ~O_NONBLOCK; 1111 err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 1112 substream->ffile->f_flags = saved_f_flags; 1113 if (err < 0) 1114 return err; 1115 runtime->oss.prepare = 1; 1116 } 1117 1118 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 1119 if (substream != NULL) { 1120 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1121 return err; 1122 runtime = substream->runtime; 1123 err = snd_pcm_kernel_capture_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 1124 if (err < 0) 1125 return err; 1126 runtime->oss.buffer_used = 0; 1127 runtime->oss.prepare = 1; 1128 } 1129 return 0; 1130 } 1131 1132 static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate) 1133 { 1134 int idx; 1135 1136 for (idx = 1; idx >= 0; --idx) { 1137 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1138 struct snd_pcm_runtime *runtime; 1139 if (substream == NULL) 1140 continue; 1141 runtime = substream->runtime; 1142 if (rate < 1000) 1143 rate = 1000; 1144 else if (rate > 192000) 1145 rate = 192000; 1146 if (runtime->oss.rate != rate) { 1147 runtime->oss.params = 1; 1148 runtime->oss.rate = rate; 1149 } 1150 } 1151 return snd_pcm_oss_get_rate(pcm_oss_file); 1152 } 1153 1154 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file) 1155 { 1156 struct snd_pcm_substream *substream; 1157 int err; 1158 1159 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1160 return err; 1161 return substream->runtime->oss.rate; 1162 } 1163 1164 static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels) 1165 { 1166 int idx; 1167 if (channels < 1) 1168 channels = 1; 1169 if (channels > 128) 1170 return -EINVAL; 1171 for (idx = 1; idx >= 0; --idx) { 1172 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1173 struct snd_pcm_runtime *runtime; 1174 if (substream == NULL) 1175 continue; 1176 runtime = substream->runtime; 1177 if (runtime->oss.channels != channels) { 1178 runtime->oss.params = 1; 1179 runtime->oss.channels = channels; 1180 } 1181 } 1182 return snd_pcm_oss_get_channels(pcm_oss_file); 1183 } 1184 1185 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file) 1186 { 1187 struct snd_pcm_substream *substream; 1188 int err; 1189 1190 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1191 return err; 1192 return substream->runtime->oss.channels; 1193 } 1194 1195 static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file) 1196 { 1197 struct snd_pcm_substream *substream; 1198 int err; 1199 1200 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1201 return err; 1202 return substream->runtime->oss.period_bytes; 1203 } 1204 1205 static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) 1206 { 1207 struct snd_pcm_substream *substream; 1208 int err; 1209 int direct; 1210 struct snd_pcm_hw_params *params; 1211 unsigned int formats = 0; 1212 struct snd_mask format_mask; 1213 int fmt; 1214 1215 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1216 return err; 1217 if (atomic_read(&substream->runtime->mmap_count)) { 1218 direct = 1; 1219 } else { 1220 struct snd_pcm_oss_setup *setup = substream->oss.setup; 1221 direct = (setup != NULL && setup->direct); 1222 } 1223 if (!direct) 1224 return AFMT_MU_LAW | AFMT_U8 | 1225 AFMT_S16_LE | AFMT_S16_BE | 1226 AFMT_S8 | AFMT_U16_LE | 1227 AFMT_U16_BE; 1228 params = kmalloc(sizeof(*params), GFP_KERNEL); 1229 if (!params) 1230 return -ENOMEM; 1231 _snd_pcm_hw_params_any(params); 1232 err = snd_pcm_hw_refine(substream, params); 1233 format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 1234 kfree(params); 1235 snd_assert(err >= 0, return err); 1236 for (fmt = 0; fmt < 32; ++fmt) { 1237 if (snd_mask_test(&format_mask, fmt)) { 1238 int f = snd_pcm_oss_format_to(fmt); 1239 if (f >= 0) 1240 formats |= f; 1241 } 1242 } 1243 return formats; 1244 } 1245 1246 static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) 1247 { 1248 int formats, idx; 1249 1250 if (format != AFMT_QUERY) { 1251 formats = snd_pcm_oss_get_formats(pcm_oss_file); 1252 if (!(formats & format)) 1253 format = AFMT_U8; 1254 for (idx = 1; idx >= 0; --idx) { 1255 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1256 struct snd_pcm_runtime *runtime; 1257 if (substream == NULL) 1258 continue; 1259 runtime = substream->runtime; 1260 if (runtime->oss.format != format) { 1261 runtime->oss.params = 1; 1262 runtime->oss.format = format; 1263 } 1264 } 1265 } 1266 return snd_pcm_oss_get_format(pcm_oss_file); 1267 } 1268 1269 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) 1270 { 1271 struct snd_pcm_substream *substream; 1272 int err; 1273 1274 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1275 return err; 1276 return substream->runtime->oss.format; 1277 } 1278 1279 static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide) 1280 { 1281 struct snd_pcm_runtime *runtime; 1282 1283 if (substream == NULL) 1284 return 0; 1285 runtime = substream->runtime; 1286 if (subdivide == 0) { 1287 subdivide = runtime->oss.subdivision; 1288 if (subdivide == 0) 1289 subdivide = 1; 1290 return subdivide; 1291 } 1292 if (runtime->oss.subdivision || runtime->oss.fragshift) 1293 return -EINVAL; 1294 if (subdivide != 1 && subdivide != 2 && subdivide != 4 && 1295 subdivide != 8 && subdivide != 16) 1296 return -EINVAL; 1297 runtime->oss.subdivision = subdivide; 1298 runtime->oss.params = 1; 1299 return subdivide; 1300 } 1301 1302 static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide) 1303 { 1304 int err = -EINVAL, idx; 1305 1306 for (idx = 1; idx >= 0; --idx) { 1307 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1308 if (substream == NULL) 1309 continue; 1310 if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0) 1311 return err; 1312 } 1313 return err; 1314 } 1315 1316 static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val) 1317 { 1318 struct snd_pcm_runtime *runtime; 1319 1320 if (substream == NULL) 1321 return 0; 1322 runtime = substream->runtime; 1323 if (runtime->oss.subdivision || runtime->oss.fragshift) 1324 return -EINVAL; 1325 runtime->oss.fragshift = val & 0xffff; 1326 runtime->oss.maxfrags = (val >> 16) & 0xffff; 1327 if (runtime->oss.fragshift < 4) /* < 16 */ 1328 runtime->oss.fragshift = 4; 1329 if (runtime->oss.maxfrags < 2) 1330 runtime->oss.maxfrags = 2; 1331 runtime->oss.params = 1; 1332 return 0; 1333 } 1334 1335 static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val) 1336 { 1337 int err = -EINVAL, idx; 1338 1339 for (idx = 1; idx >= 0; --idx) { 1340 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1341 if (substream == NULL) 1342 continue; 1343 if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0) 1344 return err; 1345 } 1346 return err; 1347 } 1348 1349 static int snd_pcm_oss_nonblock(struct file * file) 1350 { 1351 file->f_flags |= O_NONBLOCK; 1352 return 0; 1353 } 1354 1355 static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res) 1356 { 1357 1358 if (substream == NULL) { 1359 res &= ~DSP_CAP_DUPLEX; 1360 return res; 1361 } 1362 #ifdef DSP_CAP_MULTI 1363 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1364 if (substream->pstr->substream_count > 1) 1365 res |= DSP_CAP_MULTI; 1366 #endif 1367 /* DSP_CAP_REALTIME is set all times: */ 1368 /* all ALSA drivers can return actual pointer in ring buffer */ 1369 #if defined(DSP_CAP_REALTIME) && 0 1370 { 1371 struct snd_pcm_runtime *runtime = substream->runtime; 1372 if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH)) 1373 res &= ~DSP_CAP_REALTIME; 1374 } 1375 #endif 1376 return res; 1377 } 1378 1379 static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file) 1380 { 1381 int result, idx; 1382 1383 result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME; 1384 for (idx = 0; idx < 2; idx++) { 1385 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1386 result = snd_pcm_oss_get_caps1(substream, result); 1387 } 1388 result |= 0x0001; /* revision - same as SB AWE 64 */ 1389 return result; 1390 } 1391 1392 static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr) 1393 { 1394 struct snd_pcm_runtime *runtime = substream->runtime; 1395 snd_pcm_uframes_t appl_ptr; 1396 appl_ptr = hw_ptr + runtime->buffer_size; 1397 appl_ptr %= runtime->boundary; 1398 runtime->control->appl_ptr = appl_ptr; 1399 } 1400 1401 static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger) 1402 { 1403 struct snd_pcm_runtime *runtime; 1404 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 1405 int err, cmd; 1406 1407 #ifdef OSS_DEBUG 1408 printk("pcm_oss: trigger = 0x%x\n", trigger); 1409 #endif 1410 1411 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1412 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 1413 1414 if (psubstream) { 1415 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) 1416 return err; 1417 } 1418 if (csubstream) { 1419 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) 1420 return err; 1421 } 1422 if (psubstream) { 1423 runtime = psubstream->runtime; 1424 if (trigger & PCM_ENABLE_OUTPUT) { 1425 if (runtime->oss.trigger) 1426 goto _skip1; 1427 if (atomic_read(&psubstream->runtime->mmap_count)) 1428 snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); 1429 runtime->oss.trigger = 1; 1430 runtime->start_threshold = 1; 1431 cmd = SNDRV_PCM_IOCTL_START; 1432 } else { 1433 if (!runtime->oss.trigger) 1434 goto _skip1; 1435 runtime->oss.trigger = 0; 1436 runtime->start_threshold = runtime->boundary; 1437 cmd = SNDRV_PCM_IOCTL_DROP; 1438 runtime->oss.prepare = 1; 1439 } 1440 err = snd_pcm_kernel_playback_ioctl(psubstream, cmd, NULL); 1441 if (err < 0) 1442 return err; 1443 } 1444 _skip1: 1445 if (csubstream) { 1446 runtime = csubstream->runtime; 1447 if (trigger & PCM_ENABLE_INPUT) { 1448 if (runtime->oss.trigger) 1449 goto _skip2; 1450 runtime->oss.trigger = 1; 1451 runtime->start_threshold = 1; 1452 cmd = SNDRV_PCM_IOCTL_START; 1453 } else { 1454 if (!runtime->oss.trigger) 1455 goto _skip2; 1456 runtime->oss.trigger = 0; 1457 runtime->start_threshold = runtime->boundary; 1458 cmd = SNDRV_PCM_IOCTL_DROP; 1459 runtime->oss.prepare = 1; 1460 } 1461 err = snd_pcm_kernel_capture_ioctl(csubstream, cmd, NULL); 1462 if (err < 0) 1463 return err; 1464 } 1465 _skip2: 1466 return 0; 1467 } 1468 1469 static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file) 1470 { 1471 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 1472 int result = 0; 1473 1474 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1475 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 1476 if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger) 1477 result |= PCM_ENABLE_OUTPUT; 1478 if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger) 1479 result |= PCM_ENABLE_INPUT; 1480 return result; 1481 } 1482 1483 static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) 1484 { 1485 struct snd_pcm_substream *substream; 1486 struct snd_pcm_runtime *runtime; 1487 snd_pcm_sframes_t delay; 1488 int err; 1489 1490 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1491 if (substream == NULL) 1492 return -EINVAL; 1493 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1494 return err; 1495 runtime = substream->runtime; 1496 if (runtime->oss.params || runtime->oss.prepare) 1497 return 0; 1498 err = snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); 1499 if (err == -EPIPE) 1500 delay = 0; /* hack for broken OSS applications */ 1501 else if (err < 0) 1502 return err; 1503 return snd_pcm_oss_bytes(substream, delay); 1504 } 1505 1506 static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info) 1507 { 1508 struct snd_pcm_substream *substream; 1509 struct snd_pcm_runtime *runtime; 1510 snd_pcm_sframes_t delay; 1511 int fixup; 1512 struct count_info info; 1513 int err; 1514 1515 if (_info == NULL) 1516 return -EFAULT; 1517 substream = pcm_oss_file->streams[stream]; 1518 if (substream == NULL) 1519 return -EINVAL; 1520 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1521 return err; 1522 runtime = substream->runtime; 1523 if (runtime->oss.params || runtime->oss.prepare) { 1524 memset(&info, 0, sizeof(info)); 1525 if (copy_to_user(_info, &info, sizeof(info))) 1526 return -EFAULT; 1527 return 0; 1528 } 1529 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1530 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); 1531 if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) { 1532 err = 0; 1533 delay = 0; 1534 fixup = 0; 1535 } else { 1536 fixup = runtime->oss.buffer_used; 1537 } 1538 } else { 1539 err = snd_pcm_oss_capture_position_fixup(substream, &delay); 1540 fixup = -runtime->oss.buffer_used; 1541 } 1542 if (err < 0) 1543 return err; 1544 info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); 1545 if (atomic_read(&runtime->mmap_count)) { 1546 snd_pcm_sframes_t n; 1547 n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; 1548 if (n < 0) 1549 n += runtime->boundary; 1550 info.blocks = n / runtime->period_size; 1551 runtime->oss.prev_hw_ptr_interrupt = delay; 1552 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1553 snd_pcm_oss_simulate_fill(substream, delay); 1554 info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; 1555 } else { 1556 delay = snd_pcm_oss_bytes(substream, delay); 1557 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1558 struct snd_pcm_oss_setup *setup = substream->oss.setup; 1559 if (setup && setup->buggyptr) 1560 info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; 1561 else 1562 info.blocks = (delay + fixup) / runtime->oss.period_bytes; 1563 info.bytes = (runtime->oss.bytes - delay) & INT_MAX; 1564 } else { 1565 delay += fixup; 1566 info.blocks = delay / runtime->oss.period_bytes; 1567 info.bytes = (runtime->oss.bytes + delay) & INT_MAX; 1568 } 1569 } 1570 if (copy_to_user(_info, &info, sizeof(info))) 1571 return -EFAULT; 1572 return 0; 1573 } 1574 1575 static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info) 1576 { 1577 struct snd_pcm_substream *substream; 1578 struct snd_pcm_runtime *runtime; 1579 snd_pcm_sframes_t avail; 1580 int fixup; 1581 struct audio_buf_info info; 1582 int err; 1583 1584 if (_info == NULL) 1585 return -EFAULT; 1586 substream = pcm_oss_file->streams[stream]; 1587 if (substream == NULL) 1588 return -EINVAL; 1589 runtime = substream->runtime; 1590 1591 if (runtime->oss.params && 1592 (err = snd_pcm_oss_change_params(substream)) < 0) 1593 return err; 1594 1595 info.fragsize = runtime->oss.period_bytes; 1596 info.fragstotal = runtime->periods; 1597 if (runtime->oss.prepare) { 1598 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1599 info.bytes = runtime->oss.period_bytes * runtime->oss.periods; 1600 info.fragments = runtime->oss.periods; 1601 } else { 1602 info.bytes = 0; 1603 info.fragments = 0; 1604 } 1605 } else { 1606 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 1607 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail); 1608 if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) { 1609 avail = runtime->buffer_size; 1610 err = 0; 1611 fixup = 0; 1612 } else { 1613 avail = runtime->buffer_size - avail; 1614 fixup = -runtime->oss.buffer_used; 1615 } 1616 } else { 1617 err = snd_pcm_oss_capture_position_fixup(substream, &avail); 1618 fixup = runtime->oss.buffer_used; 1619 } 1620 if (err < 0) 1621 return err; 1622 info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup; 1623 info.fragments = info.bytes / runtime->oss.period_bytes; 1624 } 1625 1626 #ifdef OSS_DEBUG 1627 printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize); 1628 #endif 1629 if (copy_to_user(_info, &info, sizeof(info))) 1630 return -EFAULT; 1631 return 0; 1632 } 1633 1634 static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info) 1635 { 1636 // it won't be probably implemented 1637 // snd_printd("TODO: snd_pcm_oss_get_mapbuf\n"); 1638 return -EINVAL; 1639 } 1640 1641 static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name) 1642 { 1643 const char *ptr, *ptrl; 1644 struct snd_pcm_oss_setup *setup; 1645 1646 mutex_lock(&pcm->streams[stream].oss.setup_mutex); 1647 for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { 1648 if (!strcmp(setup->task_name, task_name)) { 1649 mutex_unlock(&pcm->streams[stream].oss.setup_mutex); 1650 return setup; 1651 } 1652 } 1653 ptr = ptrl = task_name; 1654 while (*ptr) { 1655 if (*ptr == '/') 1656 ptrl = ptr + 1; 1657 ptr++; 1658 } 1659 if (ptrl == task_name) { 1660 goto __not_found; 1661 return NULL; 1662 } 1663 for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) { 1664 if (!strcmp(setup->task_name, ptrl)) { 1665 mutex_unlock(&pcm->streams[stream].oss.setup_mutex); 1666 return setup; 1667 } 1668 } 1669 __not_found: 1670 mutex_unlock(&pcm->streams[stream].oss.setup_mutex); 1671 return NULL; 1672 } 1673 1674 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, 1675 struct snd_pcm_oss_setup *setup, 1676 int minor) 1677 { 1678 struct snd_pcm_runtime *runtime; 1679 1680 substream->oss.oss = 1; 1681 substream->oss.setup = setup; 1682 runtime = substream->runtime; 1683 runtime->oss.params = 1; 1684 runtime->oss.trigger = 1; 1685 runtime->oss.rate = 8000; 1686 switch (SNDRV_MINOR_OSS_DEVICE(minor)) { 1687 case SNDRV_MINOR_OSS_PCM_8: 1688 runtime->oss.format = AFMT_U8; 1689 break; 1690 case SNDRV_MINOR_OSS_PCM_16: 1691 runtime->oss.format = AFMT_S16_LE; 1692 break; 1693 default: 1694 runtime->oss.format = AFMT_MU_LAW; 1695 } 1696 runtime->oss.channels = 1; 1697 runtime->oss.fragshift = 0; 1698 runtime->oss.maxfrags = 0; 1699 runtime->oss.subdivision = 0; 1700 } 1701 1702 static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) 1703 { 1704 struct snd_pcm_runtime *runtime; 1705 runtime = substream->runtime; 1706 vfree(runtime->oss.buffer); 1707 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 1708 snd_pcm_oss_plugin_clear(substream); 1709 #endif 1710 substream->oss.file = NULL; 1711 substream->oss.oss = 0; 1712 } 1713 1714 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) 1715 { 1716 int cidx; 1717 snd_assert(pcm_oss_file != NULL, return -ENXIO); 1718 for (cidx = 0; cidx < 2; ++cidx) { 1719 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; 1720 struct snd_pcm_runtime *runtime; 1721 if (substream == NULL) 1722 continue; 1723 runtime = substream->runtime; 1724 1725 snd_pcm_stream_lock_irq(substream); 1726 if (snd_pcm_running(substream)) 1727 snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); 1728 snd_pcm_stream_unlock_irq(substream); 1729 if (substream->ffile != NULL) { 1730 if (substream->ops->hw_free != NULL) 1731 substream->ops->hw_free(substream); 1732 substream->ops->close(substream); 1733 substream->ffile = NULL; 1734 } 1735 snd_pcm_oss_release_substream(substream); 1736 snd_pcm_release_substream(substream); 1737 } 1738 kfree(pcm_oss_file); 1739 return 0; 1740 } 1741 1742 static int snd_pcm_oss_open_file(struct file *file, 1743 struct snd_pcm *pcm, 1744 struct snd_pcm_oss_file **rpcm_oss_file, 1745 int minor, 1746 struct snd_pcm_oss_setup *psetup, 1747 struct snd_pcm_oss_setup *csetup) 1748 { 1749 int err = 0; 1750 struct snd_pcm_oss_file *pcm_oss_file; 1751 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 1752 unsigned int f_mode = file->f_mode; 1753 1754 snd_assert(rpcm_oss_file != NULL, return -EINVAL); 1755 *rpcm_oss_file = NULL; 1756 1757 pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL); 1758 if (pcm_oss_file == NULL) 1759 return -ENOMEM; 1760 1761 if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && 1762 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) 1763 f_mode = FMODE_WRITE; 1764 if ((f_mode & FMODE_WRITE) && !(psetup && psetup->disable)) { 1765 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_PLAYBACK, 1766 &psubstream)) < 0) { 1767 snd_pcm_oss_release_file(pcm_oss_file); 1768 return err; 1769 } 1770 pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK] = psubstream; 1771 } 1772 if ((f_mode & FMODE_READ) && !(csetup && csetup->disable)) { 1773 if ((err = snd_pcm_open_substream(pcm, SNDRV_PCM_STREAM_CAPTURE, 1774 &csubstream)) < 0) { 1775 if (!(f_mode & FMODE_WRITE) || err != -ENODEV) { 1776 snd_pcm_oss_release_file(pcm_oss_file); 1777 return err; 1778 } else { 1779 csubstream = NULL; 1780 } 1781 } 1782 pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE] = csubstream; 1783 } 1784 1785 if (psubstream == NULL && csubstream == NULL) { 1786 snd_pcm_oss_release_file(pcm_oss_file); 1787 return -EINVAL; 1788 } 1789 if (psubstream != NULL) { 1790 psubstream->oss.file = pcm_oss_file; 1791 err = snd_pcm_hw_constraints_init(psubstream); 1792 if (err < 0) { 1793 snd_printd("snd_pcm_hw_constraint_init failed\n"); 1794 snd_pcm_oss_release_file(pcm_oss_file); 1795 return err; 1796 } 1797 if ((err = psubstream->ops->open(psubstream)) < 0) { 1798 snd_pcm_oss_release_file(pcm_oss_file); 1799 return err; 1800 } 1801 psubstream->ffile = file; 1802 err = snd_pcm_hw_constraints_complete(psubstream); 1803 if (err < 0) { 1804 snd_printd("snd_pcm_hw_constraint_complete failed\n"); 1805 snd_pcm_oss_release_file(pcm_oss_file); 1806 return err; 1807 } 1808 snd_pcm_oss_init_substream(psubstream, psetup, minor); 1809 } 1810 if (csubstream != NULL) { 1811 csubstream->oss.file = pcm_oss_file; 1812 err = snd_pcm_hw_constraints_init(csubstream); 1813 if (err < 0) { 1814 snd_printd("snd_pcm_hw_constraint_init failed\n"); 1815 snd_pcm_oss_release_file(pcm_oss_file); 1816 return err; 1817 } 1818 if ((err = csubstream->ops->open(csubstream)) < 0) { 1819 snd_pcm_oss_release_file(pcm_oss_file); 1820 return err; 1821 } 1822 csubstream->ffile = file; 1823 err = snd_pcm_hw_constraints_complete(csubstream); 1824 if (err < 0) { 1825 snd_printd("snd_pcm_hw_constraint_complete failed\n"); 1826 snd_pcm_oss_release_file(pcm_oss_file); 1827 return err; 1828 } 1829 snd_pcm_oss_init_substream(csubstream, csetup, minor); 1830 } 1831 1832 file->private_data = pcm_oss_file; 1833 *rpcm_oss_file = pcm_oss_file; 1834 return 0; 1835 } 1836 1837 1838 static int snd_task_name(struct task_struct *task, char *name, size_t size) 1839 { 1840 unsigned int idx; 1841 1842 snd_assert(task != NULL && name != NULL && size >= 2, return -EINVAL); 1843 for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) 1844 name[idx] = task->comm[idx]; 1845 name[idx] = '\0'; 1846 return 0; 1847 } 1848 1849 static int snd_pcm_oss_open(struct inode *inode, struct file *file) 1850 { 1851 int err; 1852 char task_name[32]; 1853 struct snd_pcm *pcm; 1854 struct snd_pcm_oss_file *pcm_oss_file; 1855 struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL; 1856 int nonblock; 1857 wait_queue_t wait; 1858 1859 pcm = snd_lookup_oss_minor_data(iminor(inode), 1860 SNDRV_OSS_DEVICE_TYPE_PCM); 1861 if (pcm == NULL) { 1862 err = -ENODEV; 1863 goto __error1; 1864 } 1865 err = snd_card_file_add(pcm->card, file); 1866 if (err < 0) 1867 goto __error1; 1868 if (!try_module_get(pcm->card->module)) { 1869 err = -EFAULT; 1870 goto __error2; 1871 } 1872 if (snd_task_name(current, task_name, sizeof(task_name)) < 0) { 1873 err = -EFAULT; 1874 goto __error; 1875 } 1876 if (file->f_mode & FMODE_WRITE) 1877 psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name); 1878 if (file->f_mode & FMODE_READ) 1879 csetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, task_name); 1880 1881 nonblock = !!(file->f_flags & O_NONBLOCK); 1882 if (psetup && !psetup->disable) { 1883 if (psetup->nonblock) 1884 nonblock = 1; 1885 else if (psetup->block) 1886 nonblock = 0; 1887 } else if (csetup && !csetup->disable) { 1888 if (csetup->nonblock) 1889 nonblock = 1; 1890 else if (csetup->block) 1891 nonblock = 0; 1892 } 1893 if (!nonblock) 1894 nonblock = nonblock_open; 1895 1896 init_waitqueue_entry(&wait, current); 1897 add_wait_queue(&pcm->open_wait, &wait); 1898 mutex_lock(&pcm->open_mutex); 1899 while (1) { 1900 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, 1901 iminor(inode), psetup, csetup); 1902 if (err >= 0) 1903 break; 1904 if (err == -EAGAIN) { 1905 if (nonblock) { 1906 err = -EBUSY; 1907 break; 1908 } 1909 } else 1910 break; 1911 set_current_state(TASK_INTERRUPTIBLE); 1912 mutex_unlock(&pcm->open_mutex); 1913 schedule(); 1914 mutex_lock(&pcm->open_mutex); 1915 if (signal_pending(current)) { 1916 err = -ERESTARTSYS; 1917 break; 1918 } 1919 } 1920 remove_wait_queue(&pcm->open_wait, &wait); 1921 mutex_unlock(&pcm->open_mutex); 1922 if (err < 0) 1923 goto __error; 1924 return err; 1925 1926 __error: 1927 module_put(pcm->card->module); 1928 __error2: 1929 snd_card_file_remove(pcm->card, file); 1930 __error1: 1931 return err; 1932 } 1933 1934 static int snd_pcm_oss_release(struct inode *inode, struct file *file) 1935 { 1936 struct snd_pcm *pcm; 1937 struct snd_pcm_substream *substream; 1938 struct snd_pcm_oss_file *pcm_oss_file; 1939 1940 pcm_oss_file = file->private_data; 1941 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1942 if (substream == NULL) 1943 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 1944 snd_assert(substream != NULL, return -ENXIO); 1945 pcm = substream->pcm; 1946 snd_pcm_oss_sync(pcm_oss_file); 1947 mutex_lock(&pcm->open_mutex); 1948 snd_pcm_oss_release_file(pcm_oss_file); 1949 mutex_unlock(&pcm->open_mutex); 1950 wake_up(&pcm->open_wait); 1951 module_put(pcm->card->module); 1952 snd_card_file_remove(pcm->card, file); 1953 return 0; 1954 } 1955 1956 static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1957 { 1958 struct snd_pcm_oss_file *pcm_oss_file; 1959 int __user *p = (int __user *)arg; 1960 int res; 1961 1962 pcm_oss_file = file->private_data; 1963 if (cmd == OSS_GETVERSION) 1964 return put_user(SNDRV_OSS_VERSION, p); 1965 if (cmd == OSS_ALSAEMULVER) 1966 return put_user(1, p); 1967 #if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE)) 1968 if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */ 1969 struct snd_pcm_substream *substream; 1970 int idx; 1971 for (idx = 0; idx < 2; ++idx) { 1972 substream = pcm_oss_file->streams[idx]; 1973 if (substream != NULL) 1974 break; 1975 } 1976 snd_assert(substream != NULL, return -ENXIO); 1977 return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg); 1978 } 1979 #endif 1980 if (((cmd >> 8) & 0xff) != 'P') 1981 return -EINVAL; 1982 #ifdef OSS_DEBUG 1983 printk("pcm_oss: ioctl = 0x%x\n", cmd); 1984 #endif 1985 switch (cmd) { 1986 case SNDCTL_DSP_RESET: 1987 return snd_pcm_oss_reset(pcm_oss_file); 1988 case SNDCTL_DSP_SYNC: 1989 return snd_pcm_oss_sync(pcm_oss_file); 1990 case SNDCTL_DSP_SPEED: 1991 if (get_user(res, p)) 1992 return -EFAULT; 1993 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0) 1994 return res; 1995 return put_user(res, p); 1996 case SOUND_PCM_READ_RATE: 1997 res = snd_pcm_oss_get_rate(pcm_oss_file); 1998 if (res < 0) 1999 return res; 2000 return put_user(res, p); 2001 case SNDCTL_DSP_STEREO: 2002 if (get_user(res, p)) 2003 return -EFAULT; 2004 res = res > 0 ? 2 : 1; 2005 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0) 2006 return res; 2007 return put_user(--res, p); 2008 case SNDCTL_DSP_GETBLKSIZE: 2009 res = snd_pcm_oss_get_block_size(pcm_oss_file); 2010 if (res < 0) 2011 return res; 2012 return put_user(res, p); 2013 case SNDCTL_DSP_SETFMT: 2014 if (get_user(res, p)) 2015 return -EFAULT; 2016 res = snd_pcm_oss_set_format(pcm_oss_file, res); 2017 if (res < 0) 2018 return res; 2019 return put_user(res, p); 2020 case SOUND_PCM_READ_BITS: 2021 res = snd_pcm_oss_get_format(pcm_oss_file); 2022 if (res < 0) 2023 return res; 2024 return put_user(res, p); 2025 case SNDCTL_DSP_CHANNELS: 2026 if (get_user(res, p)) 2027 return -EFAULT; 2028 res = snd_pcm_oss_set_channels(pcm_oss_file, res); 2029 if (res < 0) 2030 return res; 2031 return put_user(res, p); 2032 case SOUND_PCM_READ_CHANNELS: 2033 res = snd_pcm_oss_get_channels(pcm_oss_file); 2034 if (res < 0) 2035 return res; 2036 return put_user(res, p); 2037 case SOUND_PCM_WRITE_FILTER: 2038 case SOUND_PCM_READ_FILTER: 2039 return -EIO; 2040 case SNDCTL_DSP_POST: 2041 return snd_pcm_oss_post(pcm_oss_file); 2042 case SNDCTL_DSP_SUBDIVIDE: 2043 if (get_user(res, p)) 2044 return -EFAULT; 2045 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res); 2046 if (res < 0) 2047 return res; 2048 return put_user(res, p); 2049 case SNDCTL_DSP_SETFRAGMENT: 2050 if (get_user(res, p)) 2051 return -EFAULT; 2052 return snd_pcm_oss_set_fragment(pcm_oss_file, res); 2053 case SNDCTL_DSP_GETFMTS: 2054 res = snd_pcm_oss_get_formats(pcm_oss_file); 2055 if (res < 0) 2056 return res; 2057 return put_user(res, p); 2058 case SNDCTL_DSP_GETOSPACE: 2059 case SNDCTL_DSP_GETISPACE: 2060 return snd_pcm_oss_get_space(pcm_oss_file, 2061 cmd == SNDCTL_DSP_GETISPACE ? 2062 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2063 (struct audio_buf_info __user *) arg); 2064 case SNDCTL_DSP_NONBLOCK: 2065 return snd_pcm_oss_nonblock(file); 2066 case SNDCTL_DSP_GETCAPS: 2067 res = snd_pcm_oss_get_caps(pcm_oss_file); 2068 if (res < 0) 2069 return res; 2070 return put_user(res, p); 2071 case SNDCTL_DSP_GETTRIGGER: 2072 res = snd_pcm_oss_get_trigger(pcm_oss_file); 2073 if (res < 0) 2074 return res; 2075 return put_user(res, p); 2076 case SNDCTL_DSP_SETTRIGGER: 2077 if (get_user(res, p)) 2078 return -EFAULT; 2079 return snd_pcm_oss_set_trigger(pcm_oss_file, res); 2080 case SNDCTL_DSP_GETIPTR: 2081 case SNDCTL_DSP_GETOPTR: 2082 return snd_pcm_oss_get_ptr(pcm_oss_file, 2083 cmd == SNDCTL_DSP_GETIPTR ? 2084 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2085 (struct count_info __user *) arg); 2086 case SNDCTL_DSP_MAPINBUF: 2087 case SNDCTL_DSP_MAPOUTBUF: 2088 return snd_pcm_oss_get_mapbuf(pcm_oss_file, 2089 cmd == SNDCTL_DSP_MAPINBUF ? 2090 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2091 (struct buffmem_desc __user *) arg); 2092 case SNDCTL_DSP_SETSYNCRO: 2093 /* stop DMA now.. */ 2094 return 0; 2095 case SNDCTL_DSP_SETDUPLEX: 2096 if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX) 2097 return 0; 2098 return -EIO; 2099 case SNDCTL_DSP_GETODELAY: 2100 res = snd_pcm_oss_get_odelay(pcm_oss_file); 2101 if (res < 0) { 2102 /* it's for sure, some broken apps don't check for error codes */ 2103 put_user(0, p); 2104 return res; 2105 } 2106 return put_user(res, p); 2107 case SNDCTL_DSP_PROFILE: 2108 return 0; /* silently ignore */ 2109 default: 2110 snd_printd("pcm_oss: unknown command = 0x%x\n", cmd); 2111 } 2112 return -EINVAL; 2113 } 2114 2115 #ifdef CONFIG_COMPAT 2116 /* all compatible */ 2117 #define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl 2118 #else 2119 #define snd_pcm_oss_ioctl_compat NULL 2120 #endif 2121 2122 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 2123 { 2124 struct snd_pcm_oss_file *pcm_oss_file; 2125 struct snd_pcm_substream *substream; 2126 2127 pcm_oss_file = file->private_data; 2128 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2129 if (substream == NULL) 2130 return -ENXIO; 2131 #ifndef OSS_DEBUG 2132 return snd_pcm_oss_read1(substream, buf, count); 2133 #else 2134 { 2135 ssize_t res = snd_pcm_oss_read1(substream, buf, count); 2136 printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res); 2137 return res; 2138 } 2139 #endif 2140 } 2141 2142 static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) 2143 { 2144 struct snd_pcm_oss_file *pcm_oss_file; 2145 struct snd_pcm_substream *substream; 2146 long result; 2147 2148 pcm_oss_file = file->private_data; 2149 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2150 if (substream == NULL) 2151 return -ENXIO; 2152 result = snd_pcm_oss_write1(substream, buf, count); 2153 #ifdef OSS_DEBUG 2154 printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); 2155 #endif 2156 return result; 2157 } 2158 2159 static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) 2160 { 2161 struct snd_pcm_runtime *runtime = substream->runtime; 2162 if (atomic_read(&runtime->mmap_count)) 2163 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; 2164 else 2165 return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; 2166 } 2167 2168 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) 2169 { 2170 struct snd_pcm_runtime *runtime = substream->runtime; 2171 if (atomic_read(&runtime->mmap_count)) 2172 return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; 2173 else 2174 return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; 2175 } 2176 2177 static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait) 2178 { 2179 struct snd_pcm_oss_file *pcm_oss_file; 2180 unsigned int mask; 2181 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 2182 2183 pcm_oss_file = file->private_data; 2184 2185 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2186 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2187 2188 mask = 0; 2189 if (psubstream != NULL) { 2190 struct snd_pcm_runtime *runtime = psubstream->runtime; 2191 poll_wait(file, &runtime->sleep, wait); 2192 snd_pcm_stream_lock_irq(psubstream); 2193 if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && 2194 (runtime->status->state != SNDRV_PCM_STATE_RUNNING || 2195 snd_pcm_oss_playback_ready(psubstream))) 2196 mask |= POLLOUT | POLLWRNORM; 2197 snd_pcm_stream_unlock_irq(psubstream); 2198 } 2199 if (csubstream != NULL) { 2200 struct snd_pcm_runtime *runtime = csubstream->runtime; 2201 snd_pcm_state_t ostate; 2202 poll_wait(file, &runtime->sleep, wait); 2203 snd_pcm_stream_lock_irq(csubstream); 2204 if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || 2205 snd_pcm_oss_capture_ready(csubstream)) 2206 mask |= POLLIN | POLLRDNORM; 2207 snd_pcm_stream_unlock_irq(csubstream); 2208 if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) { 2209 struct snd_pcm_oss_file ofile; 2210 memset(&ofile, 0, sizeof(ofile)); 2211 ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2212 runtime->oss.trigger = 0; 2213 snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT); 2214 } 2215 } 2216 2217 return mask; 2218 } 2219 2220 static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) 2221 { 2222 struct snd_pcm_oss_file *pcm_oss_file; 2223 struct snd_pcm_substream *substream = NULL; 2224 struct snd_pcm_runtime *runtime; 2225 int err; 2226 2227 #ifdef OSS_DEBUG 2228 printk("pcm_oss: mmap begin\n"); 2229 #endif 2230 pcm_oss_file = file->private_data; 2231 switch ((area->vm_flags & (VM_READ | VM_WRITE))) { 2232 case VM_READ | VM_WRITE: 2233 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2234 if (substream) 2235 break; 2236 /* Fall through */ 2237 case VM_READ: 2238 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2239 break; 2240 case VM_WRITE: 2241 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2242 break; 2243 default: 2244 return -EINVAL; 2245 } 2246 /* set VM_READ access as well to fix memset() routines that do 2247 reads before writes (to improve performance) */ 2248 area->vm_flags |= VM_READ; 2249 if (substream == NULL) 2250 return -ENXIO; 2251 runtime = substream->runtime; 2252 if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID)) 2253 return -EIO; 2254 if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED) 2255 runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; 2256 else 2257 return -EIO; 2258 2259 if (runtime->oss.params) { 2260 if ((err = snd_pcm_oss_change_params(substream)) < 0) 2261 return err; 2262 } 2263 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 2264 if (runtime->oss.plugin_first != NULL) 2265 return -EIO; 2266 #endif 2267 2268 if (area->vm_pgoff != 0) 2269 return -EINVAL; 2270 2271 err = snd_pcm_mmap_data(substream, file, area); 2272 if (err < 0) 2273 return err; 2274 runtime->oss.mmap_bytes = area->vm_end - area->vm_start; 2275 runtime->silence_threshold = 0; 2276 runtime->silence_size = 0; 2277 #ifdef OSS_DEBUG 2278 printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes); 2279 #endif 2280 /* In mmap mode we never stop */ 2281 runtime->stop_threshold = runtime->boundary; 2282 2283 return 0; 2284 } 2285 2286 #ifdef CONFIG_PROC_FS 2287 /* 2288 * /proc interface 2289 */ 2290 2291 static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, 2292 struct snd_info_buffer *buffer) 2293 { 2294 struct snd_pcm_str *pstr = entry->private_data; 2295 struct snd_pcm_oss_setup *setup = pstr->oss.setup_list; 2296 mutex_lock(&pstr->oss.setup_mutex); 2297 while (setup) { 2298 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", 2299 setup->task_name, 2300 setup->periods, 2301 setup->period_size, 2302 setup->disable ? " disable" : "", 2303 setup->direct ? " direct" : "", 2304 setup->block ? " block" : "", 2305 setup->nonblock ? " non-block" : "", 2306 setup->partialfrag ? " partial-frag" : "", 2307 setup->nosilence ? " no-silence" : ""); 2308 setup = setup->next; 2309 } 2310 mutex_unlock(&pstr->oss.setup_mutex); 2311 } 2312 2313 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) 2314 { 2315 unsigned int idx; 2316 struct snd_pcm_substream *substream; 2317 struct snd_pcm_oss_setup *setup, *setupn; 2318 2319 for (idx = 0, substream = pstr->substream; 2320 idx < pstr->substream_count; idx++, substream = substream->next) 2321 substream->oss.setup = NULL; 2322 for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; 2323 setup; setup = setupn) { 2324 setupn = setup->next; 2325 kfree(setup->task_name); 2326 kfree(setup); 2327 } 2328 pstr->oss.setup_list = NULL; 2329 } 2330 2331 static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, 2332 struct snd_info_buffer *buffer) 2333 { 2334 struct snd_pcm_str *pstr = entry->private_data; 2335 char line[128], str[32], task_name[32], *ptr; 2336 int idx1; 2337 struct snd_pcm_oss_setup *setup, *setup1, template; 2338 2339 while (!snd_info_get_line(buffer, line, sizeof(line))) { 2340 mutex_lock(&pstr->oss.setup_mutex); 2341 memset(&template, 0, sizeof(template)); 2342 ptr = snd_info_get_str(task_name, line, sizeof(task_name)); 2343 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) { 2344 snd_pcm_oss_proc_free_setup_list(pstr); 2345 mutex_unlock(&pstr->oss.setup_mutex); 2346 continue; 2347 } 2348 for (setup = pstr->oss.setup_list; setup; setup = setup->next) { 2349 if (!strcmp(setup->task_name, task_name)) { 2350 template = *setup; 2351 break; 2352 } 2353 } 2354 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2355 template.periods = simple_strtoul(str, NULL, 10); 2356 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2357 template.period_size = simple_strtoul(str, NULL, 10); 2358 for (idx1 = 31; idx1 >= 0; idx1--) 2359 if (template.period_size & (1 << idx1)) 2360 break; 2361 for (idx1--; idx1 >= 0; idx1--) 2362 template.period_size &= ~(1 << idx1); 2363 do { 2364 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2365 if (!strcmp(str, "disable")) { 2366 template.disable = 1; 2367 } else if (!strcmp(str, "direct")) { 2368 template.direct = 1; 2369 } else if (!strcmp(str, "block")) { 2370 template.block = 1; 2371 } else if (!strcmp(str, "non-block")) { 2372 template.nonblock = 1; 2373 } else if (!strcmp(str, "partial-frag")) { 2374 template.partialfrag = 1; 2375 } else if (!strcmp(str, "no-silence")) { 2376 template.nosilence = 1; 2377 } else if (!strcmp(str, "buggy-ptr")) { 2378 template.buggyptr = 1; 2379 } 2380 } while (*str); 2381 if (setup == NULL) { 2382 setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL); 2383 if (setup) { 2384 if (pstr->oss.setup_list == NULL) { 2385 pstr->oss.setup_list = setup; 2386 } else { 2387 for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next); 2388 setup1->next = setup; 2389 } 2390 template.task_name = kstrdup(task_name, GFP_KERNEL); 2391 } else { 2392 buffer->error = -ENOMEM; 2393 } 2394 } 2395 if (setup) 2396 *setup = template; 2397 mutex_unlock(&pstr->oss.setup_mutex); 2398 } 2399 } 2400 2401 static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) 2402 { 2403 int stream; 2404 for (stream = 0; stream < 2; ++stream) { 2405 struct snd_info_entry *entry; 2406 struct snd_pcm_str *pstr = &pcm->streams[stream]; 2407 if (pstr->substream_count == 0) 2408 continue; 2409 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { 2410 entry->content = SNDRV_INFO_CONTENT_TEXT; 2411 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 2412 entry->c.text.read_size = 8192; 2413 entry->c.text.read = snd_pcm_oss_proc_read; 2414 entry->c.text.write_size = 8192; 2415 entry->c.text.write = snd_pcm_oss_proc_write; 2416 entry->private_data = pstr; 2417 if (snd_info_register(entry) < 0) { 2418 snd_info_free_entry(entry); 2419 entry = NULL; 2420 } 2421 } 2422 pstr->oss.proc_entry = entry; 2423 } 2424 } 2425 2426 static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) 2427 { 2428 int stream; 2429 for (stream = 0; stream < 2; ++stream) { 2430 struct snd_pcm_str *pstr = &pcm->streams[stream]; 2431 if (pstr->oss.proc_entry) { 2432 snd_info_unregister(pstr->oss.proc_entry); 2433 pstr->oss.proc_entry = NULL; 2434 snd_pcm_oss_proc_free_setup_list(pstr); 2435 } 2436 } 2437 } 2438 #else /* !CONFIG_PROC_FS */ 2439 #define snd_pcm_oss_proc_init(pcm) 2440 #define snd_pcm_oss_proc_done(pcm) 2441 #endif /* CONFIG_PROC_FS */ 2442 2443 /* 2444 * ENTRY functions 2445 */ 2446 2447 static struct file_operations snd_pcm_oss_f_reg = 2448 { 2449 .owner = THIS_MODULE, 2450 .read = snd_pcm_oss_read, 2451 .write = snd_pcm_oss_write, 2452 .open = snd_pcm_oss_open, 2453 .release = snd_pcm_oss_release, 2454 .poll = snd_pcm_oss_poll, 2455 .unlocked_ioctl = snd_pcm_oss_ioctl, 2456 .compat_ioctl = snd_pcm_oss_ioctl_compat, 2457 .mmap = snd_pcm_oss_mmap, 2458 }; 2459 2460 static void register_oss_dsp(struct snd_pcm *pcm, int index) 2461 { 2462 char name[128]; 2463 sprintf(name, "dsp%i%i", pcm->card->number, pcm->device); 2464 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 2465 pcm->card, index, &snd_pcm_oss_f_reg, 2466 pcm, name) < 0) { 2467 snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", 2468 pcm->card->number, pcm->device); 2469 } 2470 } 2471 2472 static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) 2473 { 2474 pcm->oss.reg = 0; 2475 if (dsp_map[pcm->card->number] == (int)pcm->device) { 2476 char name[128]; 2477 int duplex; 2478 register_oss_dsp(pcm, 0); 2479 duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 2480 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 2481 !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)); 2482 sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : ""); 2483 #ifdef SNDRV_OSS_INFO_DEV_AUDIO 2484 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO, 2485 pcm->card->number, 2486 name); 2487 #endif 2488 pcm->oss.reg++; 2489 pcm->oss.reg_mask |= 1; 2490 } 2491 if (adsp_map[pcm->card->number] == (int)pcm->device) { 2492 register_oss_dsp(pcm, 1); 2493 pcm->oss.reg++; 2494 pcm->oss.reg_mask |= 2; 2495 } 2496 2497 if (pcm->oss.reg) 2498 snd_pcm_oss_proc_init(pcm); 2499 2500 return 0; 2501 } 2502 2503 static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) 2504 { 2505 if (pcm->oss.reg) { 2506 if (pcm->oss.reg_mask & 1) { 2507 pcm->oss.reg_mask &= ~1; 2508 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 2509 pcm->card, 0); 2510 } 2511 if (pcm->oss.reg_mask & 2) { 2512 pcm->oss.reg_mask &= ~2; 2513 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 2514 pcm->card, 1); 2515 } 2516 } 2517 return 0; 2518 } 2519 2520 static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) 2521 { 2522 snd_pcm_oss_disconnect_minor(pcm); 2523 if (pcm->oss.reg) { 2524 if (dsp_map[pcm->card->number] == (int)pcm->device) { 2525 #ifdef SNDRV_OSS_INFO_DEV_AUDIO 2526 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); 2527 #endif 2528 } 2529 pcm->oss.reg = 0; 2530 snd_pcm_oss_proc_done(pcm); 2531 } 2532 return 0; 2533 } 2534 2535 static struct snd_pcm_notify snd_pcm_oss_notify = 2536 { 2537 .n_register = snd_pcm_oss_register_minor, 2538 .n_disconnect = snd_pcm_oss_disconnect_minor, 2539 .n_unregister = snd_pcm_oss_unregister_minor, 2540 }; 2541 2542 static int __init alsa_pcm_oss_init(void) 2543 { 2544 int i; 2545 int err; 2546 2547 /* check device map table */ 2548 for (i = 0; i < SNDRV_CARDS; i++) { 2549 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { 2550 snd_printk(KERN_ERR "invalid dsp_map[%d] = %d\n", 2551 i, dsp_map[i]); 2552 dsp_map[i] = 0; 2553 } 2554 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { 2555 snd_printk(KERN_ERR "invalid adsp_map[%d] = %d\n", 2556 i, adsp_map[i]); 2557 adsp_map[i] = 1; 2558 } 2559 } 2560 if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0) 2561 return err; 2562 return 0; 2563 } 2564 2565 static void __exit alsa_pcm_oss_exit(void) 2566 { 2567 snd_pcm_notify(&snd_pcm_oss_notify, 1); 2568 } 2569 2570 module_init(alsa_pcm_oss_init) 2571 module_exit(alsa_pcm_oss_exit) 2572