1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Digital Audio (PCM) abstract layer / OSS compatible 4 * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 5 */ 6 7 #if 0 8 #define PLUGIN_DEBUG 9 #endif 10 #if 0 11 #define OSS_DEBUG 12 #endif 13 14 #include <linux/init.h> 15 #include <linux/slab.h> 16 #include <linux/sched/signal.h> 17 #include <linux/time.h> 18 #include <linux/vmalloc.h> 19 #include <linux/module.h> 20 #include <linux/math64.h> 21 #include <linux/string.h> 22 #include <linux/compat.h> 23 #include <sound/core.h> 24 #include <sound/minors.h> 25 #include <sound/pcm.h> 26 #include <sound/pcm_params.h> 27 #include "pcm_plugin.h" 28 #include <sound/info.h> 29 #include <linux/soundcard.h> 30 #include <sound/initval.h> 31 #include <sound/mixer_oss.h> 32 33 #define OSS_ALSAEMULVER _SIOR ('M', 249, int) 34 35 static int dsp_map[SNDRV_CARDS]; 36 static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; 37 static bool nonblock_open = 1; 38 39 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); 40 MODULE_DESCRIPTION("PCM OSS emulation for ALSA."); 41 MODULE_LICENSE("GPL"); 42 module_param_array(dsp_map, int, NULL, 0444); 43 MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device."); 44 module_param_array(adsp_map, int, NULL, 0444); 45 MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device."); 46 module_param(nonblock_open, bool, 0644); 47 MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices."); 48 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM); 49 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1); 50 51 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); 52 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); 53 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); 54 55 /* 56 * helper functions to process hw_params 57 */ 58 static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin) 59 { 60 int changed = 0; 61 if (i->min < min) { 62 i->min = min; 63 i->openmin = openmin; 64 changed = 1; 65 } else if (i->min == min && !i->openmin && openmin) { 66 i->openmin = 1; 67 changed = 1; 68 } 69 if (i->integer) { 70 if (i->openmin) { 71 i->min++; 72 i->openmin = 0; 73 } 74 } 75 if (snd_interval_checkempty(i)) { 76 snd_interval_none(i); 77 return -EINVAL; 78 } 79 return changed; 80 } 81 82 static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax) 83 { 84 int changed = 0; 85 if (i->max > max) { 86 i->max = max; 87 i->openmax = openmax; 88 changed = 1; 89 } else if (i->max == max && !i->openmax && openmax) { 90 i->openmax = 1; 91 changed = 1; 92 } 93 if (i->integer) { 94 if (i->openmax) { 95 i->max--; 96 i->openmax = 0; 97 } 98 } 99 if (snd_interval_checkempty(i)) { 100 snd_interval_none(i); 101 return -EINVAL; 102 } 103 return changed; 104 } 105 106 static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) 107 { 108 struct snd_interval t; 109 t.empty = 0; 110 t.min = t.max = val; 111 t.openmin = t.openmax = 0; 112 t.integer = 1; 113 return snd_interval_refine(i, &t); 114 } 115 116 /** 117 * snd_pcm_hw_param_value_min 118 * @params: the hw_params instance 119 * @var: parameter to retrieve 120 * @dir: pointer to the direction (-1,0,1) or NULL 121 * 122 * Return the minimum value for field PAR. 123 */ 124 static unsigned int 125 snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, 126 snd_pcm_hw_param_t var, int *dir) 127 { 128 if (hw_is_mask(var)) { 129 if (dir) 130 *dir = 0; 131 return snd_mask_min(hw_param_mask_c(params, var)); 132 } 133 if (hw_is_interval(var)) { 134 const struct snd_interval *i = hw_param_interval_c(params, var); 135 if (dir) 136 *dir = i->openmin; 137 return snd_interval_min(i); 138 } 139 return -EINVAL; 140 } 141 142 /** 143 * snd_pcm_hw_param_value_max 144 * @params: the hw_params instance 145 * @var: parameter to retrieve 146 * @dir: pointer to the direction (-1,0,1) or NULL 147 * 148 * Return the maximum value for field PAR. 149 */ 150 static unsigned int 151 snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, 152 snd_pcm_hw_param_t var, int *dir) 153 { 154 if (hw_is_mask(var)) { 155 if (dir) 156 *dir = 0; 157 return snd_mask_max(hw_param_mask_c(params, var)); 158 } 159 if (hw_is_interval(var)) { 160 const struct snd_interval *i = hw_param_interval_c(params, var); 161 if (dir) 162 *dir = - (int) i->openmax; 163 return snd_interval_max(i); 164 } 165 return -EINVAL; 166 } 167 168 static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params, 169 snd_pcm_hw_param_t var, 170 const struct snd_mask *val) 171 { 172 int changed; 173 changed = snd_mask_refine(hw_param_mask(params, var), val); 174 if (changed > 0) { 175 params->cmask |= 1 << var; 176 params->rmask |= 1 << var; 177 } 178 return changed; 179 } 180 181 static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, 182 struct snd_pcm_hw_params *params, 183 snd_pcm_hw_param_t var, 184 const struct snd_mask *val) 185 { 186 int changed = _snd_pcm_hw_param_mask(params, var, val); 187 if (changed < 0) 188 return changed; 189 if (params->rmask) { 190 int err = snd_pcm_hw_refine(pcm, params); 191 if (err < 0) 192 return err; 193 } 194 return 0; 195 } 196 197 static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, 198 snd_pcm_hw_param_t var, unsigned int val, 199 int dir) 200 { 201 int changed; 202 int open = 0; 203 if (dir) { 204 if (dir > 0) { 205 open = 1; 206 } else if (dir < 0) { 207 if (val > 0) { 208 open = 1; 209 val--; 210 } 211 } 212 } 213 if (hw_is_mask(var)) 214 changed = snd_mask_refine_min(hw_param_mask(params, var), 215 val + !!open); 216 else if (hw_is_interval(var)) 217 changed = snd_interval_refine_min(hw_param_interval(params, var), 218 val, open); 219 else 220 return -EINVAL; 221 if (changed > 0) { 222 params->cmask |= 1 << var; 223 params->rmask |= 1 << var; 224 } 225 return changed; 226 } 227 228 /** 229 * snd_pcm_hw_param_min 230 * @pcm: PCM instance 231 * @params: the hw_params instance 232 * @var: parameter to retrieve 233 * @val: minimal value 234 * @dir: pointer to the direction (-1,0,1) or NULL 235 * 236 * Inside configuration space defined by PARAMS remove from PAR all 237 * values < VAL. Reduce configuration space accordingly. 238 * Return new minimum or -EINVAL if the configuration space is empty 239 */ 240 static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, 241 struct snd_pcm_hw_params *params, 242 snd_pcm_hw_param_t var, unsigned int val, 243 int *dir) 244 { 245 int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); 246 if (changed < 0) 247 return changed; 248 if (params->rmask) { 249 int err = snd_pcm_hw_refine(pcm, params); 250 if (err < 0) 251 return err; 252 } 253 return snd_pcm_hw_param_value_min(params, var, dir); 254 } 255 256 static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params, 257 snd_pcm_hw_param_t var, unsigned int val, 258 int dir) 259 { 260 int changed; 261 int open = 0; 262 if (dir) { 263 if (dir < 0) { 264 open = 1; 265 } else if (dir > 0) { 266 open = 1; 267 val++; 268 } 269 } 270 if (hw_is_mask(var)) { 271 if (val == 0 && open) { 272 snd_mask_none(hw_param_mask(params, var)); 273 changed = -EINVAL; 274 } else 275 changed = snd_mask_refine_max(hw_param_mask(params, var), 276 val - !!open); 277 } else if (hw_is_interval(var)) 278 changed = snd_interval_refine_max(hw_param_interval(params, var), 279 val, open); 280 else 281 return -EINVAL; 282 if (changed > 0) { 283 params->cmask |= 1 << var; 284 params->rmask |= 1 << var; 285 } 286 return changed; 287 } 288 289 /** 290 * snd_pcm_hw_param_max 291 * @pcm: PCM instance 292 * @params: the hw_params instance 293 * @var: parameter to retrieve 294 * @val: maximal value 295 * @dir: pointer to the direction (-1,0,1) or NULL 296 * 297 * Inside configuration space defined by PARAMS remove from PAR all 298 * values >= VAL + 1. Reduce configuration space accordingly. 299 * Return new maximum or -EINVAL if the configuration space is empty 300 */ 301 static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, 302 struct snd_pcm_hw_params *params, 303 snd_pcm_hw_param_t var, unsigned int val, 304 int *dir) 305 { 306 int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); 307 if (changed < 0) 308 return changed; 309 if (params->rmask) { 310 int err = snd_pcm_hw_refine(pcm, params); 311 if (err < 0) 312 return err; 313 } 314 return snd_pcm_hw_param_value_max(params, var, dir); 315 } 316 317 static int boundary_sub(int a, int adir, 318 int b, int bdir, 319 int *c, int *cdir) 320 { 321 adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0); 322 bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0); 323 *c = a - b; 324 *cdir = adir - bdir; 325 if (*cdir == -2) { 326 (*c)--; 327 } else if (*cdir == 2) { 328 (*c)++; 329 } 330 return 0; 331 } 332 333 static int boundary_lt(unsigned int a, int adir, 334 unsigned int b, int bdir) 335 { 336 if (adir < 0) { 337 a--; 338 adir = 1; 339 } else if (adir > 0) 340 adir = 1; 341 if (bdir < 0) { 342 b--; 343 bdir = 1; 344 } else if (bdir > 0) 345 bdir = 1; 346 return a < b || (a == b && adir < bdir); 347 } 348 349 /* Return 1 if min is nearer to best than max */ 350 static int boundary_nearer(int min, int mindir, 351 int best, int bestdir, 352 int max, int maxdir) 353 { 354 int dmin, dmindir; 355 int dmax, dmaxdir; 356 boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir); 357 boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir); 358 return boundary_lt(dmin, dmindir, dmax, dmaxdir); 359 } 360 361 /** 362 * snd_pcm_hw_param_near 363 * @pcm: PCM instance 364 * @params: the hw_params instance 365 * @var: parameter to retrieve 366 * @best: value to set 367 * @dir: pointer to the direction (-1,0,1) or NULL 368 * 369 * Inside configuration space defined by PARAMS set PAR to the available value 370 * nearest to VAL. Reduce configuration space accordingly. 371 * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS, 372 * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. 373 * Return the value found. 374 */ 375 static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, 376 struct snd_pcm_hw_params *params, 377 snd_pcm_hw_param_t var, unsigned int best, 378 int *dir) 379 { 380 struct snd_pcm_hw_params *save = NULL; 381 int v; 382 unsigned int saved_min; 383 int last = 0; 384 int min, max; 385 int mindir, maxdir; 386 int valdir = dir ? *dir : 0; 387 /* FIXME */ 388 if (best > INT_MAX) 389 best = INT_MAX; 390 min = max = best; 391 mindir = maxdir = valdir; 392 if (maxdir > 0) 393 maxdir = 0; 394 else if (maxdir == 0) 395 maxdir = -1; 396 else { 397 maxdir = 1; 398 max--; 399 } 400 save = kmalloc(sizeof(*save), GFP_KERNEL); 401 if (save == NULL) 402 return -ENOMEM; 403 *save = *params; 404 saved_min = min; 405 min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir); 406 if (min >= 0) { 407 struct snd_pcm_hw_params *params1; 408 if (max < 0) 409 goto _end; 410 if ((unsigned int)min == saved_min && mindir == valdir) 411 goto _end; 412 params1 = kmalloc(sizeof(*params1), GFP_KERNEL); 413 if (params1 == NULL) { 414 kfree(save); 415 return -ENOMEM; 416 } 417 *params1 = *save; 418 max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir); 419 if (max < 0) { 420 kfree(params1); 421 goto _end; 422 } 423 if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) { 424 *params = *params1; 425 last = 1; 426 } 427 kfree(params1); 428 } else { 429 *params = *save; 430 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); 431 if (max < 0) { 432 kfree(save); 433 return max; 434 } 435 last = 1; 436 } 437 _end: 438 kfree(save); 439 if (last) 440 v = snd_pcm_hw_param_last(pcm, params, var, dir); 441 else 442 v = snd_pcm_hw_param_first(pcm, params, var, dir); 443 return v; 444 } 445 446 static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, 447 snd_pcm_hw_param_t var, unsigned int val, 448 int dir) 449 { 450 int changed; 451 if (hw_is_mask(var)) { 452 struct snd_mask *m = hw_param_mask(params, var); 453 if (val == 0 && dir < 0) { 454 changed = -EINVAL; 455 snd_mask_none(m); 456 } else { 457 if (dir > 0) 458 val++; 459 else if (dir < 0) 460 val--; 461 changed = snd_mask_refine_set(hw_param_mask(params, var), val); 462 } 463 } else if (hw_is_interval(var)) { 464 struct snd_interval *i = hw_param_interval(params, var); 465 if (val == 0 && dir < 0) { 466 changed = -EINVAL; 467 snd_interval_none(i); 468 } else if (dir == 0) 469 changed = snd_interval_refine_set(i, val); 470 else { 471 struct snd_interval t; 472 t.openmin = 1; 473 t.openmax = 1; 474 t.empty = 0; 475 t.integer = 0; 476 if (dir < 0) { 477 t.min = val - 1; 478 t.max = val; 479 } else { 480 t.min = val; 481 t.max = val+1; 482 } 483 changed = snd_interval_refine(i, &t); 484 } 485 } else 486 return -EINVAL; 487 if (changed > 0) { 488 params->cmask |= 1 << var; 489 params->rmask |= 1 << var; 490 } 491 return changed; 492 } 493 494 /** 495 * snd_pcm_hw_param_set 496 * @pcm: PCM instance 497 * @params: the hw_params instance 498 * @var: parameter to retrieve 499 * @val: value to set 500 * @dir: pointer to the direction (-1,0,1) or NULL 501 * 502 * Inside configuration space defined by PARAMS remove from PAR all 503 * values != VAL. Reduce configuration space accordingly. 504 * Return VAL or -EINVAL if the configuration space is empty 505 */ 506 static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, 507 struct snd_pcm_hw_params *params, 508 snd_pcm_hw_param_t var, unsigned int val, 509 int dir) 510 { 511 int changed = _snd_pcm_hw_param_set(params, var, val, dir); 512 if (changed < 0) 513 return changed; 514 if (params->rmask) { 515 int err = snd_pcm_hw_refine(pcm, params); 516 if (err < 0) 517 return err; 518 } 519 return snd_pcm_hw_param_value(params, var, NULL); 520 } 521 522 static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, 523 snd_pcm_hw_param_t var) 524 { 525 int changed; 526 changed = snd_interval_setinteger(hw_param_interval(params, var)); 527 if (changed > 0) { 528 params->cmask |= 1 << var; 529 params->rmask |= 1 << var; 530 } 531 return changed; 532 } 533 534 /* 535 * plugin 536 */ 537 538 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 539 static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) 540 { 541 struct snd_pcm_runtime *runtime = substream->runtime; 542 struct snd_pcm_plugin *plugin, *next; 543 544 plugin = runtime->oss.plugin_first; 545 while (plugin) { 546 next = plugin->next; 547 snd_pcm_plugin_free(plugin); 548 plugin = next; 549 } 550 runtime->oss.plugin_first = runtime->oss.plugin_last = NULL; 551 return 0; 552 } 553 554 static int snd_pcm_plugin_insert(struct snd_pcm_plugin *plugin) 555 { 556 struct snd_pcm_runtime *runtime = plugin->plug->runtime; 557 plugin->next = runtime->oss.plugin_first; 558 plugin->prev = NULL; 559 if (runtime->oss.plugin_first) { 560 runtime->oss.plugin_first->prev = plugin; 561 runtime->oss.plugin_first = plugin; 562 } else { 563 runtime->oss.plugin_last = 564 runtime->oss.plugin_first = plugin; 565 } 566 return 0; 567 } 568 569 int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin) 570 { 571 struct snd_pcm_runtime *runtime = plugin->plug->runtime; 572 plugin->next = NULL; 573 plugin->prev = runtime->oss.plugin_last; 574 if (runtime->oss.plugin_last) { 575 runtime->oss.plugin_last->next = plugin; 576 runtime->oss.plugin_last = plugin; 577 } else { 578 runtime->oss.plugin_last = 579 runtime->oss.plugin_first = plugin; 580 } 581 return 0; 582 } 583 #endif /* CONFIG_SND_PCM_OSS_PLUGINS */ 584 585 static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) 586 { 587 struct snd_pcm_runtime *runtime = substream->runtime; 588 long buffer_size = snd_pcm_lib_buffer_bytes(substream); 589 long bytes = frames_to_bytes(runtime, frames); 590 if (buffer_size == runtime->oss.buffer_bytes) 591 return bytes; 592 #if BITS_PER_LONG >= 64 593 return runtime->oss.buffer_bytes * bytes / buffer_size; 594 #else 595 { 596 u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; 597 return div_u64(bsize, buffer_size); 598 } 599 #endif 600 } 601 602 static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes) 603 { 604 struct snd_pcm_runtime *runtime = substream->runtime; 605 long buffer_size = snd_pcm_lib_buffer_bytes(substream); 606 if (buffer_size == runtime->oss.buffer_bytes) 607 return bytes_to_frames(runtime, bytes); 608 return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes); 609 } 610 611 static inline 612 snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime) 613 { 614 return runtime->hw_ptr_interrupt; 615 } 616 617 /* define extended formats in the recent OSS versions (if any) */ 618 /* linear formats */ 619 #define AFMT_S32_LE 0x00001000 620 #define AFMT_S32_BE 0x00002000 621 #define AFMT_S24_LE 0x00008000 622 #define AFMT_S24_BE 0x00010000 623 #define AFMT_S24_PACKED 0x00040000 624 625 /* other supported formats */ 626 #define AFMT_FLOAT 0x00004000 627 #define AFMT_SPDIF_RAW 0x00020000 628 629 /* unsupported formats */ 630 #define AFMT_AC3 0x00000400 631 #define AFMT_VORBIS 0x00000800 632 633 static snd_pcm_format_t snd_pcm_oss_format_from(int format) 634 { 635 switch (format) { 636 case AFMT_MU_LAW: return SNDRV_PCM_FORMAT_MU_LAW; 637 case AFMT_A_LAW: return SNDRV_PCM_FORMAT_A_LAW; 638 case AFMT_IMA_ADPCM: return SNDRV_PCM_FORMAT_IMA_ADPCM; 639 case AFMT_U8: return SNDRV_PCM_FORMAT_U8; 640 case AFMT_S16_LE: return SNDRV_PCM_FORMAT_S16_LE; 641 case AFMT_S16_BE: return SNDRV_PCM_FORMAT_S16_BE; 642 case AFMT_S8: return SNDRV_PCM_FORMAT_S8; 643 case AFMT_U16_LE: return SNDRV_PCM_FORMAT_U16_LE; 644 case AFMT_U16_BE: return SNDRV_PCM_FORMAT_U16_BE; 645 case AFMT_MPEG: return SNDRV_PCM_FORMAT_MPEG; 646 case AFMT_S32_LE: return SNDRV_PCM_FORMAT_S32_LE; 647 case AFMT_S32_BE: return SNDRV_PCM_FORMAT_S32_BE; 648 case AFMT_S24_LE: return SNDRV_PCM_FORMAT_S24_LE; 649 case AFMT_S24_BE: return SNDRV_PCM_FORMAT_S24_BE; 650 case AFMT_S24_PACKED: return SNDRV_PCM_FORMAT_S24_3LE; 651 case AFMT_FLOAT: return SNDRV_PCM_FORMAT_FLOAT; 652 case AFMT_SPDIF_RAW: return SNDRV_PCM_FORMAT_IEC958_SUBFRAME; 653 default: return SNDRV_PCM_FORMAT_U8; 654 } 655 } 656 657 static int snd_pcm_oss_format_to(snd_pcm_format_t format) 658 { 659 switch (format) { 660 case SNDRV_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; 661 case SNDRV_PCM_FORMAT_A_LAW: return AFMT_A_LAW; 662 case SNDRV_PCM_FORMAT_IMA_ADPCM: return AFMT_IMA_ADPCM; 663 case SNDRV_PCM_FORMAT_U8: return AFMT_U8; 664 case SNDRV_PCM_FORMAT_S16_LE: return AFMT_S16_LE; 665 case SNDRV_PCM_FORMAT_S16_BE: return AFMT_S16_BE; 666 case SNDRV_PCM_FORMAT_S8: return AFMT_S8; 667 case SNDRV_PCM_FORMAT_U16_LE: return AFMT_U16_LE; 668 case SNDRV_PCM_FORMAT_U16_BE: return AFMT_U16_BE; 669 case SNDRV_PCM_FORMAT_MPEG: return AFMT_MPEG; 670 case SNDRV_PCM_FORMAT_S32_LE: return AFMT_S32_LE; 671 case SNDRV_PCM_FORMAT_S32_BE: return AFMT_S32_BE; 672 case SNDRV_PCM_FORMAT_S24_LE: return AFMT_S24_LE; 673 case SNDRV_PCM_FORMAT_S24_BE: return AFMT_S24_BE; 674 case SNDRV_PCM_FORMAT_S24_3LE: return AFMT_S24_PACKED; 675 case SNDRV_PCM_FORMAT_FLOAT: return AFMT_FLOAT; 676 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME: return AFMT_SPDIF_RAW; 677 default: return -EINVAL; 678 } 679 } 680 681 static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, 682 struct snd_pcm_hw_params *oss_params, 683 struct snd_pcm_hw_params *slave_params) 684 { 685 size_t s; 686 size_t oss_buffer_size, oss_period_size, oss_periods; 687 size_t min_period_size, max_period_size; 688 struct snd_pcm_runtime *runtime = substream->runtime; 689 size_t oss_frame_size; 690 691 oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * 692 params_channels(oss_params) / 8; 693 694 oss_buffer_size = snd_pcm_plug_client_size(substream, 695 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; 696 if (!oss_buffer_size) 697 return -EINVAL; 698 oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); 699 if (atomic_read(&substream->mmap_count)) { 700 if (oss_buffer_size > runtime->oss.mmap_bytes) 701 oss_buffer_size = runtime->oss.mmap_bytes; 702 } 703 704 if (substream->oss.setup.period_size > 16) 705 oss_period_size = substream->oss.setup.period_size; 706 else if (runtime->oss.fragshift) { 707 oss_period_size = 1 << runtime->oss.fragshift; 708 if (oss_period_size > oss_buffer_size / 2) 709 oss_period_size = oss_buffer_size / 2; 710 } else { 711 int sd; 712 size_t bytes_per_sec = params_rate(oss_params) * snd_pcm_format_physical_width(params_format(oss_params)) * params_channels(oss_params) / 8; 713 714 oss_period_size = oss_buffer_size; 715 do { 716 oss_period_size /= 2; 717 } while (oss_period_size > bytes_per_sec); 718 if (runtime->oss.subdivision == 0) { 719 sd = 4; 720 if (oss_period_size / sd > 4096) 721 sd *= 2; 722 if (oss_period_size / sd < 4096) 723 sd = 1; 724 } else 725 sd = runtime->oss.subdivision; 726 oss_period_size /= sd; 727 if (oss_period_size < 16) 728 oss_period_size = 16; 729 } 730 731 min_period_size = snd_pcm_plug_client_size(substream, 732 snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); 733 if (min_period_size) { 734 min_period_size *= oss_frame_size; 735 min_period_size = roundup_pow_of_two(min_period_size); 736 if (oss_period_size < min_period_size) 737 oss_period_size = min_period_size; 738 } 739 740 max_period_size = snd_pcm_plug_client_size(substream, 741 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); 742 if (max_period_size) { 743 max_period_size *= oss_frame_size; 744 max_period_size = rounddown_pow_of_two(max_period_size); 745 if (oss_period_size > max_period_size) 746 oss_period_size = max_period_size; 747 } 748 749 oss_periods = oss_buffer_size / oss_period_size; 750 751 if (substream->oss.setup.periods > 1) 752 oss_periods = substream->oss.setup.periods; 753 754 s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); 755 if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) 756 s = runtime->oss.maxfrags; 757 if (oss_periods > s) 758 oss_periods = s; 759 760 s = snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); 761 if (s < 2) 762 s = 2; 763 if (oss_periods < s) 764 oss_periods = s; 765 766 while (oss_period_size * oss_periods > oss_buffer_size) 767 oss_period_size /= 2; 768 769 if (oss_period_size < 16) 770 return -EINVAL; 771 runtime->oss.period_bytes = oss_period_size; 772 runtime->oss.period_frames = 1; 773 runtime->oss.periods = oss_periods; 774 return 0; 775 } 776 777 static int choose_rate(struct snd_pcm_substream *substream, 778 struct snd_pcm_hw_params *params, unsigned int best_rate) 779 { 780 const struct snd_interval *it; 781 struct snd_pcm_hw_params *save; 782 unsigned int rate, prev; 783 784 save = kmalloc(sizeof(*save), GFP_KERNEL); 785 if (save == NULL) 786 return -ENOMEM; 787 *save = *params; 788 it = hw_param_interval_c(save, SNDRV_PCM_HW_PARAM_RATE); 789 790 /* try multiples of the best rate */ 791 rate = best_rate; 792 for (;;) { 793 if (it->max < rate || (it->max == rate && it->openmax)) 794 break; 795 if (it->min < rate || (it->min == rate && !it->openmin)) { 796 int ret; 797 ret = snd_pcm_hw_param_set(substream, params, 798 SNDRV_PCM_HW_PARAM_RATE, 799 rate, 0); 800 if (ret == (int)rate) { 801 kfree(save); 802 return rate; 803 } 804 *params = *save; 805 } 806 prev = rate; 807 rate += best_rate; 808 if (rate <= prev) 809 break; 810 } 811 812 /* not found, use the nearest rate */ 813 kfree(save); 814 return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); 815 } 816 817 /* parameter locking: returns immediately if tried during streaming */ 818 static int lock_params(struct snd_pcm_runtime *runtime) 819 { 820 if (mutex_lock_interruptible(&runtime->oss.params_lock)) 821 return -ERESTARTSYS; 822 if (atomic_read(&runtime->oss.rw_ref)) { 823 mutex_unlock(&runtime->oss.params_lock); 824 return -EBUSY; 825 } 826 return 0; 827 } 828 829 static void unlock_params(struct snd_pcm_runtime *runtime) 830 { 831 mutex_unlock(&runtime->oss.params_lock); 832 } 833 834 /* call with params_lock held */ 835 static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) 836 { 837 struct snd_pcm_runtime *runtime = substream->runtime; 838 struct snd_pcm_hw_params *params, *sparams; 839 struct snd_pcm_sw_params *sw_params; 840 ssize_t oss_buffer_size, oss_period_size; 841 size_t oss_frame_size; 842 int err; 843 int direct; 844 snd_pcm_format_t format, sformat; 845 int n; 846 const struct snd_mask *sformat_mask; 847 struct snd_mask mask; 848 849 if (!runtime->oss.params) 850 return 0; 851 sw_params = kzalloc(sizeof(*sw_params), GFP_KERNEL); 852 params = kmalloc(sizeof(*params), GFP_KERNEL); 853 sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); 854 if (!sw_params || !params || !sparams) { 855 err = -ENOMEM; 856 goto failure; 857 } 858 859 if (atomic_read(&substream->mmap_count)) 860 direct = 1; 861 else 862 direct = substream->oss.setup.direct; 863 864 _snd_pcm_hw_params_any(sparams); 865 _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); 866 _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); 867 snd_mask_none(&mask); 868 if (atomic_read(&substream->mmap_count)) 869 snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); 870 else { 871 snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED); 872 if (!direct) 873 snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); 874 } 875 err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask); 876 if (err < 0) { 877 pcm_dbg(substream->pcm, "No usable accesses\n"); 878 err = -EINVAL; 879 goto failure; 880 } 881 choose_rate(substream, sparams, runtime->oss.rate); 882 snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); 883 884 format = snd_pcm_oss_format_from(runtime->oss.format); 885 886 sformat_mask = hw_param_mask_c(sparams, SNDRV_PCM_HW_PARAM_FORMAT); 887 if (direct) 888 sformat = format; 889 else 890 sformat = snd_pcm_plug_slave_format(format, sformat_mask); 891 892 if ((__force int)sformat < 0 || 893 !snd_mask_test_format(sformat_mask, sformat)) { 894 pcm_for_each_format(sformat) { 895 if (snd_mask_test_format(sformat_mask, sformat) && 896 snd_pcm_oss_format_to(sformat) >= 0) 897 goto format_found; 898 } 899 pcm_dbg(substream->pcm, "Cannot find a format!!!\n"); 900 err = -EINVAL; 901 goto failure; 902 } 903 format_found: 904 err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0); 905 if (err < 0) 906 goto failure; 907 908 if (direct) { 909 memcpy(params, sparams, sizeof(*params)); 910 } else { 911 _snd_pcm_hw_params_any(params); 912 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, 913 (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0); 914 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, 915 (__force int)snd_pcm_oss_format_from(runtime->oss.format), 0); 916 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, 917 runtime->oss.channels, 0); 918 _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, 919 runtime->oss.rate, 0); 920 pdprintf("client: access = %i, format = %i, channels = %i, rate = %i\n", 921 params_access(params), params_format(params), 922 params_channels(params), params_rate(params)); 923 } 924 pdprintf("slave: access = %i, format = %i, channels = %i, rate = %i\n", 925 params_access(sparams), params_format(sparams), 926 params_channels(sparams), params_rate(sparams)); 927 928 oss_frame_size = snd_pcm_format_physical_width(params_format(params)) * 929 params_channels(params) / 8; 930 931 err = snd_pcm_oss_period_size(substream, params, sparams); 932 if (err < 0) 933 goto failure; 934 935 n = snd_pcm_plug_slave_size(substream, runtime->oss.period_bytes / oss_frame_size); 936 err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, n, NULL); 937 if (err < 0) 938 goto failure; 939 940 err = snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_PERIODS, 941 runtime->oss.periods, NULL); 942 if (err < 0) 943 goto failure; 944 945 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 946 947 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, sparams); 948 if (err < 0) { 949 pcm_dbg(substream->pcm, "HW_PARAMS failed: %i\n", err); 950 goto failure; 951 } 952 953 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 954 snd_pcm_oss_plugin_clear(substream); 955 if (!direct) { 956 /* add necessary plugins */ 957 snd_pcm_oss_plugin_clear(substream); 958 if ((err = snd_pcm_plug_format_plugins(substream, 959 params, 960 sparams)) < 0) { 961 pcm_dbg(substream->pcm, 962 "snd_pcm_plug_format_plugins failed: %i\n", err); 963 snd_pcm_oss_plugin_clear(substream); 964 goto failure; 965 } 966 if (runtime->oss.plugin_first) { 967 struct snd_pcm_plugin *plugin; 968 if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) { 969 pcm_dbg(substream->pcm, 970 "snd_pcm_plugin_build_io failed: %i\n", err); 971 snd_pcm_oss_plugin_clear(substream); 972 goto failure; 973 } 974 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 975 err = snd_pcm_plugin_append(plugin); 976 } else { 977 err = snd_pcm_plugin_insert(plugin); 978 } 979 if (err < 0) { 980 snd_pcm_oss_plugin_clear(substream); 981 goto failure; 982 } 983 } 984 } 985 #endif 986 987 if (runtime->oss.trigger) { 988 sw_params->start_threshold = 1; 989 } else { 990 sw_params->start_threshold = runtime->boundary; 991 } 992 if (atomic_read(&substream->mmap_count) || 993 substream->stream == SNDRV_PCM_STREAM_CAPTURE) 994 sw_params->stop_threshold = runtime->boundary; 995 else 996 sw_params->stop_threshold = runtime->buffer_size; 997 sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE; 998 sw_params->period_step = 1; 999 sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 1000 1 : runtime->period_size; 1001 if (atomic_read(&substream->mmap_count) || 1002 substream->oss.setup.nosilence) { 1003 sw_params->silence_threshold = 0; 1004 sw_params->silence_size = 0; 1005 } else { 1006 snd_pcm_uframes_t frames; 1007 frames = runtime->period_size + 16; 1008 if (frames > runtime->buffer_size) 1009 frames = runtime->buffer_size; 1010 sw_params->silence_threshold = frames; 1011 sw_params->silence_size = frames; 1012 } 1013 1014 if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { 1015 pcm_dbg(substream->pcm, "SW_PARAMS failed: %i\n", err); 1016 goto failure; 1017 } 1018 1019 runtime->oss.periods = params_periods(sparams); 1020 oss_period_size = snd_pcm_plug_client_size(substream, params_period_size(sparams)); 1021 if (oss_period_size < 0) { 1022 err = -EINVAL; 1023 goto failure; 1024 } 1025 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 1026 if (runtime->oss.plugin_first) { 1027 err = snd_pcm_plug_alloc(substream, oss_period_size); 1028 if (err < 0) 1029 goto failure; 1030 } 1031 #endif 1032 oss_period_size *= oss_frame_size; 1033 1034 oss_buffer_size = oss_period_size * runtime->oss.periods; 1035 if (oss_buffer_size < 0) { 1036 err = -EINVAL; 1037 goto failure; 1038 } 1039 1040 runtime->oss.period_bytes = oss_period_size; 1041 runtime->oss.buffer_bytes = oss_buffer_size; 1042 1043 pdprintf("oss: period bytes = %i, buffer bytes = %i\n", 1044 runtime->oss.period_bytes, 1045 runtime->oss.buffer_bytes); 1046 pdprintf("slave: period_size = %i, buffer_size = %i\n", 1047 params_period_size(sparams), 1048 params_buffer_size(sparams)); 1049 1050 runtime->oss.format = snd_pcm_oss_format_to(params_format(params)); 1051 runtime->oss.channels = params_channels(params); 1052 runtime->oss.rate = params_rate(params); 1053 1054 kvfree(runtime->oss.buffer); 1055 runtime->oss.buffer = kvzalloc(runtime->oss.period_bytes, GFP_KERNEL); 1056 if (!runtime->oss.buffer) { 1057 err = -ENOMEM; 1058 goto failure; 1059 } 1060 1061 runtime->oss.params = 0; 1062 runtime->oss.prepare = 1; 1063 runtime->oss.buffer_used = 0; 1064 if (runtime->dma_area) 1065 snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes)); 1066 1067 runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size); 1068 1069 err = 0; 1070 failure: 1071 kfree(sw_params); 1072 kfree(params); 1073 kfree(sparams); 1074 return err; 1075 } 1076 1077 /* this one takes the lock by itself */ 1078 static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, 1079 bool trylock) 1080 { 1081 struct snd_pcm_runtime *runtime = substream->runtime; 1082 int err; 1083 1084 if (trylock) { 1085 if (!(mutex_trylock(&runtime->oss.params_lock))) 1086 return -EAGAIN; 1087 } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) 1088 return -ERESTARTSYS; 1089 1090 err = snd_pcm_oss_change_params_locked(substream); 1091 mutex_unlock(&runtime->oss.params_lock); 1092 return err; 1093 } 1094 1095 static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream) 1096 { 1097 int idx, err; 1098 struct snd_pcm_substream *asubstream = NULL, *substream; 1099 1100 for (idx = 0; idx < 2; idx++) { 1101 substream = pcm_oss_file->streams[idx]; 1102 if (substream == NULL) 1103 continue; 1104 if (asubstream == NULL) 1105 asubstream = substream; 1106 if (substream->runtime->oss.params) { 1107 err = snd_pcm_oss_change_params(substream, false); 1108 if (err < 0) 1109 return err; 1110 } 1111 } 1112 if (!asubstream) 1113 return -EIO; 1114 if (r_substream) 1115 *r_substream = asubstream; 1116 return 0; 1117 } 1118 1119 /* call with params_lock held */ 1120 /* NOTE: this always call PREPARE unconditionally no matter whether 1121 * runtime->oss.prepare is set or not 1122 */ 1123 static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) 1124 { 1125 int err; 1126 struct snd_pcm_runtime *runtime = substream->runtime; 1127 1128 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); 1129 if (err < 0) { 1130 pcm_dbg(substream->pcm, 1131 "snd_pcm_oss_prepare: SNDRV_PCM_IOCTL_PREPARE failed\n"); 1132 return err; 1133 } 1134 runtime->oss.prepare = 0; 1135 runtime->oss.prev_hw_ptr_period = 0; 1136 runtime->oss.period_ptr = 0; 1137 runtime->oss.buffer_used = 0; 1138 1139 return 0; 1140 } 1141 1142 static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream) 1143 { 1144 struct snd_pcm_runtime *runtime; 1145 int err; 1146 1147 runtime = substream->runtime; 1148 if (runtime->oss.params) { 1149 err = snd_pcm_oss_change_params(substream, false); 1150 if (err < 0) 1151 return err; 1152 } 1153 if (runtime->oss.prepare) { 1154 if (mutex_lock_interruptible(&runtime->oss.params_lock)) 1155 return -ERESTARTSYS; 1156 err = snd_pcm_oss_prepare(substream); 1157 mutex_unlock(&runtime->oss.params_lock); 1158 if (err < 0) 1159 return err; 1160 } 1161 return 0; 1162 } 1163 1164 /* call with params_lock held */ 1165 static int snd_pcm_oss_make_ready_locked(struct snd_pcm_substream *substream) 1166 { 1167 struct snd_pcm_runtime *runtime; 1168 int err; 1169 1170 runtime = substream->runtime; 1171 if (runtime->oss.params) { 1172 err = snd_pcm_oss_change_params_locked(substream); 1173 if (err < 0) 1174 return err; 1175 } 1176 if (runtime->oss.prepare) { 1177 err = snd_pcm_oss_prepare(substream); 1178 if (err < 0) 1179 return err; 1180 } 1181 return 0; 1182 } 1183 1184 static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay) 1185 { 1186 struct snd_pcm_runtime *runtime; 1187 snd_pcm_uframes_t frames; 1188 int err = 0; 1189 1190 while (1) { 1191 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay); 1192 if (err < 0) 1193 break; 1194 runtime = substream->runtime; 1195 if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size) 1196 break; 1197 /* in case of overrun, skip whole periods like OSS/Linux driver does */ 1198 /* until avail(delay) <= buffer_size */ 1199 frames = (*delay - runtime->buffer_size) + runtime->period_size - 1; 1200 frames /= runtime->period_size; 1201 frames *= runtime->period_size; 1202 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames); 1203 if (err < 0) 1204 break; 1205 } 1206 return err; 1207 } 1208 1209 snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel) 1210 { 1211 struct snd_pcm_runtime *runtime = substream->runtime; 1212 int ret; 1213 while (1) { 1214 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 1215 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1216 #ifdef OSS_DEBUG 1217 pcm_dbg(substream->pcm, 1218 "pcm_oss: write: recovering from %s\n", 1219 runtime->status->state == SNDRV_PCM_STATE_XRUN ? 1220 "XRUN" : "SUSPEND"); 1221 #endif 1222 ret = snd_pcm_oss_prepare(substream); 1223 if (ret < 0) 1224 break; 1225 } 1226 mutex_unlock(&runtime->oss.params_lock); 1227 ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, 1228 frames, in_kernel); 1229 mutex_lock(&runtime->oss.params_lock); 1230 if (ret != -EPIPE && ret != -ESTRPIPE) 1231 break; 1232 /* test, if we can't store new data, because the stream */ 1233 /* has not been started */ 1234 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) 1235 return -EAGAIN; 1236 } 1237 return ret; 1238 } 1239 1240 snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel) 1241 { 1242 struct snd_pcm_runtime *runtime = substream->runtime; 1243 snd_pcm_sframes_t delay; 1244 int ret; 1245 while (1) { 1246 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 1247 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1248 #ifdef OSS_DEBUG 1249 pcm_dbg(substream->pcm, 1250 "pcm_oss: read: recovering from %s\n", 1251 runtime->status->state == SNDRV_PCM_STATE_XRUN ? 1252 "XRUN" : "SUSPEND"); 1253 #endif 1254 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 1255 if (ret < 0) 1256 break; 1257 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { 1258 ret = snd_pcm_oss_prepare(substream); 1259 if (ret < 0) 1260 break; 1261 } 1262 ret = snd_pcm_oss_capture_position_fixup(substream, &delay); 1263 if (ret < 0) 1264 break; 1265 mutex_unlock(&runtime->oss.params_lock); 1266 ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, 1267 frames, in_kernel); 1268 mutex_lock(&runtime->oss.params_lock); 1269 if (ret == -EPIPE) { 1270 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { 1271 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 1272 if (ret < 0) 1273 break; 1274 } 1275 continue; 1276 } 1277 if (ret != -ESTRPIPE) 1278 break; 1279 } 1280 return ret; 1281 } 1282 1283 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 1284 snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames) 1285 { 1286 struct snd_pcm_runtime *runtime = substream->runtime; 1287 int ret; 1288 while (1) { 1289 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 1290 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1291 #ifdef OSS_DEBUG 1292 pcm_dbg(substream->pcm, 1293 "pcm_oss: writev: recovering from %s\n", 1294 runtime->status->state == SNDRV_PCM_STATE_XRUN ? 1295 "XRUN" : "SUSPEND"); 1296 #endif 1297 ret = snd_pcm_oss_prepare(substream); 1298 if (ret < 0) 1299 break; 1300 } 1301 ret = snd_pcm_kernel_writev(substream, bufs, frames); 1302 if (ret != -EPIPE && ret != -ESTRPIPE) 1303 break; 1304 1305 /* test, if we can't store new data, because the stream */ 1306 /* has not been started */ 1307 if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) 1308 return -EAGAIN; 1309 } 1310 return ret; 1311 } 1312 1313 snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames) 1314 { 1315 struct snd_pcm_runtime *runtime = substream->runtime; 1316 int ret; 1317 while (1) { 1318 if (runtime->status->state == SNDRV_PCM_STATE_XRUN || 1319 runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { 1320 #ifdef OSS_DEBUG 1321 pcm_dbg(substream->pcm, 1322 "pcm_oss: readv: recovering from %s\n", 1323 runtime->status->state == SNDRV_PCM_STATE_XRUN ? 1324 "XRUN" : "SUSPEND"); 1325 #endif 1326 ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 1327 if (ret < 0) 1328 break; 1329 } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { 1330 ret = snd_pcm_oss_prepare(substream); 1331 if (ret < 0) 1332 break; 1333 } 1334 ret = snd_pcm_kernel_readv(substream, bufs, frames); 1335 if (ret != -EPIPE && ret != -ESTRPIPE) 1336 break; 1337 } 1338 return ret; 1339 } 1340 #endif /* CONFIG_SND_PCM_OSS_PLUGINS */ 1341 1342 static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) 1343 { 1344 struct snd_pcm_runtime *runtime = substream->runtime; 1345 snd_pcm_sframes_t frames, frames1; 1346 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 1347 if (runtime->oss.plugin_first) { 1348 struct snd_pcm_plugin_channel *channels; 1349 size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; 1350 if (!in_kernel) { 1351 if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes)) 1352 return -EFAULT; 1353 buf = runtime->oss.buffer; 1354 } 1355 frames = bytes / oss_frame_bytes; 1356 frames1 = snd_pcm_plug_client_channels_buf(substream, (char *)buf, frames, &channels); 1357 if (frames1 < 0) 1358 return frames1; 1359 frames1 = snd_pcm_plug_write_transfer(substream, channels, frames1); 1360 if (frames1 <= 0) 1361 return frames1; 1362 bytes = frames1 * oss_frame_bytes; 1363 } else 1364 #endif 1365 { 1366 frames = bytes_to_frames(runtime, bytes); 1367 frames1 = snd_pcm_oss_write3(substream, buf, frames, in_kernel); 1368 if (frames1 <= 0) 1369 return frames1; 1370 bytes = frames_to_bytes(runtime, frames1); 1371 } 1372 return bytes; 1373 } 1374 1375 static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes) 1376 { 1377 size_t xfer = 0; 1378 ssize_t tmp = 0; 1379 struct snd_pcm_runtime *runtime = substream->runtime; 1380 1381 if (atomic_read(&substream->mmap_count)) 1382 return -ENXIO; 1383 1384 atomic_inc(&runtime->oss.rw_ref); 1385 while (bytes > 0) { 1386 if (mutex_lock_interruptible(&runtime->oss.params_lock)) { 1387 tmp = -ERESTARTSYS; 1388 break; 1389 } 1390 tmp = snd_pcm_oss_make_ready_locked(substream); 1391 if (tmp < 0) 1392 goto err; 1393 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { 1394 tmp = bytes; 1395 if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) 1396 tmp = runtime->oss.period_bytes - runtime->oss.buffer_used; 1397 if (tmp > 0) { 1398 if (copy_from_user(runtime->oss.buffer + runtime->oss.buffer_used, buf, tmp)) { 1399 tmp = -EFAULT; 1400 goto err; 1401 } 1402 } 1403 runtime->oss.buffer_used += tmp; 1404 buf += tmp; 1405 bytes -= tmp; 1406 xfer += tmp; 1407 if (substream->oss.setup.partialfrag || 1408 runtime->oss.buffer_used == runtime->oss.period_bytes) { 1409 tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer + runtime->oss.period_ptr, 1410 runtime->oss.buffer_used - runtime->oss.period_ptr, 1); 1411 if (tmp <= 0) 1412 goto err; 1413 runtime->oss.bytes += tmp; 1414 runtime->oss.period_ptr += tmp; 1415 runtime->oss.period_ptr %= runtime->oss.period_bytes; 1416 if (runtime->oss.period_ptr == 0 || 1417 runtime->oss.period_ptr == runtime->oss.buffer_used) 1418 runtime->oss.buffer_used = 0; 1419 else if ((substream->f_flags & O_NONBLOCK) != 0) { 1420 tmp = -EAGAIN; 1421 goto err; 1422 } 1423 } 1424 } else { 1425 tmp = snd_pcm_oss_write2(substream, 1426 (const char __force *)buf, 1427 runtime->oss.period_bytes, 0); 1428 if (tmp <= 0) 1429 goto err; 1430 runtime->oss.bytes += tmp; 1431 buf += tmp; 1432 bytes -= tmp; 1433 xfer += tmp; 1434 if ((substream->f_flags & O_NONBLOCK) != 0 && 1435 tmp != runtime->oss.period_bytes) 1436 tmp = -EAGAIN; 1437 } 1438 err: 1439 mutex_unlock(&runtime->oss.params_lock); 1440 if (tmp < 0) 1441 break; 1442 if (signal_pending(current)) { 1443 tmp = -ERESTARTSYS; 1444 break; 1445 } 1446 tmp = 0; 1447 } 1448 atomic_dec(&runtime->oss.rw_ref); 1449 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 1450 } 1451 1452 static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel) 1453 { 1454 struct snd_pcm_runtime *runtime = substream->runtime; 1455 snd_pcm_sframes_t frames, frames1; 1456 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 1457 char __user *final_dst = (char __force __user *)buf; 1458 if (runtime->oss.plugin_first) { 1459 struct snd_pcm_plugin_channel *channels; 1460 size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; 1461 if (!in_kernel) 1462 buf = runtime->oss.buffer; 1463 frames = bytes / oss_frame_bytes; 1464 frames1 = snd_pcm_plug_client_channels_buf(substream, buf, frames, &channels); 1465 if (frames1 < 0) 1466 return frames1; 1467 frames1 = snd_pcm_plug_read_transfer(substream, channels, frames1); 1468 if (frames1 <= 0) 1469 return frames1; 1470 bytes = frames1 * oss_frame_bytes; 1471 if (!in_kernel && copy_to_user(final_dst, buf, bytes)) 1472 return -EFAULT; 1473 } else 1474 #endif 1475 { 1476 frames = bytes_to_frames(runtime, bytes); 1477 frames1 = snd_pcm_oss_read3(substream, buf, frames, in_kernel); 1478 if (frames1 <= 0) 1479 return frames1; 1480 bytes = frames_to_bytes(runtime, frames1); 1481 } 1482 return bytes; 1483 } 1484 1485 static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes) 1486 { 1487 size_t xfer = 0; 1488 ssize_t tmp = 0; 1489 struct snd_pcm_runtime *runtime = substream->runtime; 1490 1491 if (atomic_read(&substream->mmap_count)) 1492 return -ENXIO; 1493 1494 atomic_inc(&runtime->oss.rw_ref); 1495 while (bytes > 0) { 1496 if (mutex_lock_interruptible(&runtime->oss.params_lock)) { 1497 tmp = -ERESTARTSYS; 1498 break; 1499 } 1500 tmp = snd_pcm_oss_make_ready_locked(substream); 1501 if (tmp < 0) 1502 goto err; 1503 if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { 1504 if (runtime->oss.buffer_used == 0) { 1505 tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); 1506 if (tmp <= 0) 1507 goto err; 1508 runtime->oss.bytes += tmp; 1509 runtime->oss.period_ptr = tmp; 1510 runtime->oss.buffer_used = tmp; 1511 } 1512 tmp = bytes; 1513 if ((size_t) tmp > runtime->oss.buffer_used) 1514 tmp = runtime->oss.buffer_used; 1515 if (copy_to_user(buf, runtime->oss.buffer + (runtime->oss.period_ptr - runtime->oss.buffer_used), tmp)) { 1516 tmp = -EFAULT; 1517 goto err; 1518 } 1519 buf += tmp; 1520 bytes -= tmp; 1521 xfer += tmp; 1522 runtime->oss.buffer_used -= tmp; 1523 } else { 1524 tmp = snd_pcm_oss_read2(substream, (char __force *)buf, 1525 runtime->oss.period_bytes, 0); 1526 if (tmp <= 0) 1527 goto err; 1528 runtime->oss.bytes += tmp; 1529 buf += tmp; 1530 bytes -= tmp; 1531 xfer += tmp; 1532 } 1533 err: 1534 mutex_unlock(&runtime->oss.params_lock); 1535 if (tmp < 0) 1536 break; 1537 if (signal_pending(current)) { 1538 tmp = -ERESTARTSYS; 1539 break; 1540 } 1541 tmp = 0; 1542 } 1543 atomic_dec(&runtime->oss.rw_ref); 1544 return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; 1545 } 1546 1547 static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file) 1548 { 1549 struct snd_pcm_substream *substream; 1550 struct snd_pcm_runtime *runtime; 1551 int i; 1552 1553 for (i = 0; i < 2; i++) { 1554 substream = pcm_oss_file->streams[i]; 1555 if (!substream) 1556 continue; 1557 runtime = substream->runtime; 1558 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 1559 mutex_lock(&runtime->oss.params_lock); 1560 runtime->oss.prepare = 1; 1561 runtime->oss.buffer_used = 0; 1562 runtime->oss.prev_hw_ptr_period = 0; 1563 runtime->oss.period_ptr = 0; 1564 mutex_unlock(&runtime->oss.params_lock); 1565 } 1566 return 0; 1567 } 1568 1569 static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file) 1570 { 1571 struct snd_pcm_substream *substream; 1572 int err; 1573 1574 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1575 if (substream != NULL) { 1576 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1577 return err; 1578 snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_START, NULL); 1579 } 1580 /* note: all errors from the start action are ignored */ 1581 /* OSS apps do not know, how to handle them */ 1582 return 0; 1583 } 1584 1585 static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) 1586 { 1587 struct snd_pcm_runtime *runtime; 1588 ssize_t result = 0; 1589 snd_pcm_state_t state; 1590 long res; 1591 wait_queue_entry_t wait; 1592 1593 runtime = substream->runtime; 1594 init_waitqueue_entry(&wait, current); 1595 add_wait_queue(&runtime->sleep, &wait); 1596 #ifdef OSS_DEBUG 1597 pcm_dbg(substream->pcm, "sync1: size = %li\n", size); 1598 #endif 1599 while (1) { 1600 result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1); 1601 if (result > 0) { 1602 runtime->oss.buffer_used = 0; 1603 result = 0; 1604 break; 1605 } 1606 if (result != 0 && result != -EAGAIN) 1607 break; 1608 result = 0; 1609 set_current_state(TASK_INTERRUPTIBLE); 1610 snd_pcm_stream_lock_irq(substream); 1611 state = runtime->status->state; 1612 snd_pcm_stream_unlock_irq(substream); 1613 if (state != SNDRV_PCM_STATE_RUNNING) { 1614 set_current_state(TASK_RUNNING); 1615 break; 1616 } 1617 res = schedule_timeout(10 * HZ); 1618 if (signal_pending(current)) { 1619 result = -ERESTARTSYS; 1620 break; 1621 } 1622 if (res == 0) { 1623 pcm_err(substream->pcm, 1624 "OSS sync error - DMA timeout\n"); 1625 result = -EIO; 1626 break; 1627 } 1628 } 1629 remove_wait_queue(&runtime->sleep, &wait); 1630 return result; 1631 } 1632 1633 static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) 1634 { 1635 int err = 0; 1636 unsigned int saved_f_flags; 1637 struct snd_pcm_substream *substream; 1638 struct snd_pcm_runtime *runtime; 1639 snd_pcm_format_t format; 1640 unsigned long width; 1641 size_t size; 1642 1643 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1644 if (substream != NULL) { 1645 runtime = substream->runtime; 1646 if (atomic_read(&substream->mmap_count)) 1647 goto __direct; 1648 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1649 return err; 1650 atomic_inc(&runtime->oss.rw_ref); 1651 if (mutex_lock_interruptible(&runtime->oss.params_lock)) { 1652 atomic_dec(&runtime->oss.rw_ref); 1653 return -ERESTARTSYS; 1654 } 1655 format = snd_pcm_oss_format_from(runtime->oss.format); 1656 width = snd_pcm_format_physical_width(format); 1657 if (runtime->oss.buffer_used > 0) { 1658 #ifdef OSS_DEBUG 1659 pcm_dbg(substream->pcm, "sync: buffer_used\n"); 1660 #endif 1661 size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width; 1662 snd_pcm_format_set_silence(format, 1663 runtime->oss.buffer + runtime->oss.buffer_used, 1664 size); 1665 err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes); 1666 if (err < 0) 1667 goto unlock; 1668 } else if (runtime->oss.period_ptr > 0) { 1669 #ifdef OSS_DEBUG 1670 pcm_dbg(substream->pcm, "sync: period_ptr\n"); 1671 #endif 1672 size = runtime->oss.period_bytes - runtime->oss.period_ptr; 1673 snd_pcm_format_set_silence(format, 1674 runtime->oss.buffer, 1675 size * 8 / width); 1676 err = snd_pcm_oss_sync1(substream, size); 1677 if (err < 0) 1678 goto unlock; 1679 } 1680 /* 1681 * The ALSA's period might be a bit large than OSS one. 1682 * Fill the remain portion of ALSA period with zeros. 1683 */ 1684 size = runtime->control->appl_ptr % runtime->period_size; 1685 if (size > 0) { 1686 size = runtime->period_size - size; 1687 if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) 1688 snd_pcm_lib_write(substream, NULL, size); 1689 else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) 1690 snd_pcm_lib_writev(substream, NULL, size); 1691 } 1692 unlock: 1693 mutex_unlock(&runtime->oss.params_lock); 1694 atomic_dec(&runtime->oss.rw_ref); 1695 if (err < 0) 1696 return err; 1697 /* 1698 * finish sync: drain the buffer 1699 */ 1700 __direct: 1701 saved_f_flags = substream->f_flags; 1702 substream->f_flags &= ~O_NONBLOCK; 1703 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); 1704 substream->f_flags = saved_f_flags; 1705 if (err < 0) 1706 return err; 1707 mutex_lock(&runtime->oss.params_lock); 1708 runtime->oss.prepare = 1; 1709 mutex_unlock(&runtime->oss.params_lock); 1710 } 1711 1712 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 1713 if (substream != NULL) { 1714 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 1715 return err; 1716 runtime = substream->runtime; 1717 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); 1718 if (err < 0) 1719 return err; 1720 mutex_lock(&runtime->oss.params_lock); 1721 runtime->oss.buffer_used = 0; 1722 runtime->oss.prepare = 1; 1723 mutex_unlock(&runtime->oss.params_lock); 1724 } 1725 return 0; 1726 } 1727 1728 static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate) 1729 { 1730 int idx; 1731 1732 for (idx = 1; idx >= 0; --idx) { 1733 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1734 struct snd_pcm_runtime *runtime; 1735 int err; 1736 1737 if (substream == NULL) 1738 continue; 1739 runtime = substream->runtime; 1740 if (rate < 1000) 1741 rate = 1000; 1742 else if (rate > 192000) 1743 rate = 192000; 1744 err = lock_params(runtime); 1745 if (err < 0) 1746 return err; 1747 if (runtime->oss.rate != rate) { 1748 runtime->oss.params = 1; 1749 runtime->oss.rate = rate; 1750 } 1751 unlock_params(runtime); 1752 } 1753 return snd_pcm_oss_get_rate(pcm_oss_file); 1754 } 1755 1756 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file) 1757 { 1758 struct snd_pcm_substream *substream; 1759 int err; 1760 1761 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1762 return err; 1763 return substream->runtime->oss.rate; 1764 } 1765 1766 static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels) 1767 { 1768 int idx; 1769 if (channels < 1) 1770 channels = 1; 1771 if (channels > 128) 1772 return -EINVAL; 1773 for (idx = 1; idx >= 0; --idx) { 1774 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1775 struct snd_pcm_runtime *runtime; 1776 int err; 1777 1778 if (substream == NULL) 1779 continue; 1780 runtime = substream->runtime; 1781 err = lock_params(runtime); 1782 if (err < 0) 1783 return err; 1784 if (runtime->oss.channels != channels) { 1785 runtime->oss.params = 1; 1786 runtime->oss.channels = channels; 1787 } 1788 unlock_params(runtime); 1789 } 1790 return snd_pcm_oss_get_channels(pcm_oss_file); 1791 } 1792 1793 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file) 1794 { 1795 struct snd_pcm_substream *substream; 1796 int err; 1797 1798 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1799 return err; 1800 return substream->runtime->oss.channels; 1801 } 1802 1803 static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file) 1804 { 1805 struct snd_pcm_substream *substream; 1806 int err; 1807 1808 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1809 return err; 1810 return substream->runtime->oss.period_bytes; 1811 } 1812 1813 static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) 1814 { 1815 struct snd_pcm_substream *substream; 1816 int err; 1817 int direct; 1818 struct snd_pcm_hw_params *params; 1819 unsigned int formats = 0; 1820 const struct snd_mask *format_mask; 1821 int fmt; 1822 1823 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1824 return err; 1825 if (atomic_read(&substream->mmap_count)) 1826 direct = 1; 1827 else 1828 direct = substream->oss.setup.direct; 1829 if (!direct) 1830 return AFMT_MU_LAW | AFMT_U8 | 1831 AFMT_S16_LE | AFMT_S16_BE | 1832 AFMT_S8 | AFMT_U16_LE | 1833 AFMT_U16_BE | 1834 AFMT_S32_LE | AFMT_S32_BE | 1835 AFMT_S24_LE | AFMT_S24_BE | 1836 AFMT_S24_PACKED; 1837 params = kmalloc(sizeof(*params), GFP_KERNEL); 1838 if (!params) 1839 return -ENOMEM; 1840 _snd_pcm_hw_params_any(params); 1841 err = snd_pcm_hw_refine(substream, params); 1842 if (err < 0) 1843 goto error; 1844 format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); 1845 for (fmt = 0; fmt < 32; ++fmt) { 1846 if (snd_mask_test(format_mask, fmt)) { 1847 int f = snd_pcm_oss_format_to((__force snd_pcm_format_t)fmt); 1848 if (f >= 0) 1849 formats |= f; 1850 } 1851 } 1852 1853 error: 1854 kfree(params); 1855 return err < 0 ? err : formats; 1856 } 1857 1858 static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) 1859 { 1860 int formats, idx; 1861 int err; 1862 1863 if (format != AFMT_QUERY) { 1864 formats = snd_pcm_oss_get_formats(pcm_oss_file); 1865 if (formats < 0) 1866 return formats; 1867 if (!(formats & format)) 1868 format = AFMT_U8; 1869 for (idx = 1; idx >= 0; --idx) { 1870 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1871 struct snd_pcm_runtime *runtime; 1872 if (substream == NULL) 1873 continue; 1874 runtime = substream->runtime; 1875 err = lock_params(runtime); 1876 if (err < 0) 1877 return err; 1878 if (runtime->oss.format != format) { 1879 runtime->oss.params = 1; 1880 runtime->oss.format = format; 1881 } 1882 unlock_params(runtime); 1883 } 1884 } 1885 return snd_pcm_oss_get_format(pcm_oss_file); 1886 } 1887 1888 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) 1889 { 1890 struct snd_pcm_substream *substream; 1891 int err; 1892 1893 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1894 return err; 1895 return substream->runtime->oss.format; 1896 } 1897 1898 static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide) 1899 { 1900 struct snd_pcm_runtime *runtime; 1901 1902 runtime = substream->runtime; 1903 if (subdivide == 0) { 1904 subdivide = runtime->oss.subdivision; 1905 if (subdivide == 0) 1906 subdivide = 1; 1907 return subdivide; 1908 } 1909 if (runtime->oss.subdivision || runtime->oss.fragshift) 1910 return -EINVAL; 1911 if (subdivide != 1 && subdivide != 2 && subdivide != 4 && 1912 subdivide != 8 && subdivide != 16) 1913 return -EINVAL; 1914 runtime->oss.subdivision = subdivide; 1915 runtime->oss.params = 1; 1916 return subdivide; 1917 } 1918 1919 static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide) 1920 { 1921 int err = -EINVAL, idx; 1922 1923 for (idx = 1; idx >= 0; --idx) { 1924 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1925 struct snd_pcm_runtime *runtime; 1926 1927 if (substream == NULL) 1928 continue; 1929 runtime = substream->runtime; 1930 err = lock_params(runtime); 1931 if (err < 0) 1932 return err; 1933 err = snd_pcm_oss_set_subdivide1(substream, subdivide); 1934 unlock_params(runtime); 1935 if (err < 0) 1936 return err; 1937 } 1938 return err; 1939 } 1940 1941 static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val) 1942 { 1943 struct snd_pcm_runtime *runtime; 1944 int fragshift; 1945 1946 runtime = substream->runtime; 1947 if (runtime->oss.subdivision || runtime->oss.fragshift) 1948 return -EINVAL; 1949 fragshift = val & 0xffff; 1950 if (fragshift >= 31) 1951 return -EINVAL; 1952 runtime->oss.fragshift = fragshift; 1953 runtime->oss.maxfrags = (val >> 16) & 0xffff; 1954 if (runtime->oss.fragshift < 4) /* < 16 */ 1955 runtime->oss.fragshift = 4; 1956 if (runtime->oss.maxfrags < 2) 1957 runtime->oss.maxfrags = 2; 1958 runtime->oss.params = 1; 1959 return 0; 1960 } 1961 1962 static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val) 1963 { 1964 int err = -EINVAL, idx; 1965 1966 for (idx = 1; idx >= 0; --idx) { 1967 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1968 struct snd_pcm_runtime *runtime; 1969 1970 if (substream == NULL) 1971 continue; 1972 runtime = substream->runtime; 1973 err = lock_params(runtime); 1974 if (err < 0) 1975 return err; 1976 err = snd_pcm_oss_set_fragment1(substream, val); 1977 unlock_params(runtime); 1978 if (err < 0) 1979 return err; 1980 } 1981 return err; 1982 } 1983 1984 static int snd_pcm_oss_nonblock(struct file * file) 1985 { 1986 spin_lock(&file->f_lock); 1987 file->f_flags |= O_NONBLOCK; 1988 spin_unlock(&file->f_lock); 1989 return 0; 1990 } 1991 1992 static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res) 1993 { 1994 1995 if (substream == NULL) { 1996 res &= ~DSP_CAP_DUPLEX; 1997 return res; 1998 } 1999 #ifdef DSP_CAP_MULTI 2000 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 2001 if (substream->pstr->substream_count > 1) 2002 res |= DSP_CAP_MULTI; 2003 #endif 2004 /* DSP_CAP_REALTIME is set all times: */ 2005 /* all ALSA drivers can return actual pointer in ring buffer */ 2006 #if defined(DSP_CAP_REALTIME) && 0 2007 { 2008 struct snd_pcm_runtime *runtime = substream->runtime; 2009 if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH)) 2010 res &= ~DSP_CAP_REALTIME; 2011 } 2012 #endif 2013 return res; 2014 } 2015 2016 static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file) 2017 { 2018 int result, idx; 2019 2020 result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME; 2021 for (idx = 0; idx < 2; idx++) { 2022 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 2023 result = snd_pcm_oss_get_caps1(substream, result); 2024 } 2025 result |= 0x0001; /* revision - same as SB AWE 64 */ 2026 return result; 2027 } 2028 2029 static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, 2030 snd_pcm_uframes_t hw_ptr) 2031 { 2032 struct snd_pcm_runtime *runtime = substream->runtime; 2033 snd_pcm_uframes_t appl_ptr; 2034 appl_ptr = hw_ptr + runtime->buffer_size; 2035 appl_ptr %= runtime->boundary; 2036 runtime->control->appl_ptr = appl_ptr; 2037 } 2038 2039 static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger) 2040 { 2041 struct snd_pcm_runtime *runtime; 2042 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 2043 int err, cmd; 2044 2045 #ifdef OSS_DEBUG 2046 pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger); 2047 #endif 2048 2049 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2050 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2051 2052 if (psubstream) { 2053 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) 2054 return err; 2055 } 2056 if (csubstream) { 2057 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) 2058 return err; 2059 } 2060 if (psubstream) { 2061 runtime = psubstream->runtime; 2062 cmd = 0; 2063 if (mutex_lock_interruptible(&runtime->oss.params_lock)) 2064 return -ERESTARTSYS; 2065 if (trigger & PCM_ENABLE_OUTPUT) { 2066 if (runtime->oss.trigger) 2067 goto _skip1; 2068 if (atomic_read(&psubstream->mmap_count)) 2069 snd_pcm_oss_simulate_fill(psubstream, 2070 get_hw_ptr_period(runtime)); 2071 runtime->oss.trigger = 1; 2072 runtime->start_threshold = 1; 2073 cmd = SNDRV_PCM_IOCTL_START; 2074 } else { 2075 if (!runtime->oss.trigger) 2076 goto _skip1; 2077 runtime->oss.trigger = 0; 2078 runtime->start_threshold = runtime->boundary; 2079 cmd = SNDRV_PCM_IOCTL_DROP; 2080 runtime->oss.prepare = 1; 2081 } 2082 _skip1: 2083 mutex_unlock(&runtime->oss.params_lock); 2084 if (cmd) { 2085 err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); 2086 if (err < 0) 2087 return err; 2088 } 2089 } 2090 if (csubstream) { 2091 runtime = csubstream->runtime; 2092 cmd = 0; 2093 if (mutex_lock_interruptible(&runtime->oss.params_lock)) 2094 return -ERESTARTSYS; 2095 if (trigger & PCM_ENABLE_INPUT) { 2096 if (runtime->oss.trigger) 2097 goto _skip2; 2098 runtime->oss.trigger = 1; 2099 runtime->start_threshold = 1; 2100 cmd = SNDRV_PCM_IOCTL_START; 2101 } else { 2102 if (!runtime->oss.trigger) 2103 goto _skip2; 2104 runtime->oss.trigger = 0; 2105 runtime->start_threshold = runtime->boundary; 2106 cmd = SNDRV_PCM_IOCTL_DROP; 2107 runtime->oss.prepare = 1; 2108 } 2109 _skip2: 2110 mutex_unlock(&runtime->oss.params_lock); 2111 if (cmd) { 2112 err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); 2113 if (err < 0) 2114 return err; 2115 } 2116 } 2117 return 0; 2118 } 2119 2120 static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file) 2121 { 2122 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 2123 int result = 0; 2124 2125 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2126 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2127 if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger) 2128 result |= PCM_ENABLE_OUTPUT; 2129 if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger) 2130 result |= PCM_ENABLE_INPUT; 2131 return result; 2132 } 2133 2134 static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) 2135 { 2136 struct snd_pcm_substream *substream; 2137 struct snd_pcm_runtime *runtime; 2138 snd_pcm_sframes_t delay; 2139 int err; 2140 2141 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2142 if (substream == NULL) 2143 return -EINVAL; 2144 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 2145 return err; 2146 runtime = substream->runtime; 2147 if (runtime->oss.params || runtime->oss.prepare) 2148 return 0; 2149 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); 2150 if (err == -EPIPE) 2151 delay = 0; /* hack for broken OSS applications */ 2152 else if (err < 0) 2153 return err; 2154 return snd_pcm_oss_bytes(substream, delay); 2155 } 2156 2157 static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info) 2158 { 2159 struct snd_pcm_substream *substream; 2160 struct snd_pcm_runtime *runtime; 2161 snd_pcm_sframes_t delay; 2162 int fixup; 2163 struct count_info info; 2164 int err; 2165 2166 if (_info == NULL) 2167 return -EFAULT; 2168 substream = pcm_oss_file->streams[stream]; 2169 if (substream == NULL) 2170 return -EINVAL; 2171 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 2172 return err; 2173 runtime = substream->runtime; 2174 if (runtime->oss.params || runtime->oss.prepare) { 2175 memset(&info, 0, sizeof(info)); 2176 if (copy_to_user(_info, &info, sizeof(info))) 2177 return -EFAULT; 2178 return 0; 2179 } 2180 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2181 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); 2182 if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) { 2183 err = 0; 2184 delay = 0; 2185 fixup = 0; 2186 } else { 2187 fixup = runtime->oss.buffer_used; 2188 } 2189 } else { 2190 err = snd_pcm_oss_capture_position_fixup(substream, &delay); 2191 fixup = -runtime->oss.buffer_used; 2192 } 2193 if (err < 0) 2194 return err; 2195 info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); 2196 if (atomic_read(&substream->mmap_count)) { 2197 snd_pcm_sframes_t n; 2198 delay = get_hw_ptr_period(runtime); 2199 n = delay - runtime->oss.prev_hw_ptr_period; 2200 if (n < 0) 2201 n += runtime->boundary; 2202 info.blocks = n / runtime->period_size; 2203 runtime->oss.prev_hw_ptr_period = delay; 2204 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 2205 snd_pcm_oss_simulate_fill(substream, delay); 2206 info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; 2207 } else { 2208 delay = snd_pcm_oss_bytes(substream, delay); 2209 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2210 if (substream->oss.setup.buggyptr) 2211 info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; 2212 else 2213 info.blocks = (delay + fixup) / runtime->oss.period_bytes; 2214 info.bytes = (runtime->oss.bytes - delay) & INT_MAX; 2215 } else { 2216 delay += fixup; 2217 info.blocks = delay / runtime->oss.period_bytes; 2218 info.bytes = (runtime->oss.bytes + delay) & INT_MAX; 2219 } 2220 } 2221 if (copy_to_user(_info, &info, sizeof(info))) 2222 return -EFAULT; 2223 return 0; 2224 } 2225 2226 static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info) 2227 { 2228 struct snd_pcm_substream *substream; 2229 struct snd_pcm_runtime *runtime; 2230 snd_pcm_sframes_t avail; 2231 int fixup; 2232 struct audio_buf_info info; 2233 int err; 2234 2235 if (_info == NULL) 2236 return -EFAULT; 2237 substream = pcm_oss_file->streams[stream]; 2238 if (substream == NULL) 2239 return -EINVAL; 2240 runtime = substream->runtime; 2241 2242 if (runtime->oss.params && 2243 (err = snd_pcm_oss_change_params(substream, false)) < 0) 2244 return err; 2245 2246 info.fragsize = runtime->oss.period_bytes; 2247 info.fragstotal = runtime->periods; 2248 if (runtime->oss.prepare) { 2249 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2250 info.bytes = runtime->oss.period_bytes * runtime->oss.periods; 2251 info.fragments = runtime->oss.periods; 2252 } else { 2253 info.bytes = 0; 2254 info.fragments = 0; 2255 } 2256 } else { 2257 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2258 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail); 2259 if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) { 2260 avail = runtime->buffer_size; 2261 err = 0; 2262 fixup = 0; 2263 } else { 2264 avail = runtime->buffer_size - avail; 2265 fixup = -runtime->oss.buffer_used; 2266 } 2267 } else { 2268 err = snd_pcm_oss_capture_position_fixup(substream, &avail); 2269 fixup = runtime->oss.buffer_used; 2270 } 2271 if (err < 0) 2272 return err; 2273 info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup; 2274 info.fragments = info.bytes / runtime->oss.period_bytes; 2275 } 2276 2277 #ifdef OSS_DEBUG 2278 pcm_dbg(substream->pcm, 2279 "pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", 2280 info.bytes, info.fragments, info.fragstotal, info.fragsize); 2281 #endif 2282 if (copy_to_user(_info, &info, sizeof(info))) 2283 return -EFAULT; 2284 return 0; 2285 } 2286 2287 static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info) 2288 { 2289 // it won't be probably implemented 2290 // pr_debug("TODO: snd_pcm_oss_get_mapbuf\n"); 2291 return -EINVAL; 2292 } 2293 2294 static const char *strip_task_path(const char *path) 2295 { 2296 const char *ptr, *ptrl = NULL; 2297 for (ptr = path; *ptr; ptr++) { 2298 if (*ptr == '/') 2299 ptrl = ptr + 1; 2300 } 2301 return ptrl; 2302 } 2303 2304 static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, 2305 const char *task_name, 2306 struct snd_pcm_oss_setup *rsetup) 2307 { 2308 struct snd_pcm_oss_setup *setup; 2309 2310 mutex_lock(&pcm->streams[stream].oss.setup_mutex); 2311 do { 2312 for (setup = pcm->streams[stream].oss.setup_list; setup; 2313 setup = setup->next) { 2314 if (!strcmp(setup->task_name, task_name)) 2315 goto out; 2316 } 2317 } while ((task_name = strip_task_path(task_name)) != NULL); 2318 out: 2319 if (setup) 2320 *rsetup = *setup; 2321 mutex_unlock(&pcm->streams[stream].oss.setup_mutex); 2322 } 2323 2324 static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) 2325 { 2326 struct snd_pcm_runtime *runtime; 2327 runtime = substream->runtime; 2328 kvfree(runtime->oss.buffer); 2329 runtime->oss.buffer = NULL; 2330 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 2331 snd_pcm_oss_plugin_clear(substream); 2332 #endif 2333 substream->oss.oss = 0; 2334 } 2335 2336 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, 2337 struct snd_pcm_oss_setup *setup, 2338 int minor) 2339 { 2340 struct snd_pcm_runtime *runtime; 2341 2342 substream->oss.oss = 1; 2343 substream->oss.setup = *setup; 2344 if (setup->nonblock) 2345 substream->f_flags |= O_NONBLOCK; 2346 else if (setup->block) 2347 substream->f_flags &= ~O_NONBLOCK; 2348 runtime = substream->runtime; 2349 runtime->oss.params = 1; 2350 runtime->oss.trigger = 1; 2351 runtime->oss.rate = 8000; 2352 mutex_init(&runtime->oss.params_lock); 2353 switch (SNDRV_MINOR_OSS_DEVICE(minor)) { 2354 case SNDRV_MINOR_OSS_PCM_8: 2355 runtime->oss.format = AFMT_U8; 2356 break; 2357 case SNDRV_MINOR_OSS_PCM_16: 2358 runtime->oss.format = AFMT_S16_LE; 2359 break; 2360 default: 2361 runtime->oss.format = AFMT_MU_LAW; 2362 } 2363 runtime->oss.channels = 1; 2364 runtime->oss.fragshift = 0; 2365 runtime->oss.maxfrags = 0; 2366 runtime->oss.subdivision = 0; 2367 substream->pcm_release = snd_pcm_oss_release_substream; 2368 atomic_set(&runtime->oss.rw_ref, 0); 2369 } 2370 2371 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) 2372 { 2373 int cidx; 2374 if (!pcm_oss_file) 2375 return 0; 2376 for (cidx = 0; cidx < 2; ++cidx) { 2377 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; 2378 if (substream) 2379 snd_pcm_release_substream(substream); 2380 } 2381 kfree(pcm_oss_file); 2382 return 0; 2383 } 2384 2385 static int snd_pcm_oss_open_file(struct file *file, 2386 struct snd_pcm *pcm, 2387 struct snd_pcm_oss_file **rpcm_oss_file, 2388 int minor, 2389 struct snd_pcm_oss_setup *setup) 2390 { 2391 int idx, err; 2392 struct snd_pcm_oss_file *pcm_oss_file; 2393 struct snd_pcm_substream *substream; 2394 fmode_t f_mode = file->f_mode; 2395 2396 if (rpcm_oss_file) 2397 *rpcm_oss_file = NULL; 2398 2399 pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL); 2400 if (pcm_oss_file == NULL) 2401 return -ENOMEM; 2402 2403 if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && 2404 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) 2405 f_mode = FMODE_WRITE; 2406 2407 file->f_flags &= ~O_APPEND; 2408 for (idx = 0; idx < 2; idx++) { 2409 if (setup[idx].disable) 2410 continue; 2411 if (! pcm->streams[idx].substream_count) 2412 continue; /* no matching substream */ 2413 if (idx == SNDRV_PCM_STREAM_PLAYBACK) { 2414 if (! (f_mode & FMODE_WRITE)) 2415 continue; 2416 } else { 2417 if (! (f_mode & FMODE_READ)) 2418 continue; 2419 } 2420 err = snd_pcm_open_substream(pcm, idx, file, &substream); 2421 if (err < 0) { 2422 snd_pcm_oss_release_file(pcm_oss_file); 2423 return err; 2424 } 2425 2426 pcm_oss_file->streams[idx] = substream; 2427 snd_pcm_oss_init_substream(substream, &setup[idx], minor); 2428 } 2429 2430 if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) { 2431 snd_pcm_oss_release_file(pcm_oss_file); 2432 return -EINVAL; 2433 } 2434 2435 file->private_data = pcm_oss_file; 2436 if (rpcm_oss_file) 2437 *rpcm_oss_file = pcm_oss_file; 2438 return 0; 2439 } 2440 2441 2442 static int snd_task_name(struct task_struct *task, char *name, size_t size) 2443 { 2444 unsigned int idx; 2445 2446 if (snd_BUG_ON(!task || !name || size < 2)) 2447 return -EINVAL; 2448 for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) 2449 name[idx] = task->comm[idx]; 2450 name[idx] = '\0'; 2451 return 0; 2452 } 2453 2454 static int snd_pcm_oss_open(struct inode *inode, struct file *file) 2455 { 2456 int err; 2457 char task_name[32]; 2458 struct snd_pcm *pcm; 2459 struct snd_pcm_oss_file *pcm_oss_file; 2460 struct snd_pcm_oss_setup setup[2]; 2461 int nonblock; 2462 wait_queue_entry_t wait; 2463 2464 err = nonseekable_open(inode, file); 2465 if (err < 0) 2466 return err; 2467 2468 pcm = snd_lookup_oss_minor_data(iminor(inode), 2469 SNDRV_OSS_DEVICE_TYPE_PCM); 2470 if (pcm == NULL) { 2471 err = -ENODEV; 2472 goto __error1; 2473 } 2474 err = snd_card_file_add(pcm->card, file); 2475 if (err < 0) 2476 goto __error1; 2477 if (!try_module_get(pcm->card->module)) { 2478 err = -EFAULT; 2479 goto __error2; 2480 } 2481 if (snd_task_name(current, task_name, sizeof(task_name)) < 0) { 2482 err = -EFAULT; 2483 goto __error; 2484 } 2485 memset(setup, 0, sizeof(setup)); 2486 if (file->f_mode & FMODE_WRITE) 2487 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, 2488 task_name, &setup[0]); 2489 if (file->f_mode & FMODE_READ) 2490 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, 2491 task_name, &setup[1]); 2492 2493 nonblock = !!(file->f_flags & O_NONBLOCK); 2494 if (!nonblock) 2495 nonblock = nonblock_open; 2496 2497 init_waitqueue_entry(&wait, current); 2498 add_wait_queue(&pcm->open_wait, &wait); 2499 mutex_lock(&pcm->open_mutex); 2500 while (1) { 2501 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, 2502 iminor(inode), setup); 2503 if (err >= 0) 2504 break; 2505 if (err == -EAGAIN) { 2506 if (nonblock) { 2507 err = -EBUSY; 2508 break; 2509 } 2510 } else 2511 break; 2512 set_current_state(TASK_INTERRUPTIBLE); 2513 mutex_unlock(&pcm->open_mutex); 2514 schedule(); 2515 mutex_lock(&pcm->open_mutex); 2516 if (pcm->card->shutdown) { 2517 err = -ENODEV; 2518 break; 2519 } 2520 if (signal_pending(current)) { 2521 err = -ERESTARTSYS; 2522 break; 2523 } 2524 } 2525 remove_wait_queue(&pcm->open_wait, &wait); 2526 mutex_unlock(&pcm->open_mutex); 2527 if (err < 0) 2528 goto __error; 2529 snd_card_unref(pcm->card); 2530 return err; 2531 2532 __error: 2533 module_put(pcm->card->module); 2534 __error2: 2535 snd_card_file_remove(pcm->card, file); 2536 __error1: 2537 if (pcm) 2538 snd_card_unref(pcm->card); 2539 return err; 2540 } 2541 2542 static int snd_pcm_oss_release(struct inode *inode, struct file *file) 2543 { 2544 struct snd_pcm *pcm; 2545 struct snd_pcm_substream *substream; 2546 struct snd_pcm_oss_file *pcm_oss_file; 2547 2548 pcm_oss_file = file->private_data; 2549 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2550 if (substream == NULL) 2551 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2552 if (snd_BUG_ON(!substream)) 2553 return -ENXIO; 2554 pcm = substream->pcm; 2555 if (!pcm->card->shutdown) 2556 snd_pcm_oss_sync(pcm_oss_file); 2557 mutex_lock(&pcm->open_mutex); 2558 snd_pcm_oss_release_file(pcm_oss_file); 2559 mutex_unlock(&pcm->open_mutex); 2560 wake_up(&pcm->open_wait); 2561 module_put(pcm->card->module); 2562 snd_card_file_remove(pcm->card, file); 2563 return 0; 2564 } 2565 2566 static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2567 { 2568 struct snd_pcm_oss_file *pcm_oss_file; 2569 int __user *p = (int __user *)arg; 2570 int res; 2571 2572 pcm_oss_file = file->private_data; 2573 if (cmd == OSS_GETVERSION) 2574 return put_user(SNDRV_OSS_VERSION, p); 2575 if (cmd == OSS_ALSAEMULVER) 2576 return put_user(1, p); 2577 #if IS_REACHABLE(CONFIG_SND_MIXER_OSS) 2578 if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */ 2579 struct snd_pcm_substream *substream; 2580 int idx; 2581 for (idx = 0; idx < 2; ++idx) { 2582 substream = pcm_oss_file->streams[idx]; 2583 if (substream != NULL) 2584 break; 2585 } 2586 if (snd_BUG_ON(idx >= 2)) 2587 return -ENXIO; 2588 return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg); 2589 } 2590 #endif 2591 if (((cmd >> 8) & 0xff) != 'P') 2592 return -EINVAL; 2593 #ifdef OSS_DEBUG 2594 pr_debug("pcm_oss: ioctl = 0x%x\n", cmd); 2595 #endif 2596 switch (cmd) { 2597 case SNDCTL_DSP_RESET: 2598 return snd_pcm_oss_reset(pcm_oss_file); 2599 case SNDCTL_DSP_SYNC: 2600 return snd_pcm_oss_sync(pcm_oss_file); 2601 case SNDCTL_DSP_SPEED: 2602 if (get_user(res, p)) 2603 return -EFAULT; 2604 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0) 2605 return res; 2606 return put_user(res, p); 2607 case SOUND_PCM_READ_RATE: 2608 res = snd_pcm_oss_get_rate(pcm_oss_file); 2609 if (res < 0) 2610 return res; 2611 return put_user(res, p); 2612 case SNDCTL_DSP_STEREO: 2613 if (get_user(res, p)) 2614 return -EFAULT; 2615 res = res > 0 ? 2 : 1; 2616 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0) 2617 return res; 2618 return put_user(--res, p); 2619 case SNDCTL_DSP_GETBLKSIZE: 2620 res = snd_pcm_oss_get_block_size(pcm_oss_file); 2621 if (res < 0) 2622 return res; 2623 return put_user(res, p); 2624 case SNDCTL_DSP_SETFMT: 2625 if (get_user(res, p)) 2626 return -EFAULT; 2627 res = snd_pcm_oss_set_format(pcm_oss_file, res); 2628 if (res < 0) 2629 return res; 2630 return put_user(res, p); 2631 case SOUND_PCM_READ_BITS: 2632 res = snd_pcm_oss_get_format(pcm_oss_file); 2633 if (res < 0) 2634 return res; 2635 return put_user(res, p); 2636 case SNDCTL_DSP_CHANNELS: 2637 if (get_user(res, p)) 2638 return -EFAULT; 2639 res = snd_pcm_oss_set_channels(pcm_oss_file, res); 2640 if (res < 0) 2641 return res; 2642 return put_user(res, p); 2643 case SOUND_PCM_READ_CHANNELS: 2644 res = snd_pcm_oss_get_channels(pcm_oss_file); 2645 if (res < 0) 2646 return res; 2647 return put_user(res, p); 2648 case SOUND_PCM_WRITE_FILTER: 2649 case SOUND_PCM_READ_FILTER: 2650 return -EIO; 2651 case SNDCTL_DSP_POST: 2652 return snd_pcm_oss_post(pcm_oss_file); 2653 case SNDCTL_DSP_SUBDIVIDE: 2654 if (get_user(res, p)) 2655 return -EFAULT; 2656 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res); 2657 if (res < 0) 2658 return res; 2659 return put_user(res, p); 2660 case SNDCTL_DSP_SETFRAGMENT: 2661 if (get_user(res, p)) 2662 return -EFAULT; 2663 return snd_pcm_oss_set_fragment(pcm_oss_file, res); 2664 case SNDCTL_DSP_GETFMTS: 2665 res = snd_pcm_oss_get_formats(pcm_oss_file); 2666 if (res < 0) 2667 return res; 2668 return put_user(res, p); 2669 case SNDCTL_DSP_GETOSPACE: 2670 case SNDCTL_DSP_GETISPACE: 2671 return snd_pcm_oss_get_space(pcm_oss_file, 2672 cmd == SNDCTL_DSP_GETISPACE ? 2673 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2674 (struct audio_buf_info __user *) arg); 2675 case SNDCTL_DSP_NONBLOCK: 2676 return snd_pcm_oss_nonblock(file); 2677 case SNDCTL_DSP_GETCAPS: 2678 res = snd_pcm_oss_get_caps(pcm_oss_file); 2679 if (res < 0) 2680 return res; 2681 return put_user(res, p); 2682 case SNDCTL_DSP_GETTRIGGER: 2683 res = snd_pcm_oss_get_trigger(pcm_oss_file); 2684 if (res < 0) 2685 return res; 2686 return put_user(res, p); 2687 case SNDCTL_DSP_SETTRIGGER: 2688 if (get_user(res, p)) 2689 return -EFAULT; 2690 return snd_pcm_oss_set_trigger(pcm_oss_file, res); 2691 case SNDCTL_DSP_GETIPTR: 2692 case SNDCTL_DSP_GETOPTR: 2693 return snd_pcm_oss_get_ptr(pcm_oss_file, 2694 cmd == SNDCTL_DSP_GETIPTR ? 2695 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2696 (struct count_info __user *) arg); 2697 case SNDCTL_DSP_MAPINBUF: 2698 case SNDCTL_DSP_MAPOUTBUF: 2699 return snd_pcm_oss_get_mapbuf(pcm_oss_file, 2700 cmd == SNDCTL_DSP_MAPINBUF ? 2701 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2702 (struct buffmem_desc __user *) arg); 2703 case SNDCTL_DSP_SETSYNCRO: 2704 /* stop DMA now.. */ 2705 return 0; 2706 case SNDCTL_DSP_SETDUPLEX: 2707 if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX) 2708 return 0; 2709 return -EIO; 2710 case SNDCTL_DSP_GETODELAY: 2711 res = snd_pcm_oss_get_odelay(pcm_oss_file); 2712 if (res < 0) { 2713 /* it's for sure, some broken apps don't check for error codes */ 2714 put_user(0, p); 2715 return res; 2716 } 2717 return put_user(res, p); 2718 case SNDCTL_DSP_PROFILE: 2719 return 0; /* silently ignore */ 2720 default: 2721 pr_debug("pcm_oss: unknown command = 0x%x\n", cmd); 2722 } 2723 return -EINVAL; 2724 } 2725 2726 #ifdef CONFIG_COMPAT 2727 /* all compatible */ 2728 static long snd_pcm_oss_ioctl_compat(struct file *file, unsigned int cmd, 2729 unsigned long arg) 2730 { 2731 /* 2732 * Everything is compatbile except SNDCTL_DSP_MAPINBUF/SNDCTL_DSP_MAPOUTBUF, 2733 * which are not implemented for the native case either 2734 */ 2735 return snd_pcm_oss_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); 2736 } 2737 #else 2738 #define snd_pcm_oss_ioctl_compat NULL 2739 #endif 2740 2741 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 2742 { 2743 struct snd_pcm_oss_file *pcm_oss_file; 2744 struct snd_pcm_substream *substream; 2745 2746 pcm_oss_file = file->private_data; 2747 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2748 if (substream == NULL) 2749 return -ENXIO; 2750 substream->f_flags = file->f_flags & O_NONBLOCK; 2751 #ifndef OSS_DEBUG 2752 return snd_pcm_oss_read1(substream, buf, count); 2753 #else 2754 { 2755 ssize_t res = snd_pcm_oss_read1(substream, buf, count); 2756 pcm_dbg(substream->pcm, 2757 "pcm_oss: read %li bytes (returned %li bytes)\n", 2758 (long)count, (long)res); 2759 return res; 2760 } 2761 #endif 2762 } 2763 2764 static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) 2765 { 2766 struct snd_pcm_oss_file *pcm_oss_file; 2767 struct snd_pcm_substream *substream; 2768 long result; 2769 2770 pcm_oss_file = file->private_data; 2771 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2772 if (substream == NULL) 2773 return -ENXIO; 2774 substream->f_flags = file->f_flags & O_NONBLOCK; 2775 result = snd_pcm_oss_write1(substream, buf, count); 2776 #ifdef OSS_DEBUG 2777 pcm_dbg(substream->pcm, "pcm_oss: write %li bytes (wrote %li bytes)\n", 2778 (long)count, (long)result); 2779 #endif 2780 return result; 2781 } 2782 2783 static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) 2784 { 2785 struct snd_pcm_runtime *runtime = substream->runtime; 2786 if (atomic_read(&substream->mmap_count)) 2787 return runtime->oss.prev_hw_ptr_period != 2788 get_hw_ptr_period(runtime); 2789 else 2790 return snd_pcm_playback_avail(runtime) >= 2791 runtime->oss.period_frames; 2792 } 2793 2794 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) 2795 { 2796 struct snd_pcm_runtime *runtime = substream->runtime; 2797 if (atomic_read(&substream->mmap_count)) 2798 return runtime->oss.prev_hw_ptr_period != 2799 get_hw_ptr_period(runtime); 2800 else 2801 return snd_pcm_capture_avail(runtime) >= 2802 runtime->oss.period_frames; 2803 } 2804 2805 static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) 2806 { 2807 struct snd_pcm_oss_file *pcm_oss_file; 2808 __poll_t mask; 2809 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 2810 2811 pcm_oss_file = file->private_data; 2812 2813 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2814 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2815 2816 mask = 0; 2817 if (psubstream != NULL) { 2818 struct snd_pcm_runtime *runtime = psubstream->runtime; 2819 poll_wait(file, &runtime->sleep, wait); 2820 snd_pcm_stream_lock_irq(psubstream); 2821 if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && 2822 (runtime->status->state != SNDRV_PCM_STATE_RUNNING || 2823 snd_pcm_oss_playback_ready(psubstream))) 2824 mask |= EPOLLOUT | EPOLLWRNORM; 2825 snd_pcm_stream_unlock_irq(psubstream); 2826 } 2827 if (csubstream != NULL) { 2828 struct snd_pcm_runtime *runtime = csubstream->runtime; 2829 snd_pcm_state_t ostate; 2830 poll_wait(file, &runtime->sleep, wait); 2831 snd_pcm_stream_lock_irq(csubstream); 2832 if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || 2833 snd_pcm_oss_capture_ready(csubstream)) 2834 mask |= EPOLLIN | EPOLLRDNORM; 2835 snd_pcm_stream_unlock_irq(csubstream); 2836 if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) { 2837 struct snd_pcm_oss_file ofile; 2838 memset(&ofile, 0, sizeof(ofile)); 2839 ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2840 runtime->oss.trigger = 0; 2841 snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT); 2842 } 2843 } 2844 2845 return mask; 2846 } 2847 2848 static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) 2849 { 2850 struct snd_pcm_oss_file *pcm_oss_file; 2851 struct snd_pcm_substream *substream = NULL; 2852 struct snd_pcm_runtime *runtime; 2853 int err; 2854 2855 #ifdef OSS_DEBUG 2856 pr_debug("pcm_oss: mmap begin\n"); 2857 #endif 2858 pcm_oss_file = file->private_data; 2859 switch ((area->vm_flags & (VM_READ | VM_WRITE))) { 2860 case VM_READ | VM_WRITE: 2861 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2862 if (substream) 2863 break; 2864 fallthrough; 2865 case VM_READ: 2866 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2867 break; 2868 case VM_WRITE: 2869 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2870 break; 2871 default: 2872 return -EINVAL; 2873 } 2874 /* set VM_READ access as well to fix memset() routines that do 2875 reads before writes (to improve performance) */ 2876 area->vm_flags |= VM_READ; 2877 if (substream == NULL) 2878 return -ENXIO; 2879 runtime = substream->runtime; 2880 if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID)) 2881 return -EIO; 2882 if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED) 2883 runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; 2884 else 2885 return -EIO; 2886 2887 if (runtime->oss.params) { 2888 /* use mutex_trylock() for params_lock for avoiding a deadlock 2889 * between mmap_lock and params_lock taken by 2890 * copy_from/to_user() in snd_pcm_oss_write/read() 2891 */ 2892 err = snd_pcm_oss_change_params(substream, true); 2893 if (err < 0) 2894 return err; 2895 } 2896 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 2897 if (runtime->oss.plugin_first != NULL) 2898 return -EIO; 2899 #endif 2900 2901 if (area->vm_pgoff != 0) 2902 return -EINVAL; 2903 2904 err = snd_pcm_mmap_data(substream, file, area); 2905 if (err < 0) 2906 return err; 2907 runtime->oss.mmap_bytes = area->vm_end - area->vm_start; 2908 runtime->silence_threshold = 0; 2909 runtime->silence_size = 0; 2910 #ifdef OSS_DEBUG 2911 pr_debug("pcm_oss: mmap ok, bytes = 0x%x\n", 2912 runtime->oss.mmap_bytes); 2913 #endif 2914 /* In mmap mode we never stop */ 2915 runtime->stop_threshold = runtime->boundary; 2916 2917 return 0; 2918 } 2919 2920 #ifdef CONFIG_SND_VERBOSE_PROCFS 2921 /* 2922 * /proc interface 2923 */ 2924 2925 static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, 2926 struct snd_info_buffer *buffer) 2927 { 2928 struct snd_pcm_str *pstr = entry->private_data; 2929 struct snd_pcm_oss_setup *setup = pstr->oss.setup_list; 2930 mutex_lock(&pstr->oss.setup_mutex); 2931 while (setup) { 2932 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", 2933 setup->task_name, 2934 setup->periods, 2935 setup->period_size, 2936 setup->disable ? " disable" : "", 2937 setup->direct ? " direct" : "", 2938 setup->block ? " block" : "", 2939 setup->nonblock ? " non-block" : "", 2940 setup->partialfrag ? " partial-frag" : "", 2941 setup->nosilence ? " no-silence" : ""); 2942 setup = setup->next; 2943 } 2944 mutex_unlock(&pstr->oss.setup_mutex); 2945 } 2946 2947 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) 2948 { 2949 struct snd_pcm_oss_setup *setup, *setupn; 2950 2951 for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; 2952 setup; setup = setupn) { 2953 setupn = setup->next; 2954 kfree(setup->task_name); 2955 kfree(setup); 2956 } 2957 pstr->oss.setup_list = NULL; 2958 } 2959 2960 static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, 2961 struct snd_info_buffer *buffer) 2962 { 2963 struct snd_pcm_str *pstr = entry->private_data; 2964 char line[128], str[32], task_name[32]; 2965 const char *ptr; 2966 int idx1; 2967 struct snd_pcm_oss_setup *setup, *setup1, template; 2968 2969 while (!snd_info_get_line(buffer, line, sizeof(line))) { 2970 mutex_lock(&pstr->oss.setup_mutex); 2971 memset(&template, 0, sizeof(template)); 2972 ptr = snd_info_get_str(task_name, line, sizeof(task_name)); 2973 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) { 2974 snd_pcm_oss_proc_free_setup_list(pstr); 2975 mutex_unlock(&pstr->oss.setup_mutex); 2976 continue; 2977 } 2978 for (setup = pstr->oss.setup_list; setup; setup = setup->next) { 2979 if (!strcmp(setup->task_name, task_name)) { 2980 template = *setup; 2981 break; 2982 } 2983 } 2984 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2985 template.periods = simple_strtoul(str, NULL, 10); 2986 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2987 template.period_size = simple_strtoul(str, NULL, 10); 2988 for (idx1 = 31; idx1 >= 0; idx1--) 2989 if (template.period_size & (1 << idx1)) 2990 break; 2991 for (idx1--; idx1 >= 0; idx1--) 2992 template.period_size &= ~(1 << idx1); 2993 do { 2994 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2995 if (!strcmp(str, "disable")) { 2996 template.disable = 1; 2997 } else if (!strcmp(str, "direct")) { 2998 template.direct = 1; 2999 } else if (!strcmp(str, "block")) { 3000 template.block = 1; 3001 } else if (!strcmp(str, "non-block")) { 3002 template.nonblock = 1; 3003 } else if (!strcmp(str, "partial-frag")) { 3004 template.partialfrag = 1; 3005 } else if (!strcmp(str, "no-silence")) { 3006 template.nosilence = 1; 3007 } else if (!strcmp(str, "buggy-ptr")) { 3008 template.buggyptr = 1; 3009 } 3010 } while (*str); 3011 if (setup == NULL) { 3012 setup = kmalloc(sizeof(*setup), GFP_KERNEL); 3013 if (! setup) { 3014 buffer->error = -ENOMEM; 3015 mutex_unlock(&pstr->oss.setup_mutex); 3016 return; 3017 } 3018 if (pstr->oss.setup_list == NULL) 3019 pstr->oss.setup_list = setup; 3020 else { 3021 for (setup1 = pstr->oss.setup_list; 3022 setup1->next; setup1 = setup1->next); 3023 setup1->next = setup; 3024 } 3025 template.task_name = kstrdup(task_name, GFP_KERNEL); 3026 if (! template.task_name) { 3027 kfree(setup); 3028 buffer->error = -ENOMEM; 3029 mutex_unlock(&pstr->oss.setup_mutex); 3030 return; 3031 } 3032 } 3033 *setup = template; 3034 mutex_unlock(&pstr->oss.setup_mutex); 3035 } 3036 } 3037 3038 static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) 3039 { 3040 int stream; 3041 for (stream = 0; stream < 2; ++stream) { 3042 struct snd_info_entry *entry; 3043 struct snd_pcm_str *pstr = &pcm->streams[stream]; 3044 if (pstr->substream_count == 0) 3045 continue; 3046 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { 3047 entry->content = SNDRV_INFO_CONTENT_TEXT; 3048 entry->mode = S_IFREG | 0644; 3049 entry->c.text.read = snd_pcm_oss_proc_read; 3050 entry->c.text.write = snd_pcm_oss_proc_write; 3051 entry->private_data = pstr; 3052 if (snd_info_register(entry) < 0) { 3053 snd_info_free_entry(entry); 3054 entry = NULL; 3055 } 3056 } 3057 pstr->oss.proc_entry = entry; 3058 } 3059 } 3060 3061 static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) 3062 { 3063 int stream; 3064 for (stream = 0; stream < 2; ++stream) { 3065 struct snd_pcm_str *pstr = &pcm->streams[stream]; 3066 snd_info_free_entry(pstr->oss.proc_entry); 3067 pstr->oss.proc_entry = NULL; 3068 snd_pcm_oss_proc_free_setup_list(pstr); 3069 } 3070 } 3071 #else /* !CONFIG_SND_VERBOSE_PROCFS */ 3072 #define snd_pcm_oss_proc_init(pcm) 3073 #define snd_pcm_oss_proc_done(pcm) 3074 #endif /* CONFIG_SND_VERBOSE_PROCFS */ 3075 3076 /* 3077 * ENTRY functions 3078 */ 3079 3080 static const struct file_operations snd_pcm_oss_f_reg = 3081 { 3082 .owner = THIS_MODULE, 3083 .read = snd_pcm_oss_read, 3084 .write = snd_pcm_oss_write, 3085 .open = snd_pcm_oss_open, 3086 .release = snd_pcm_oss_release, 3087 .llseek = no_llseek, 3088 .poll = snd_pcm_oss_poll, 3089 .unlocked_ioctl = snd_pcm_oss_ioctl, 3090 .compat_ioctl = snd_pcm_oss_ioctl_compat, 3091 .mmap = snd_pcm_oss_mmap, 3092 }; 3093 3094 static void register_oss_dsp(struct snd_pcm *pcm, int index) 3095 { 3096 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 3097 pcm->card, index, &snd_pcm_oss_f_reg, 3098 pcm) < 0) { 3099 pcm_err(pcm, "unable to register OSS PCM device %i:%i\n", 3100 pcm->card->number, pcm->device); 3101 } 3102 } 3103 3104 static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) 3105 { 3106 pcm->oss.reg = 0; 3107 if (dsp_map[pcm->card->number] == (int)pcm->device) { 3108 char name[128]; 3109 int duplex; 3110 register_oss_dsp(pcm, 0); 3111 duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 3112 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 3113 !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)); 3114 sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : ""); 3115 #ifdef SNDRV_OSS_INFO_DEV_AUDIO 3116 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO, 3117 pcm->card->number, 3118 name); 3119 #endif 3120 pcm->oss.reg++; 3121 pcm->oss.reg_mask |= 1; 3122 } 3123 if (adsp_map[pcm->card->number] == (int)pcm->device) { 3124 register_oss_dsp(pcm, 1); 3125 pcm->oss.reg++; 3126 pcm->oss.reg_mask |= 2; 3127 } 3128 3129 if (pcm->oss.reg) 3130 snd_pcm_oss_proc_init(pcm); 3131 3132 return 0; 3133 } 3134 3135 static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) 3136 { 3137 if (pcm->oss.reg) { 3138 if (pcm->oss.reg_mask & 1) { 3139 pcm->oss.reg_mask &= ~1; 3140 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 3141 pcm->card, 0); 3142 } 3143 if (pcm->oss.reg_mask & 2) { 3144 pcm->oss.reg_mask &= ~2; 3145 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 3146 pcm->card, 1); 3147 } 3148 if (dsp_map[pcm->card->number] == (int)pcm->device) { 3149 #ifdef SNDRV_OSS_INFO_DEV_AUDIO 3150 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); 3151 #endif 3152 } 3153 pcm->oss.reg = 0; 3154 } 3155 return 0; 3156 } 3157 3158 static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) 3159 { 3160 snd_pcm_oss_disconnect_minor(pcm); 3161 snd_pcm_oss_proc_done(pcm); 3162 return 0; 3163 } 3164 3165 static struct snd_pcm_notify snd_pcm_oss_notify = 3166 { 3167 .n_register = snd_pcm_oss_register_minor, 3168 .n_disconnect = snd_pcm_oss_disconnect_minor, 3169 .n_unregister = snd_pcm_oss_unregister_minor, 3170 }; 3171 3172 static int __init alsa_pcm_oss_init(void) 3173 { 3174 int i; 3175 int err; 3176 3177 /* check device map table */ 3178 for (i = 0; i < SNDRV_CARDS; i++) { 3179 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { 3180 pr_err("ALSA: pcm_oss: invalid dsp_map[%d] = %d\n", 3181 i, dsp_map[i]); 3182 dsp_map[i] = 0; 3183 } 3184 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { 3185 pr_err("ALSA: pcm_oss: invalid adsp_map[%d] = %d\n", 3186 i, adsp_map[i]); 3187 adsp_map[i] = 1; 3188 } 3189 } 3190 if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0) 3191 return err; 3192 return 0; 3193 } 3194 3195 static void __exit alsa_pcm_oss_exit(void) 3196 { 3197 snd_pcm_notify(&snd_pcm_oss_notify, 1); 3198 } 3199 3200 module_init(alsa_pcm_oss_init) 3201 module_exit(alsa_pcm_oss_exit) 3202