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