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