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