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