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