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 format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); 1766 kfree(params); 1767 if (err < 0) 1768 return err; 1769 for (fmt = 0; fmt < 32; ++fmt) { 1770 if (snd_mask_test(format_mask, fmt)) { 1771 int f = snd_pcm_oss_format_to(fmt); 1772 if (f >= 0) 1773 formats |= f; 1774 } 1775 } 1776 return formats; 1777 } 1778 1779 static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) 1780 { 1781 int formats, idx; 1782 1783 if (format != AFMT_QUERY) { 1784 formats = snd_pcm_oss_get_formats(pcm_oss_file); 1785 if (formats < 0) 1786 return formats; 1787 if (!(formats & format)) 1788 format = AFMT_U8; 1789 for (idx = 1; idx >= 0; --idx) { 1790 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1791 struct snd_pcm_runtime *runtime; 1792 if (substream == NULL) 1793 continue; 1794 runtime = substream->runtime; 1795 if (runtime->oss.format != format) { 1796 runtime->oss.params = 1; 1797 runtime->oss.format = format; 1798 } 1799 } 1800 } 1801 return snd_pcm_oss_get_format(pcm_oss_file); 1802 } 1803 1804 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file) 1805 { 1806 struct snd_pcm_substream *substream; 1807 int err; 1808 1809 if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) 1810 return err; 1811 return substream->runtime->oss.format; 1812 } 1813 1814 static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide) 1815 { 1816 struct snd_pcm_runtime *runtime; 1817 1818 if (substream == NULL) 1819 return 0; 1820 runtime = substream->runtime; 1821 if (subdivide == 0) { 1822 subdivide = runtime->oss.subdivision; 1823 if (subdivide == 0) 1824 subdivide = 1; 1825 return subdivide; 1826 } 1827 if (runtime->oss.subdivision || runtime->oss.fragshift) 1828 return -EINVAL; 1829 if (subdivide != 1 && subdivide != 2 && subdivide != 4 && 1830 subdivide != 8 && subdivide != 16) 1831 return -EINVAL; 1832 runtime->oss.subdivision = subdivide; 1833 runtime->oss.params = 1; 1834 return subdivide; 1835 } 1836 1837 static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide) 1838 { 1839 int err = -EINVAL, idx; 1840 1841 for (idx = 1; idx >= 0; --idx) { 1842 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1843 if (substream == NULL) 1844 continue; 1845 if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0) 1846 return err; 1847 } 1848 return err; 1849 } 1850 1851 static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val) 1852 { 1853 struct snd_pcm_runtime *runtime; 1854 1855 if (substream == NULL) 1856 return 0; 1857 runtime = substream->runtime; 1858 if (runtime->oss.subdivision || runtime->oss.fragshift) 1859 return -EINVAL; 1860 runtime->oss.fragshift = val & 0xffff; 1861 runtime->oss.maxfrags = (val >> 16) & 0xffff; 1862 if (runtime->oss.fragshift < 4) /* < 16 */ 1863 runtime->oss.fragshift = 4; 1864 if (runtime->oss.maxfrags < 2) 1865 runtime->oss.maxfrags = 2; 1866 runtime->oss.params = 1; 1867 return 0; 1868 } 1869 1870 static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val) 1871 { 1872 int err = -EINVAL, idx; 1873 1874 for (idx = 1; idx >= 0; --idx) { 1875 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1876 if (substream == NULL) 1877 continue; 1878 if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0) 1879 return err; 1880 } 1881 return err; 1882 } 1883 1884 static int snd_pcm_oss_nonblock(struct file * file) 1885 { 1886 spin_lock(&file->f_lock); 1887 file->f_flags |= O_NONBLOCK; 1888 spin_unlock(&file->f_lock); 1889 return 0; 1890 } 1891 1892 static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res) 1893 { 1894 1895 if (substream == NULL) { 1896 res &= ~DSP_CAP_DUPLEX; 1897 return res; 1898 } 1899 #ifdef DSP_CAP_MULTI 1900 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1901 if (substream->pstr->substream_count > 1) 1902 res |= DSP_CAP_MULTI; 1903 #endif 1904 /* DSP_CAP_REALTIME is set all times: */ 1905 /* all ALSA drivers can return actual pointer in ring buffer */ 1906 #if defined(DSP_CAP_REALTIME) && 0 1907 { 1908 struct snd_pcm_runtime *runtime = substream->runtime; 1909 if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH)) 1910 res &= ~DSP_CAP_REALTIME; 1911 } 1912 #endif 1913 return res; 1914 } 1915 1916 static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file) 1917 { 1918 int result, idx; 1919 1920 result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME; 1921 for (idx = 0; idx < 2; idx++) { 1922 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; 1923 result = snd_pcm_oss_get_caps1(substream, result); 1924 } 1925 result |= 0x0001; /* revision - same as SB AWE 64 */ 1926 return result; 1927 } 1928 1929 static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, 1930 snd_pcm_uframes_t hw_ptr) 1931 { 1932 struct snd_pcm_runtime *runtime = substream->runtime; 1933 snd_pcm_uframes_t appl_ptr; 1934 appl_ptr = hw_ptr + runtime->buffer_size; 1935 appl_ptr %= runtime->boundary; 1936 runtime->control->appl_ptr = appl_ptr; 1937 } 1938 1939 static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger) 1940 { 1941 struct snd_pcm_runtime *runtime; 1942 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 1943 int err, cmd; 1944 1945 #ifdef OSS_DEBUG 1946 pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger); 1947 #endif 1948 1949 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 1950 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 1951 1952 if (psubstream) { 1953 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0) 1954 return err; 1955 } 1956 if (csubstream) { 1957 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0) 1958 return err; 1959 } 1960 if (psubstream) { 1961 runtime = psubstream->runtime; 1962 if (trigger & PCM_ENABLE_OUTPUT) { 1963 if (runtime->oss.trigger) 1964 goto _skip1; 1965 if (atomic_read(&psubstream->mmap_count)) 1966 snd_pcm_oss_simulate_fill(psubstream, 1967 get_hw_ptr_period(runtime)); 1968 runtime->oss.trigger = 1; 1969 runtime->start_threshold = 1; 1970 cmd = SNDRV_PCM_IOCTL_START; 1971 } else { 1972 if (!runtime->oss.trigger) 1973 goto _skip1; 1974 runtime->oss.trigger = 0; 1975 runtime->start_threshold = runtime->boundary; 1976 cmd = SNDRV_PCM_IOCTL_DROP; 1977 runtime->oss.prepare = 1; 1978 } 1979 err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); 1980 if (err < 0) 1981 return err; 1982 } 1983 _skip1: 1984 if (csubstream) { 1985 runtime = csubstream->runtime; 1986 if (trigger & PCM_ENABLE_INPUT) { 1987 if (runtime->oss.trigger) 1988 goto _skip2; 1989 runtime->oss.trigger = 1; 1990 runtime->start_threshold = 1; 1991 cmd = SNDRV_PCM_IOCTL_START; 1992 } else { 1993 if (!runtime->oss.trigger) 1994 goto _skip2; 1995 runtime->oss.trigger = 0; 1996 runtime->start_threshold = runtime->boundary; 1997 cmd = SNDRV_PCM_IOCTL_DROP; 1998 runtime->oss.prepare = 1; 1999 } 2000 err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); 2001 if (err < 0) 2002 return err; 2003 } 2004 _skip2: 2005 return 0; 2006 } 2007 2008 static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file) 2009 { 2010 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 2011 int result = 0; 2012 2013 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2014 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2015 if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger) 2016 result |= PCM_ENABLE_OUTPUT; 2017 if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger) 2018 result |= PCM_ENABLE_INPUT; 2019 return result; 2020 } 2021 2022 static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file) 2023 { 2024 struct snd_pcm_substream *substream; 2025 struct snd_pcm_runtime *runtime; 2026 snd_pcm_sframes_t delay; 2027 int err; 2028 2029 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2030 if (substream == NULL) 2031 return -EINVAL; 2032 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 2033 return err; 2034 runtime = substream->runtime; 2035 if (runtime->oss.params || runtime->oss.prepare) 2036 return 0; 2037 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); 2038 if (err == -EPIPE) 2039 delay = 0; /* hack for broken OSS applications */ 2040 else if (err < 0) 2041 return err; 2042 return snd_pcm_oss_bytes(substream, delay); 2043 } 2044 2045 static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info) 2046 { 2047 struct snd_pcm_substream *substream; 2048 struct snd_pcm_runtime *runtime; 2049 snd_pcm_sframes_t delay; 2050 int fixup; 2051 struct count_info info; 2052 int err; 2053 2054 if (_info == NULL) 2055 return -EFAULT; 2056 substream = pcm_oss_file->streams[stream]; 2057 if (substream == NULL) 2058 return -EINVAL; 2059 if ((err = snd_pcm_oss_make_ready(substream)) < 0) 2060 return err; 2061 runtime = substream->runtime; 2062 if (runtime->oss.params || runtime->oss.prepare) { 2063 memset(&info, 0, sizeof(info)); 2064 if (copy_to_user(_info, &info, sizeof(info))) 2065 return -EFAULT; 2066 return 0; 2067 } 2068 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2069 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); 2070 if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) { 2071 err = 0; 2072 delay = 0; 2073 fixup = 0; 2074 } else { 2075 fixup = runtime->oss.buffer_used; 2076 } 2077 } else { 2078 err = snd_pcm_oss_capture_position_fixup(substream, &delay); 2079 fixup = -runtime->oss.buffer_used; 2080 } 2081 if (err < 0) 2082 return err; 2083 info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); 2084 if (atomic_read(&substream->mmap_count)) { 2085 snd_pcm_sframes_t n; 2086 delay = get_hw_ptr_period(runtime); 2087 n = delay - runtime->oss.prev_hw_ptr_period; 2088 if (n < 0) 2089 n += runtime->boundary; 2090 info.blocks = n / runtime->period_size; 2091 runtime->oss.prev_hw_ptr_period = delay; 2092 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 2093 snd_pcm_oss_simulate_fill(substream, delay); 2094 info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX; 2095 } else { 2096 delay = snd_pcm_oss_bytes(substream, delay); 2097 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2098 if (substream->oss.setup.buggyptr) 2099 info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes; 2100 else 2101 info.blocks = (delay + fixup) / runtime->oss.period_bytes; 2102 info.bytes = (runtime->oss.bytes - delay) & INT_MAX; 2103 } else { 2104 delay += fixup; 2105 info.blocks = delay / runtime->oss.period_bytes; 2106 info.bytes = (runtime->oss.bytes + delay) & INT_MAX; 2107 } 2108 } 2109 if (copy_to_user(_info, &info, sizeof(info))) 2110 return -EFAULT; 2111 return 0; 2112 } 2113 2114 static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info) 2115 { 2116 struct snd_pcm_substream *substream; 2117 struct snd_pcm_runtime *runtime; 2118 snd_pcm_sframes_t avail; 2119 int fixup; 2120 struct audio_buf_info info; 2121 int err; 2122 2123 if (_info == NULL) 2124 return -EFAULT; 2125 substream = pcm_oss_file->streams[stream]; 2126 if (substream == NULL) 2127 return -EINVAL; 2128 runtime = substream->runtime; 2129 2130 if (runtime->oss.params && 2131 (err = snd_pcm_oss_change_params(substream, false)) < 0) 2132 return err; 2133 2134 info.fragsize = runtime->oss.period_bytes; 2135 info.fragstotal = runtime->periods; 2136 if (runtime->oss.prepare) { 2137 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2138 info.bytes = runtime->oss.period_bytes * runtime->oss.periods; 2139 info.fragments = runtime->oss.periods; 2140 } else { 2141 info.bytes = 0; 2142 info.fragments = 0; 2143 } 2144 } else { 2145 if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 2146 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail); 2147 if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) { 2148 avail = runtime->buffer_size; 2149 err = 0; 2150 fixup = 0; 2151 } else { 2152 avail = runtime->buffer_size - avail; 2153 fixup = -runtime->oss.buffer_used; 2154 } 2155 } else { 2156 err = snd_pcm_oss_capture_position_fixup(substream, &avail); 2157 fixup = runtime->oss.buffer_used; 2158 } 2159 if (err < 0) 2160 return err; 2161 info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup; 2162 info.fragments = info.bytes / runtime->oss.period_bytes; 2163 } 2164 2165 #ifdef OSS_DEBUG 2166 pcm_dbg(substream->pcm, 2167 "pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", 2168 info.bytes, info.fragments, info.fragstotal, info.fragsize); 2169 #endif 2170 if (copy_to_user(_info, &info, sizeof(info))) 2171 return -EFAULT; 2172 return 0; 2173 } 2174 2175 static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info) 2176 { 2177 // it won't be probably implemented 2178 // pr_debug("TODO: snd_pcm_oss_get_mapbuf\n"); 2179 return -EINVAL; 2180 } 2181 2182 static const char *strip_task_path(const char *path) 2183 { 2184 const char *ptr, *ptrl = NULL; 2185 for (ptr = path; *ptr; ptr++) { 2186 if (*ptr == '/') 2187 ptrl = ptr + 1; 2188 } 2189 return ptrl; 2190 } 2191 2192 static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, 2193 const char *task_name, 2194 struct snd_pcm_oss_setup *rsetup) 2195 { 2196 struct snd_pcm_oss_setup *setup; 2197 2198 mutex_lock(&pcm->streams[stream].oss.setup_mutex); 2199 do { 2200 for (setup = pcm->streams[stream].oss.setup_list; setup; 2201 setup = setup->next) { 2202 if (!strcmp(setup->task_name, task_name)) 2203 goto out; 2204 } 2205 } while ((task_name = strip_task_path(task_name)) != NULL); 2206 out: 2207 if (setup) 2208 *rsetup = *setup; 2209 mutex_unlock(&pcm->streams[stream].oss.setup_mutex); 2210 } 2211 2212 static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream) 2213 { 2214 struct snd_pcm_runtime *runtime; 2215 runtime = substream->runtime; 2216 vfree(runtime->oss.buffer); 2217 runtime->oss.buffer = NULL; 2218 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 2219 snd_pcm_oss_plugin_clear(substream); 2220 #endif 2221 substream->oss.oss = 0; 2222 } 2223 2224 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, 2225 struct snd_pcm_oss_setup *setup, 2226 int minor) 2227 { 2228 struct snd_pcm_runtime *runtime; 2229 2230 substream->oss.oss = 1; 2231 substream->oss.setup = *setup; 2232 if (setup->nonblock) 2233 substream->f_flags |= O_NONBLOCK; 2234 else if (setup->block) 2235 substream->f_flags &= ~O_NONBLOCK; 2236 runtime = substream->runtime; 2237 runtime->oss.params = 1; 2238 runtime->oss.trigger = 1; 2239 runtime->oss.rate = 8000; 2240 mutex_init(&runtime->oss.params_lock); 2241 switch (SNDRV_MINOR_OSS_DEVICE(minor)) { 2242 case SNDRV_MINOR_OSS_PCM_8: 2243 runtime->oss.format = AFMT_U8; 2244 break; 2245 case SNDRV_MINOR_OSS_PCM_16: 2246 runtime->oss.format = AFMT_S16_LE; 2247 break; 2248 default: 2249 runtime->oss.format = AFMT_MU_LAW; 2250 } 2251 runtime->oss.channels = 1; 2252 runtime->oss.fragshift = 0; 2253 runtime->oss.maxfrags = 0; 2254 runtime->oss.subdivision = 0; 2255 substream->pcm_release = snd_pcm_oss_release_substream; 2256 } 2257 2258 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) 2259 { 2260 int cidx; 2261 if (!pcm_oss_file) 2262 return 0; 2263 for (cidx = 0; cidx < 2; ++cidx) { 2264 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx]; 2265 if (substream) 2266 snd_pcm_release_substream(substream); 2267 } 2268 kfree(pcm_oss_file); 2269 return 0; 2270 } 2271 2272 static int snd_pcm_oss_open_file(struct file *file, 2273 struct snd_pcm *pcm, 2274 struct snd_pcm_oss_file **rpcm_oss_file, 2275 int minor, 2276 struct snd_pcm_oss_setup *setup) 2277 { 2278 int idx, err; 2279 struct snd_pcm_oss_file *pcm_oss_file; 2280 struct snd_pcm_substream *substream; 2281 fmode_t f_mode = file->f_mode; 2282 2283 if (rpcm_oss_file) 2284 *rpcm_oss_file = NULL; 2285 2286 pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL); 2287 if (pcm_oss_file == NULL) 2288 return -ENOMEM; 2289 2290 if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) && 2291 (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) 2292 f_mode = FMODE_WRITE; 2293 2294 file->f_flags &= ~O_APPEND; 2295 for (idx = 0; idx < 2; idx++) { 2296 if (setup[idx].disable) 2297 continue; 2298 if (! pcm->streams[idx].substream_count) 2299 continue; /* no matching substream */ 2300 if (idx == SNDRV_PCM_STREAM_PLAYBACK) { 2301 if (! (f_mode & FMODE_WRITE)) 2302 continue; 2303 } else { 2304 if (! (f_mode & FMODE_READ)) 2305 continue; 2306 } 2307 err = snd_pcm_open_substream(pcm, idx, file, &substream); 2308 if (err < 0) { 2309 snd_pcm_oss_release_file(pcm_oss_file); 2310 return err; 2311 } 2312 2313 pcm_oss_file->streams[idx] = substream; 2314 substream->file = pcm_oss_file; 2315 snd_pcm_oss_init_substream(substream, &setup[idx], minor); 2316 } 2317 2318 if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) { 2319 snd_pcm_oss_release_file(pcm_oss_file); 2320 return -EINVAL; 2321 } 2322 2323 file->private_data = pcm_oss_file; 2324 if (rpcm_oss_file) 2325 *rpcm_oss_file = pcm_oss_file; 2326 return 0; 2327 } 2328 2329 2330 static int snd_task_name(struct task_struct *task, char *name, size_t size) 2331 { 2332 unsigned int idx; 2333 2334 if (snd_BUG_ON(!task || !name || size < 2)) 2335 return -EINVAL; 2336 for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++) 2337 name[idx] = task->comm[idx]; 2338 name[idx] = '\0'; 2339 return 0; 2340 } 2341 2342 static int snd_pcm_oss_open(struct inode *inode, struct file *file) 2343 { 2344 int err; 2345 char task_name[32]; 2346 struct snd_pcm *pcm; 2347 struct snd_pcm_oss_file *pcm_oss_file; 2348 struct snd_pcm_oss_setup setup[2]; 2349 int nonblock; 2350 wait_queue_entry_t wait; 2351 2352 err = nonseekable_open(inode, file); 2353 if (err < 0) 2354 return err; 2355 2356 pcm = snd_lookup_oss_minor_data(iminor(inode), 2357 SNDRV_OSS_DEVICE_TYPE_PCM); 2358 if (pcm == NULL) { 2359 err = -ENODEV; 2360 goto __error1; 2361 } 2362 err = snd_card_file_add(pcm->card, file); 2363 if (err < 0) 2364 goto __error1; 2365 if (!try_module_get(pcm->card->module)) { 2366 err = -EFAULT; 2367 goto __error2; 2368 } 2369 if (snd_task_name(current, task_name, sizeof(task_name)) < 0) { 2370 err = -EFAULT; 2371 goto __error; 2372 } 2373 memset(setup, 0, sizeof(setup)); 2374 if (file->f_mode & FMODE_WRITE) 2375 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, 2376 task_name, &setup[0]); 2377 if (file->f_mode & FMODE_READ) 2378 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE, 2379 task_name, &setup[1]); 2380 2381 nonblock = !!(file->f_flags & O_NONBLOCK); 2382 if (!nonblock) 2383 nonblock = nonblock_open; 2384 2385 init_waitqueue_entry(&wait, current); 2386 add_wait_queue(&pcm->open_wait, &wait); 2387 mutex_lock(&pcm->open_mutex); 2388 while (1) { 2389 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, 2390 iminor(inode), setup); 2391 if (err >= 0) 2392 break; 2393 if (err == -EAGAIN) { 2394 if (nonblock) { 2395 err = -EBUSY; 2396 break; 2397 } 2398 } else 2399 break; 2400 set_current_state(TASK_INTERRUPTIBLE); 2401 mutex_unlock(&pcm->open_mutex); 2402 schedule(); 2403 mutex_lock(&pcm->open_mutex); 2404 if (pcm->card->shutdown) { 2405 err = -ENODEV; 2406 break; 2407 } 2408 if (signal_pending(current)) { 2409 err = -ERESTARTSYS; 2410 break; 2411 } 2412 } 2413 remove_wait_queue(&pcm->open_wait, &wait); 2414 mutex_unlock(&pcm->open_mutex); 2415 if (err < 0) 2416 goto __error; 2417 snd_card_unref(pcm->card); 2418 return err; 2419 2420 __error: 2421 module_put(pcm->card->module); 2422 __error2: 2423 snd_card_file_remove(pcm->card, file); 2424 __error1: 2425 if (pcm) 2426 snd_card_unref(pcm->card); 2427 return err; 2428 } 2429 2430 static int snd_pcm_oss_release(struct inode *inode, struct file *file) 2431 { 2432 struct snd_pcm *pcm; 2433 struct snd_pcm_substream *substream; 2434 struct snd_pcm_oss_file *pcm_oss_file; 2435 2436 pcm_oss_file = file->private_data; 2437 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2438 if (substream == NULL) 2439 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2440 if (snd_BUG_ON(!substream)) 2441 return -ENXIO; 2442 pcm = substream->pcm; 2443 if (!pcm->card->shutdown) 2444 snd_pcm_oss_sync(pcm_oss_file); 2445 mutex_lock(&pcm->open_mutex); 2446 snd_pcm_oss_release_file(pcm_oss_file); 2447 mutex_unlock(&pcm->open_mutex); 2448 wake_up(&pcm->open_wait); 2449 module_put(pcm->card->module); 2450 snd_card_file_remove(pcm->card, file); 2451 return 0; 2452 } 2453 2454 static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 2455 { 2456 struct snd_pcm_oss_file *pcm_oss_file; 2457 int __user *p = (int __user *)arg; 2458 int res; 2459 2460 pcm_oss_file = file->private_data; 2461 if (cmd == OSS_GETVERSION) 2462 return put_user(SNDRV_OSS_VERSION, p); 2463 if (cmd == OSS_ALSAEMULVER) 2464 return put_user(1, p); 2465 #if IS_REACHABLE(CONFIG_SND_MIXER_OSS) 2466 if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */ 2467 struct snd_pcm_substream *substream; 2468 int idx; 2469 for (idx = 0; idx < 2; ++idx) { 2470 substream = pcm_oss_file->streams[idx]; 2471 if (substream != NULL) 2472 break; 2473 } 2474 if (snd_BUG_ON(idx >= 2)) 2475 return -ENXIO; 2476 return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg); 2477 } 2478 #endif 2479 if (((cmd >> 8) & 0xff) != 'P') 2480 return -EINVAL; 2481 #ifdef OSS_DEBUG 2482 pr_debug("pcm_oss: ioctl = 0x%x\n", cmd); 2483 #endif 2484 switch (cmd) { 2485 case SNDCTL_DSP_RESET: 2486 return snd_pcm_oss_reset(pcm_oss_file); 2487 case SNDCTL_DSP_SYNC: 2488 return snd_pcm_oss_sync(pcm_oss_file); 2489 case SNDCTL_DSP_SPEED: 2490 if (get_user(res, p)) 2491 return -EFAULT; 2492 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0) 2493 return res; 2494 return put_user(res, p); 2495 case SOUND_PCM_READ_RATE: 2496 res = snd_pcm_oss_get_rate(pcm_oss_file); 2497 if (res < 0) 2498 return res; 2499 return put_user(res, p); 2500 case SNDCTL_DSP_STEREO: 2501 if (get_user(res, p)) 2502 return -EFAULT; 2503 res = res > 0 ? 2 : 1; 2504 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0) 2505 return res; 2506 return put_user(--res, p); 2507 case SNDCTL_DSP_GETBLKSIZE: 2508 res = snd_pcm_oss_get_block_size(pcm_oss_file); 2509 if (res < 0) 2510 return res; 2511 return put_user(res, p); 2512 case SNDCTL_DSP_SETFMT: 2513 if (get_user(res, p)) 2514 return -EFAULT; 2515 res = snd_pcm_oss_set_format(pcm_oss_file, res); 2516 if (res < 0) 2517 return res; 2518 return put_user(res, p); 2519 case SOUND_PCM_READ_BITS: 2520 res = snd_pcm_oss_get_format(pcm_oss_file); 2521 if (res < 0) 2522 return res; 2523 return put_user(res, p); 2524 case SNDCTL_DSP_CHANNELS: 2525 if (get_user(res, p)) 2526 return -EFAULT; 2527 res = snd_pcm_oss_set_channels(pcm_oss_file, res); 2528 if (res < 0) 2529 return res; 2530 return put_user(res, p); 2531 case SOUND_PCM_READ_CHANNELS: 2532 res = snd_pcm_oss_get_channels(pcm_oss_file); 2533 if (res < 0) 2534 return res; 2535 return put_user(res, p); 2536 case SOUND_PCM_WRITE_FILTER: 2537 case SOUND_PCM_READ_FILTER: 2538 return -EIO; 2539 case SNDCTL_DSP_POST: 2540 return snd_pcm_oss_post(pcm_oss_file); 2541 case SNDCTL_DSP_SUBDIVIDE: 2542 if (get_user(res, p)) 2543 return -EFAULT; 2544 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res); 2545 if (res < 0) 2546 return res; 2547 return put_user(res, p); 2548 case SNDCTL_DSP_SETFRAGMENT: 2549 if (get_user(res, p)) 2550 return -EFAULT; 2551 return snd_pcm_oss_set_fragment(pcm_oss_file, res); 2552 case SNDCTL_DSP_GETFMTS: 2553 res = snd_pcm_oss_get_formats(pcm_oss_file); 2554 if (res < 0) 2555 return res; 2556 return put_user(res, p); 2557 case SNDCTL_DSP_GETOSPACE: 2558 case SNDCTL_DSP_GETISPACE: 2559 return snd_pcm_oss_get_space(pcm_oss_file, 2560 cmd == SNDCTL_DSP_GETISPACE ? 2561 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2562 (struct audio_buf_info __user *) arg); 2563 case SNDCTL_DSP_NONBLOCK: 2564 return snd_pcm_oss_nonblock(file); 2565 case SNDCTL_DSP_GETCAPS: 2566 res = snd_pcm_oss_get_caps(pcm_oss_file); 2567 if (res < 0) 2568 return res; 2569 return put_user(res, p); 2570 case SNDCTL_DSP_GETTRIGGER: 2571 res = snd_pcm_oss_get_trigger(pcm_oss_file); 2572 if (res < 0) 2573 return res; 2574 return put_user(res, p); 2575 case SNDCTL_DSP_SETTRIGGER: 2576 if (get_user(res, p)) 2577 return -EFAULT; 2578 return snd_pcm_oss_set_trigger(pcm_oss_file, res); 2579 case SNDCTL_DSP_GETIPTR: 2580 case SNDCTL_DSP_GETOPTR: 2581 return snd_pcm_oss_get_ptr(pcm_oss_file, 2582 cmd == SNDCTL_DSP_GETIPTR ? 2583 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2584 (struct count_info __user *) arg); 2585 case SNDCTL_DSP_MAPINBUF: 2586 case SNDCTL_DSP_MAPOUTBUF: 2587 return snd_pcm_oss_get_mapbuf(pcm_oss_file, 2588 cmd == SNDCTL_DSP_MAPINBUF ? 2589 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, 2590 (struct buffmem_desc __user *) arg); 2591 case SNDCTL_DSP_SETSYNCRO: 2592 /* stop DMA now.. */ 2593 return 0; 2594 case SNDCTL_DSP_SETDUPLEX: 2595 if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX) 2596 return 0; 2597 return -EIO; 2598 case SNDCTL_DSP_GETODELAY: 2599 res = snd_pcm_oss_get_odelay(pcm_oss_file); 2600 if (res < 0) { 2601 /* it's for sure, some broken apps don't check for error codes */ 2602 put_user(0, p); 2603 return res; 2604 } 2605 return put_user(res, p); 2606 case SNDCTL_DSP_PROFILE: 2607 return 0; /* silently ignore */ 2608 default: 2609 pr_debug("pcm_oss: unknown command = 0x%x\n", cmd); 2610 } 2611 return -EINVAL; 2612 } 2613 2614 #ifdef CONFIG_COMPAT 2615 /* all compatible */ 2616 static long snd_pcm_oss_ioctl_compat(struct file *file, unsigned int cmd, 2617 unsigned long arg) 2618 { 2619 return snd_pcm_oss_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); 2620 } 2621 #else 2622 #define snd_pcm_oss_ioctl_compat NULL 2623 #endif 2624 2625 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) 2626 { 2627 struct snd_pcm_oss_file *pcm_oss_file; 2628 struct snd_pcm_substream *substream; 2629 2630 pcm_oss_file = file->private_data; 2631 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2632 if (substream == NULL) 2633 return -ENXIO; 2634 substream->f_flags = file->f_flags & O_NONBLOCK; 2635 #ifndef OSS_DEBUG 2636 return snd_pcm_oss_read1(substream, buf, count); 2637 #else 2638 { 2639 ssize_t res = snd_pcm_oss_read1(substream, buf, count); 2640 pcm_dbg(substream->pcm, 2641 "pcm_oss: read %li bytes (returned %li bytes)\n", 2642 (long)count, (long)res); 2643 return res; 2644 } 2645 #endif 2646 } 2647 2648 static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) 2649 { 2650 struct snd_pcm_oss_file *pcm_oss_file; 2651 struct snd_pcm_substream *substream; 2652 long result; 2653 2654 pcm_oss_file = file->private_data; 2655 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2656 if (substream == NULL) 2657 return -ENXIO; 2658 substream->f_flags = file->f_flags & O_NONBLOCK; 2659 result = snd_pcm_oss_write1(substream, buf, count); 2660 #ifdef OSS_DEBUG 2661 pcm_dbg(substream->pcm, "pcm_oss: write %li bytes (wrote %li bytes)\n", 2662 (long)count, (long)result); 2663 #endif 2664 return result; 2665 } 2666 2667 static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) 2668 { 2669 struct snd_pcm_runtime *runtime = substream->runtime; 2670 if (atomic_read(&substream->mmap_count)) 2671 return runtime->oss.prev_hw_ptr_period != 2672 get_hw_ptr_period(runtime); 2673 else 2674 return snd_pcm_playback_avail(runtime) >= 2675 runtime->oss.period_frames; 2676 } 2677 2678 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) 2679 { 2680 struct snd_pcm_runtime *runtime = substream->runtime; 2681 if (atomic_read(&substream->mmap_count)) 2682 return runtime->oss.prev_hw_ptr_period != 2683 get_hw_ptr_period(runtime); 2684 else 2685 return snd_pcm_capture_avail(runtime) >= 2686 runtime->oss.period_frames; 2687 } 2688 2689 static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) 2690 { 2691 struct snd_pcm_oss_file *pcm_oss_file; 2692 __poll_t mask; 2693 struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL; 2694 2695 pcm_oss_file = file->private_data; 2696 2697 psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2698 csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2699 2700 mask = 0; 2701 if (psubstream != NULL) { 2702 struct snd_pcm_runtime *runtime = psubstream->runtime; 2703 poll_wait(file, &runtime->sleep, wait); 2704 snd_pcm_stream_lock_irq(psubstream); 2705 if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && 2706 (runtime->status->state != SNDRV_PCM_STATE_RUNNING || 2707 snd_pcm_oss_playback_ready(psubstream))) 2708 mask |= EPOLLOUT | EPOLLWRNORM; 2709 snd_pcm_stream_unlock_irq(psubstream); 2710 } 2711 if (csubstream != NULL) { 2712 struct snd_pcm_runtime *runtime = csubstream->runtime; 2713 snd_pcm_state_t ostate; 2714 poll_wait(file, &runtime->sleep, wait); 2715 snd_pcm_stream_lock_irq(csubstream); 2716 if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || 2717 snd_pcm_oss_capture_ready(csubstream)) 2718 mask |= EPOLLIN | EPOLLRDNORM; 2719 snd_pcm_stream_unlock_irq(csubstream); 2720 if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) { 2721 struct snd_pcm_oss_file ofile; 2722 memset(&ofile, 0, sizeof(ofile)); 2723 ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2724 runtime->oss.trigger = 0; 2725 snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT); 2726 } 2727 } 2728 2729 return mask; 2730 } 2731 2732 static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area) 2733 { 2734 struct snd_pcm_oss_file *pcm_oss_file; 2735 struct snd_pcm_substream *substream = NULL; 2736 struct snd_pcm_runtime *runtime; 2737 int err; 2738 2739 #ifdef OSS_DEBUG 2740 pr_debug("pcm_oss: mmap begin\n"); 2741 #endif 2742 pcm_oss_file = file->private_data; 2743 switch ((area->vm_flags & (VM_READ | VM_WRITE))) { 2744 case VM_READ | VM_WRITE: 2745 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2746 if (substream) 2747 break; 2748 /* Fall through */ 2749 case VM_READ: 2750 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; 2751 break; 2752 case VM_WRITE: 2753 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; 2754 break; 2755 default: 2756 return -EINVAL; 2757 } 2758 /* set VM_READ access as well to fix memset() routines that do 2759 reads before writes (to improve performance) */ 2760 area->vm_flags |= VM_READ; 2761 if (substream == NULL) 2762 return -ENXIO; 2763 runtime = substream->runtime; 2764 if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID)) 2765 return -EIO; 2766 if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED) 2767 runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED; 2768 else 2769 return -EIO; 2770 2771 if (runtime->oss.params) { 2772 /* use mutex_trylock() for params_lock for avoiding a deadlock 2773 * between mmap_sem and params_lock taken by 2774 * copy_from/to_user() in snd_pcm_oss_write/read() 2775 */ 2776 err = snd_pcm_oss_change_params(substream, true); 2777 if (err < 0) 2778 return err; 2779 } 2780 #ifdef CONFIG_SND_PCM_OSS_PLUGINS 2781 if (runtime->oss.plugin_first != NULL) 2782 return -EIO; 2783 #endif 2784 2785 if (area->vm_pgoff != 0) 2786 return -EINVAL; 2787 2788 err = snd_pcm_mmap_data(substream, file, area); 2789 if (err < 0) 2790 return err; 2791 runtime->oss.mmap_bytes = area->vm_end - area->vm_start; 2792 runtime->silence_threshold = 0; 2793 runtime->silence_size = 0; 2794 #ifdef OSS_DEBUG 2795 pr_debug("pcm_oss: mmap ok, bytes = 0x%x\n", 2796 runtime->oss.mmap_bytes); 2797 #endif 2798 /* In mmap mode we never stop */ 2799 runtime->stop_threshold = runtime->boundary; 2800 2801 return 0; 2802 } 2803 2804 #ifdef CONFIG_SND_VERBOSE_PROCFS 2805 /* 2806 * /proc interface 2807 */ 2808 2809 static void snd_pcm_oss_proc_read(struct snd_info_entry *entry, 2810 struct snd_info_buffer *buffer) 2811 { 2812 struct snd_pcm_str *pstr = entry->private_data; 2813 struct snd_pcm_oss_setup *setup = pstr->oss.setup_list; 2814 mutex_lock(&pstr->oss.setup_mutex); 2815 while (setup) { 2816 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", 2817 setup->task_name, 2818 setup->periods, 2819 setup->period_size, 2820 setup->disable ? " disable" : "", 2821 setup->direct ? " direct" : "", 2822 setup->block ? " block" : "", 2823 setup->nonblock ? " non-block" : "", 2824 setup->partialfrag ? " partial-frag" : "", 2825 setup->nosilence ? " no-silence" : ""); 2826 setup = setup->next; 2827 } 2828 mutex_unlock(&pstr->oss.setup_mutex); 2829 } 2830 2831 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr) 2832 { 2833 struct snd_pcm_oss_setup *setup, *setupn; 2834 2835 for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL; 2836 setup; setup = setupn) { 2837 setupn = setup->next; 2838 kfree(setup->task_name); 2839 kfree(setup); 2840 } 2841 pstr->oss.setup_list = NULL; 2842 } 2843 2844 static void snd_pcm_oss_proc_write(struct snd_info_entry *entry, 2845 struct snd_info_buffer *buffer) 2846 { 2847 struct snd_pcm_str *pstr = entry->private_data; 2848 char line[128], str[32], task_name[32]; 2849 const char *ptr; 2850 int idx1; 2851 struct snd_pcm_oss_setup *setup, *setup1, template; 2852 2853 while (!snd_info_get_line(buffer, line, sizeof(line))) { 2854 mutex_lock(&pstr->oss.setup_mutex); 2855 memset(&template, 0, sizeof(template)); 2856 ptr = snd_info_get_str(task_name, line, sizeof(task_name)); 2857 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) { 2858 snd_pcm_oss_proc_free_setup_list(pstr); 2859 mutex_unlock(&pstr->oss.setup_mutex); 2860 continue; 2861 } 2862 for (setup = pstr->oss.setup_list; setup; setup = setup->next) { 2863 if (!strcmp(setup->task_name, task_name)) { 2864 template = *setup; 2865 break; 2866 } 2867 } 2868 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2869 template.periods = simple_strtoul(str, NULL, 10); 2870 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2871 template.period_size = simple_strtoul(str, NULL, 10); 2872 for (idx1 = 31; idx1 >= 0; idx1--) 2873 if (template.period_size & (1 << idx1)) 2874 break; 2875 for (idx1--; idx1 >= 0; idx1--) 2876 template.period_size &= ~(1 << idx1); 2877 do { 2878 ptr = snd_info_get_str(str, ptr, sizeof(str)); 2879 if (!strcmp(str, "disable")) { 2880 template.disable = 1; 2881 } else if (!strcmp(str, "direct")) { 2882 template.direct = 1; 2883 } else if (!strcmp(str, "block")) { 2884 template.block = 1; 2885 } else if (!strcmp(str, "non-block")) { 2886 template.nonblock = 1; 2887 } else if (!strcmp(str, "partial-frag")) { 2888 template.partialfrag = 1; 2889 } else if (!strcmp(str, "no-silence")) { 2890 template.nosilence = 1; 2891 } else if (!strcmp(str, "buggy-ptr")) { 2892 template.buggyptr = 1; 2893 } 2894 } while (*str); 2895 if (setup == NULL) { 2896 setup = kmalloc(sizeof(*setup), GFP_KERNEL); 2897 if (! setup) { 2898 buffer->error = -ENOMEM; 2899 mutex_unlock(&pstr->oss.setup_mutex); 2900 return; 2901 } 2902 if (pstr->oss.setup_list == NULL) 2903 pstr->oss.setup_list = setup; 2904 else { 2905 for (setup1 = pstr->oss.setup_list; 2906 setup1->next; setup1 = setup1->next); 2907 setup1->next = setup; 2908 } 2909 template.task_name = kstrdup(task_name, GFP_KERNEL); 2910 if (! template.task_name) { 2911 kfree(setup); 2912 buffer->error = -ENOMEM; 2913 mutex_unlock(&pstr->oss.setup_mutex); 2914 return; 2915 } 2916 } 2917 *setup = template; 2918 mutex_unlock(&pstr->oss.setup_mutex); 2919 } 2920 } 2921 2922 static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) 2923 { 2924 int stream; 2925 for (stream = 0; stream < 2; ++stream) { 2926 struct snd_info_entry *entry; 2927 struct snd_pcm_str *pstr = &pcm->streams[stream]; 2928 if (pstr->substream_count == 0) 2929 continue; 2930 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { 2931 entry->content = SNDRV_INFO_CONTENT_TEXT; 2932 entry->mode = S_IFREG | S_IRUGO | S_IWUSR; 2933 entry->c.text.read = snd_pcm_oss_proc_read; 2934 entry->c.text.write = snd_pcm_oss_proc_write; 2935 entry->private_data = pstr; 2936 if (snd_info_register(entry) < 0) { 2937 snd_info_free_entry(entry); 2938 entry = NULL; 2939 } 2940 } 2941 pstr->oss.proc_entry = entry; 2942 } 2943 } 2944 2945 static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) 2946 { 2947 int stream; 2948 for (stream = 0; stream < 2; ++stream) { 2949 struct snd_pcm_str *pstr = &pcm->streams[stream]; 2950 snd_info_free_entry(pstr->oss.proc_entry); 2951 pstr->oss.proc_entry = NULL; 2952 snd_pcm_oss_proc_free_setup_list(pstr); 2953 } 2954 } 2955 #else /* !CONFIG_SND_VERBOSE_PROCFS */ 2956 #define snd_pcm_oss_proc_init(pcm) 2957 #define snd_pcm_oss_proc_done(pcm) 2958 #endif /* CONFIG_SND_VERBOSE_PROCFS */ 2959 2960 /* 2961 * ENTRY functions 2962 */ 2963 2964 static const struct file_operations snd_pcm_oss_f_reg = 2965 { 2966 .owner = THIS_MODULE, 2967 .read = snd_pcm_oss_read, 2968 .write = snd_pcm_oss_write, 2969 .open = snd_pcm_oss_open, 2970 .release = snd_pcm_oss_release, 2971 .llseek = no_llseek, 2972 .poll = snd_pcm_oss_poll, 2973 .unlocked_ioctl = snd_pcm_oss_ioctl, 2974 .compat_ioctl = snd_pcm_oss_ioctl_compat, 2975 .mmap = snd_pcm_oss_mmap, 2976 }; 2977 2978 static void register_oss_dsp(struct snd_pcm *pcm, int index) 2979 { 2980 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 2981 pcm->card, index, &snd_pcm_oss_f_reg, 2982 pcm) < 0) { 2983 pcm_err(pcm, "unable to register OSS PCM device %i:%i\n", 2984 pcm->card->number, pcm->device); 2985 } 2986 } 2987 2988 static int snd_pcm_oss_register_minor(struct snd_pcm *pcm) 2989 { 2990 pcm->oss.reg = 0; 2991 if (dsp_map[pcm->card->number] == (int)pcm->device) { 2992 char name[128]; 2993 int duplex; 2994 register_oss_dsp(pcm, 0); 2995 duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 2996 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 2997 !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)); 2998 sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : ""); 2999 #ifdef SNDRV_OSS_INFO_DEV_AUDIO 3000 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO, 3001 pcm->card->number, 3002 name); 3003 #endif 3004 pcm->oss.reg++; 3005 pcm->oss.reg_mask |= 1; 3006 } 3007 if (adsp_map[pcm->card->number] == (int)pcm->device) { 3008 register_oss_dsp(pcm, 1); 3009 pcm->oss.reg++; 3010 pcm->oss.reg_mask |= 2; 3011 } 3012 3013 if (pcm->oss.reg) 3014 snd_pcm_oss_proc_init(pcm); 3015 3016 return 0; 3017 } 3018 3019 static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) 3020 { 3021 if (pcm->oss.reg) { 3022 if (pcm->oss.reg_mask & 1) { 3023 pcm->oss.reg_mask &= ~1; 3024 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 3025 pcm->card, 0); 3026 } 3027 if (pcm->oss.reg_mask & 2) { 3028 pcm->oss.reg_mask &= ~2; 3029 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 3030 pcm->card, 1); 3031 } 3032 if (dsp_map[pcm->card->number] == (int)pcm->device) { 3033 #ifdef SNDRV_OSS_INFO_DEV_AUDIO 3034 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); 3035 #endif 3036 } 3037 pcm->oss.reg = 0; 3038 } 3039 return 0; 3040 } 3041 3042 static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) 3043 { 3044 snd_pcm_oss_disconnect_minor(pcm); 3045 snd_pcm_oss_proc_done(pcm); 3046 return 0; 3047 } 3048 3049 static struct snd_pcm_notify snd_pcm_oss_notify = 3050 { 3051 .n_register = snd_pcm_oss_register_minor, 3052 .n_disconnect = snd_pcm_oss_disconnect_minor, 3053 .n_unregister = snd_pcm_oss_unregister_minor, 3054 }; 3055 3056 static int __init alsa_pcm_oss_init(void) 3057 { 3058 int i; 3059 int err; 3060 3061 /* check device map table */ 3062 for (i = 0; i < SNDRV_CARDS; i++) { 3063 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) { 3064 pr_err("ALSA: pcm_oss: invalid dsp_map[%d] = %d\n", 3065 i, dsp_map[i]); 3066 dsp_map[i] = 0; 3067 } 3068 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) { 3069 pr_err("ALSA: pcm_oss: invalid adsp_map[%d] = %d\n", 3070 i, adsp_map[i]); 3071 adsp_map[i] = 1; 3072 } 3073 } 3074 if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0) 3075 return err; 3076 return 0; 3077 } 3078 3079 static void __exit alsa_pcm_oss_exit(void) 3080 { 3081 snd_pcm_notify(&snd_pcm_oss_notify, 1); 3082 } 3083 3084 module_init(alsa_pcm_oss_init) 3085 module_exit(alsa_pcm_oss_exit) 3086