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