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