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