de1917484647ee52e5dc78d49992f1aaf11d8ec4
[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         int fragshift;
1939
1940         runtime = substream->runtime;
1941         if (runtime->oss.subdivision || runtime->oss.fragshift)
1942                 return -EINVAL;
1943         fragshift = val & 0xffff;
1944         if (fragshift >= 31)
1945                 return -EINVAL;
1946         runtime->oss.fragshift = fragshift;
1947         runtime->oss.maxfrags = (val >> 16) & 0xffff;
1948         if (runtime->oss.fragshift < 4)         /* < 16 */
1949                 runtime->oss.fragshift = 4;
1950         if (runtime->oss.maxfrags < 2)
1951                 runtime->oss.maxfrags = 2;
1952         runtime->oss.params = 1;
1953         return 0;
1954 }
1955
1956 static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val)
1957 {
1958         int err = -EINVAL, idx;
1959
1960         for (idx = 1; idx >= 0; --idx) {
1961                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
1962                 struct snd_pcm_runtime *runtime;
1963
1964                 if (substream == NULL)
1965                         continue;
1966                 runtime = substream->runtime;
1967                 err = lock_params(runtime);
1968                 if (err < 0)
1969                         return err;
1970                 err = snd_pcm_oss_set_fragment1(substream, val);
1971                 unlock_params(runtime);
1972                 if (err < 0)
1973                         return err;
1974         }
1975         return err;
1976 }
1977
1978 static int snd_pcm_oss_nonblock(struct file * file)
1979 {
1980         spin_lock(&file->f_lock);
1981         file->f_flags |= O_NONBLOCK;
1982         spin_unlock(&file->f_lock);
1983         return 0;
1984 }
1985
1986 static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res)
1987 {
1988
1989         if (substream == NULL) {
1990                 res &= ~DSP_CAP_DUPLEX;
1991                 return res;
1992         }
1993 #ifdef DSP_CAP_MULTI
1994         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
1995                 if (substream->pstr->substream_count > 1)
1996                         res |= DSP_CAP_MULTI;
1997 #endif
1998         /* DSP_CAP_REALTIME is set all times: */
1999         /* all ALSA drivers can return actual pointer in ring buffer */
2000 #if defined(DSP_CAP_REALTIME) && 0
2001         {
2002                 struct snd_pcm_runtime *runtime = substream->runtime;
2003                 if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH))
2004                         res &= ~DSP_CAP_REALTIME;
2005         }
2006 #endif
2007         return res;
2008 }
2009
2010 static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file)
2011 {
2012         int result, idx;
2013         
2014         result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME;
2015         for (idx = 0; idx < 2; idx++) {
2016                 struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
2017                 result = snd_pcm_oss_get_caps1(substream, result);
2018         }
2019         result |= 0x0001;       /* revision - same as SB AWE 64 */
2020         return result;
2021 }
2022
2023 static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream,
2024                                       snd_pcm_uframes_t hw_ptr)
2025 {
2026         struct snd_pcm_runtime *runtime = substream->runtime;
2027         snd_pcm_uframes_t appl_ptr;
2028         appl_ptr = hw_ptr + runtime->buffer_size;
2029         appl_ptr %= runtime->boundary;
2030         runtime->control->appl_ptr = appl_ptr;
2031 }
2032
2033 static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger)
2034 {
2035         struct snd_pcm_runtime *runtime;
2036         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
2037         int err, cmd;
2038
2039 #ifdef OSS_DEBUG
2040         pcm_dbg(substream->pcm, "pcm_oss: trigger = 0x%x\n", trigger);
2041 #endif
2042         
2043         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2044         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2045
2046         if (psubstream) {
2047                 if ((err = snd_pcm_oss_make_ready(psubstream)) < 0)
2048                         return err;
2049         }
2050         if (csubstream) {
2051                 if ((err = snd_pcm_oss_make_ready(csubstream)) < 0)
2052                         return err;
2053         }
2054         if (psubstream) {
2055                 runtime = psubstream->runtime;
2056                 cmd = 0;
2057                 if (mutex_lock_interruptible(&runtime->oss.params_lock))
2058                         return -ERESTARTSYS;
2059                 if (trigger & PCM_ENABLE_OUTPUT) {
2060                         if (runtime->oss.trigger)
2061                                 goto _skip1;
2062                         if (atomic_read(&psubstream->mmap_count))
2063                                 snd_pcm_oss_simulate_fill(psubstream,
2064                                                 get_hw_ptr_period(runtime));
2065                         runtime->oss.trigger = 1;
2066                         runtime->start_threshold = 1;
2067                         cmd = SNDRV_PCM_IOCTL_START;
2068                 } else {
2069                         if (!runtime->oss.trigger)
2070                                 goto _skip1;
2071                         runtime->oss.trigger = 0;
2072                         runtime->start_threshold = runtime->boundary;
2073                         cmd = SNDRV_PCM_IOCTL_DROP;
2074                         runtime->oss.prepare = 1;
2075                 }
2076  _skip1:
2077                 mutex_unlock(&runtime->oss.params_lock);
2078                 if (cmd) {
2079                         err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL);
2080                         if (err < 0)
2081                                 return err;
2082                 }
2083         }
2084         if (csubstream) {
2085                 runtime = csubstream->runtime;
2086                 cmd = 0;
2087                 if (mutex_lock_interruptible(&runtime->oss.params_lock))
2088                         return -ERESTARTSYS;
2089                 if (trigger & PCM_ENABLE_INPUT) {
2090                         if (runtime->oss.trigger)
2091                                 goto _skip2;
2092                         runtime->oss.trigger = 1;
2093                         runtime->start_threshold = 1;
2094                         cmd = SNDRV_PCM_IOCTL_START;
2095                 } else {
2096                         if (!runtime->oss.trigger)
2097                                 goto _skip2;
2098                         runtime->oss.trigger = 0;
2099                         runtime->start_threshold = runtime->boundary;
2100                         cmd = SNDRV_PCM_IOCTL_DROP;
2101                         runtime->oss.prepare = 1;
2102                 }
2103  _skip2:
2104                 mutex_unlock(&runtime->oss.params_lock);
2105                 if (cmd) {
2106                         err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL);
2107                         if (err < 0)
2108                                 return err;
2109                 }
2110         }
2111         return 0;
2112 }
2113
2114 static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
2115 {
2116         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
2117         int result = 0;
2118
2119         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2120         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2121         if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
2122                 result |= PCM_ENABLE_OUTPUT;
2123         if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
2124                 result |= PCM_ENABLE_INPUT;
2125         return result;
2126 }
2127
2128 static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
2129 {
2130         struct snd_pcm_substream *substream;
2131         struct snd_pcm_runtime *runtime;
2132         snd_pcm_sframes_t delay;
2133         int err;
2134
2135         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2136         if (substream == NULL)
2137                 return -EINVAL;
2138         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2139                 return err;
2140         runtime = substream->runtime;
2141         if (runtime->oss.params || runtime->oss.prepare)
2142                 return 0;
2143         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
2144         if (err == -EPIPE)
2145                 delay = 0;      /* hack for broken OSS applications */
2146         else if (err < 0)
2147                 return err;
2148         return snd_pcm_oss_bytes(substream, delay);
2149 }
2150
2151 static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info)
2152 {       
2153         struct snd_pcm_substream *substream;
2154         struct snd_pcm_runtime *runtime;
2155         snd_pcm_sframes_t delay;
2156         int fixup;
2157         struct count_info info;
2158         int err;
2159
2160         if (_info == NULL)
2161                 return -EFAULT;
2162         substream = pcm_oss_file->streams[stream];
2163         if (substream == NULL)
2164                 return -EINVAL;
2165         if ((err = snd_pcm_oss_make_ready(substream)) < 0)
2166                 return err;
2167         runtime = substream->runtime;
2168         if (runtime->oss.params || runtime->oss.prepare) {
2169                 memset(&info, 0, sizeof(info));
2170                 if (copy_to_user(_info, &info, sizeof(info)))
2171                         return -EFAULT;
2172                 return 0;
2173         }
2174         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2175                 err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
2176                 if (err == -EPIPE || err == -ESTRPIPE || (! err && delay < 0)) {
2177                         err = 0;
2178                         delay = 0;
2179                         fixup = 0;
2180                 } else {
2181                         fixup = runtime->oss.buffer_used;
2182                 }
2183         } else {
2184                 err = snd_pcm_oss_capture_position_fixup(substream, &delay);
2185                 fixup = -runtime->oss.buffer_used;
2186         }
2187         if (err < 0)
2188                 return err;
2189         info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
2190         if (atomic_read(&substream->mmap_count)) {
2191                 snd_pcm_sframes_t n;
2192                 delay = get_hw_ptr_period(runtime);
2193                 n = delay - runtime->oss.prev_hw_ptr_period;
2194                 if (n < 0)
2195                         n += runtime->boundary;
2196                 info.blocks = n / runtime->period_size;
2197                 runtime->oss.prev_hw_ptr_period = delay;
2198                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
2199                         snd_pcm_oss_simulate_fill(substream, delay);
2200                 info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
2201         } else {
2202                 delay = snd_pcm_oss_bytes(substream, delay);
2203                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2204                         if (substream->oss.setup.buggyptr)
2205                                 info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
2206                         else
2207                                 info.blocks = (delay + fixup) / runtime->oss.period_bytes;
2208                         info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
2209                 } else {
2210                         delay += fixup;
2211                         info.blocks = delay / runtime->oss.period_bytes;
2212                         info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
2213                 }
2214         }
2215         if (copy_to_user(_info, &info, sizeof(info)))
2216                 return -EFAULT;
2217         return 0;
2218 }
2219
2220 static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info)
2221 {
2222         struct snd_pcm_substream *substream;
2223         struct snd_pcm_runtime *runtime;
2224         snd_pcm_sframes_t avail;
2225         int fixup;
2226         struct audio_buf_info info;
2227         int err;
2228
2229         if (_info == NULL)
2230                 return -EFAULT;
2231         substream = pcm_oss_file->streams[stream];
2232         if (substream == NULL)
2233                 return -EINVAL;
2234         runtime = substream->runtime;
2235
2236         if (runtime->oss.params &&
2237             (err = snd_pcm_oss_change_params(substream, false)) < 0)
2238                 return err;
2239
2240         info.fragsize = runtime->oss.period_bytes;
2241         info.fragstotal = runtime->periods;
2242         if (runtime->oss.prepare) {
2243                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2244                         info.bytes = runtime->oss.period_bytes * runtime->oss.periods;
2245                         info.fragments = runtime->oss.periods;
2246                 } else {
2247                         info.bytes = 0;
2248                         info.fragments = 0;
2249                 }
2250         } else {
2251                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
2252                         err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);
2253                         if (err == -EPIPE || err == -ESTRPIPE || (! err && avail < 0)) {
2254                                 avail = runtime->buffer_size;
2255                                 err = 0;
2256                                 fixup = 0;
2257                         } else {
2258                                 avail = runtime->buffer_size - avail;
2259                                 fixup = -runtime->oss.buffer_used;
2260                         }
2261                 } else {
2262                         err = snd_pcm_oss_capture_position_fixup(substream, &avail);
2263                         fixup = runtime->oss.buffer_used;
2264                 }
2265                 if (err < 0)
2266                         return err;
2267                 info.bytes = snd_pcm_oss_bytes(substream, avail) + fixup;
2268                 info.fragments = info.bytes / runtime->oss.period_bytes;
2269         }
2270
2271 #ifdef OSS_DEBUG
2272         pcm_dbg(substream->pcm,
2273                 "pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n",
2274                 info.bytes, info.fragments, info.fragstotal, info.fragsize);
2275 #endif
2276         if (copy_to_user(_info, &info, sizeof(info)))
2277                 return -EFAULT;
2278         return 0;
2279 }
2280
2281 static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info)
2282 {
2283         // it won't be probably implemented
2284         // pr_debug("TODO: snd_pcm_oss_get_mapbuf\n");
2285         return -EINVAL;
2286 }
2287
2288 static const char *strip_task_path(const char *path)
2289 {
2290         const char *ptr, *ptrl = NULL;
2291         for (ptr = path; *ptr; ptr++) {
2292                 if (*ptr == '/')
2293                         ptrl = ptr + 1;
2294         }
2295         return ptrl;
2296 }
2297
2298 static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
2299                                       const char *task_name,
2300                                       struct snd_pcm_oss_setup *rsetup)
2301 {
2302         struct snd_pcm_oss_setup *setup;
2303
2304         mutex_lock(&pcm->streams[stream].oss.setup_mutex);
2305         do {
2306                 for (setup = pcm->streams[stream].oss.setup_list; setup;
2307                      setup = setup->next) {
2308                         if (!strcmp(setup->task_name, task_name))
2309                                 goto out;
2310                 }
2311         } while ((task_name = strip_task_path(task_name)) != NULL);
2312  out:
2313         if (setup)
2314                 *rsetup = *setup;
2315         mutex_unlock(&pcm->streams[stream].oss.setup_mutex);
2316 }
2317
2318 static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
2319 {
2320         struct snd_pcm_runtime *runtime;
2321         runtime = substream->runtime;
2322         kvfree(runtime->oss.buffer);
2323         runtime->oss.buffer = NULL;
2324 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2325         snd_pcm_oss_plugin_clear(substream);
2326 #endif
2327         substream->oss.oss = 0;
2328 }
2329
2330 static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
2331                                        struct snd_pcm_oss_setup *setup,
2332                                        int minor)
2333 {
2334         struct snd_pcm_runtime *runtime;
2335
2336         substream->oss.oss = 1;
2337         substream->oss.setup = *setup;
2338         if (setup->nonblock)
2339                 substream->f_flags |= O_NONBLOCK;
2340         else if (setup->block)
2341                 substream->f_flags &= ~O_NONBLOCK;
2342         runtime = substream->runtime;
2343         runtime->oss.params = 1;
2344         runtime->oss.trigger = 1;
2345         runtime->oss.rate = 8000;
2346         mutex_init(&runtime->oss.params_lock);
2347         switch (SNDRV_MINOR_OSS_DEVICE(minor)) {
2348         case SNDRV_MINOR_OSS_PCM_8:
2349                 runtime->oss.format = AFMT_U8;
2350                 break;
2351         case SNDRV_MINOR_OSS_PCM_16:
2352                 runtime->oss.format = AFMT_S16_LE;
2353                 break;
2354         default:
2355                 runtime->oss.format = AFMT_MU_LAW;
2356         }
2357         runtime->oss.channels = 1;
2358         runtime->oss.fragshift = 0;
2359         runtime->oss.maxfrags = 0;
2360         runtime->oss.subdivision = 0;
2361         substream->pcm_release = snd_pcm_oss_release_substream;
2362         atomic_set(&runtime->oss.rw_ref, 0);
2363 }
2364
2365 static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
2366 {
2367         int cidx;
2368         if (!pcm_oss_file)
2369                 return 0;
2370         for (cidx = 0; cidx < 2; ++cidx) {
2371                 struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
2372                 if (substream)
2373                         snd_pcm_release_substream(substream);
2374         }
2375         kfree(pcm_oss_file);
2376         return 0;
2377 }
2378
2379 static int snd_pcm_oss_open_file(struct file *file,
2380                                  struct snd_pcm *pcm,
2381                                  struct snd_pcm_oss_file **rpcm_oss_file,
2382                                  int minor,
2383                                  struct snd_pcm_oss_setup *setup)
2384 {
2385         int idx, err;
2386         struct snd_pcm_oss_file *pcm_oss_file;
2387         struct snd_pcm_substream *substream;
2388         fmode_t f_mode = file->f_mode;
2389
2390         if (rpcm_oss_file)
2391                 *rpcm_oss_file = NULL;
2392
2393         pcm_oss_file = kzalloc(sizeof(*pcm_oss_file), GFP_KERNEL);
2394         if (pcm_oss_file == NULL)
2395                 return -ENOMEM;
2396
2397         if ((f_mode & (FMODE_WRITE|FMODE_READ)) == (FMODE_WRITE|FMODE_READ) &&
2398             (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
2399                 f_mode = FMODE_WRITE;
2400
2401         file->f_flags &= ~O_APPEND;
2402         for (idx = 0; idx < 2; idx++) {
2403                 if (setup[idx].disable)
2404                         continue;
2405                 if (! pcm->streams[idx].substream_count)
2406                         continue; /* no matching substream */
2407                 if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
2408                         if (! (f_mode & FMODE_WRITE))
2409                                 continue;
2410                 } else {
2411                         if (! (f_mode & FMODE_READ))
2412                                 continue;
2413                 }
2414                 err = snd_pcm_open_substream(pcm, idx, file, &substream);
2415                 if (err < 0) {
2416                         snd_pcm_oss_release_file(pcm_oss_file);
2417                         return err;
2418                 }
2419
2420                 pcm_oss_file->streams[idx] = substream;
2421                 snd_pcm_oss_init_substream(substream, &setup[idx], minor);
2422         }
2423         
2424         if (!pcm_oss_file->streams[0] && !pcm_oss_file->streams[1]) {
2425                 snd_pcm_oss_release_file(pcm_oss_file);
2426                 return -EINVAL;
2427         }
2428
2429         file->private_data = pcm_oss_file;
2430         if (rpcm_oss_file)
2431                 *rpcm_oss_file = pcm_oss_file;
2432         return 0;
2433 }
2434
2435
2436 static int snd_task_name(struct task_struct *task, char *name, size_t size)
2437 {
2438         unsigned int idx;
2439
2440         if (snd_BUG_ON(!task || !name || size < 2))
2441                 return -EINVAL;
2442         for (idx = 0; idx < sizeof(task->comm) && idx + 1 < size; idx++)
2443                 name[idx] = task->comm[idx];
2444         name[idx] = '\0';
2445         return 0;
2446 }
2447
2448 static int snd_pcm_oss_open(struct inode *inode, struct file *file)
2449 {
2450         int err;
2451         char task_name[32];
2452         struct snd_pcm *pcm;
2453         struct snd_pcm_oss_file *pcm_oss_file;
2454         struct snd_pcm_oss_setup setup[2];
2455         int nonblock;
2456         wait_queue_entry_t wait;
2457
2458         err = nonseekable_open(inode, file);
2459         if (err < 0)
2460                 return err;
2461
2462         pcm = snd_lookup_oss_minor_data(iminor(inode),
2463                                         SNDRV_OSS_DEVICE_TYPE_PCM);
2464         if (pcm == NULL) {
2465                 err = -ENODEV;
2466                 goto __error1;
2467         }
2468         err = snd_card_file_add(pcm->card, file);
2469         if (err < 0)
2470                 goto __error1;
2471         if (!try_module_get(pcm->card->module)) {
2472                 err = -EFAULT;
2473                 goto __error2;
2474         }
2475         if (snd_task_name(current, task_name, sizeof(task_name)) < 0) {
2476                 err = -EFAULT;
2477                 goto __error;
2478         }
2479         memset(setup, 0, sizeof(setup));
2480         if (file->f_mode & FMODE_WRITE)
2481                 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK,
2482                                            task_name, &setup[0]);
2483         if (file->f_mode & FMODE_READ)
2484                 snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_CAPTURE,
2485                                            task_name, &setup[1]);
2486
2487         nonblock = !!(file->f_flags & O_NONBLOCK);
2488         if (!nonblock)
2489                 nonblock = nonblock_open;
2490
2491         init_waitqueue_entry(&wait, current);
2492         add_wait_queue(&pcm->open_wait, &wait);
2493         mutex_lock(&pcm->open_mutex);
2494         while (1) {
2495                 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
2496                                             iminor(inode), setup);
2497                 if (err >= 0)
2498                         break;
2499                 if (err == -EAGAIN) {
2500                         if (nonblock) {
2501                                 err = -EBUSY;
2502                                 break;
2503                         }
2504                 } else
2505                         break;
2506                 set_current_state(TASK_INTERRUPTIBLE);
2507                 mutex_unlock(&pcm->open_mutex);
2508                 schedule();
2509                 mutex_lock(&pcm->open_mutex);
2510                 if (pcm->card->shutdown) {
2511                         err = -ENODEV;
2512                         break;
2513                 }
2514                 if (signal_pending(current)) {
2515                         err = -ERESTARTSYS;
2516                         break;
2517                 }
2518         }
2519         remove_wait_queue(&pcm->open_wait, &wait);
2520         mutex_unlock(&pcm->open_mutex);
2521         if (err < 0)
2522                 goto __error;
2523         snd_card_unref(pcm->card);
2524         return err;
2525
2526       __error:
2527         module_put(pcm->card->module);
2528       __error2:
2529         snd_card_file_remove(pcm->card, file);
2530       __error1:
2531         if (pcm)
2532                 snd_card_unref(pcm->card);
2533         return err;
2534 }
2535
2536 static int snd_pcm_oss_release(struct inode *inode, struct file *file)
2537 {
2538         struct snd_pcm *pcm;
2539         struct snd_pcm_substream *substream;
2540         struct snd_pcm_oss_file *pcm_oss_file;
2541
2542         pcm_oss_file = file->private_data;
2543         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2544         if (substream == NULL)
2545                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2546         if (snd_BUG_ON(!substream))
2547                 return -ENXIO;
2548         pcm = substream->pcm;
2549         if (!pcm->card->shutdown)
2550                 snd_pcm_oss_sync(pcm_oss_file);
2551         mutex_lock(&pcm->open_mutex);
2552         snd_pcm_oss_release_file(pcm_oss_file);
2553         mutex_unlock(&pcm->open_mutex);
2554         wake_up(&pcm->open_wait);
2555         module_put(pcm->card->module);
2556         snd_card_file_remove(pcm->card, file);
2557         return 0;
2558 }
2559
2560 static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2561 {
2562         struct snd_pcm_oss_file *pcm_oss_file;
2563         int __user *p = (int __user *)arg;
2564         int res;
2565
2566         pcm_oss_file = file->private_data;
2567         if (cmd == OSS_GETVERSION)
2568                 return put_user(SNDRV_OSS_VERSION, p);
2569         if (cmd == OSS_ALSAEMULVER)
2570                 return put_user(1, p);
2571 #if IS_REACHABLE(CONFIG_SND_MIXER_OSS)
2572         if (((cmd >> 8) & 0xff) == 'M') {       /* mixer ioctl - for OSS compatibility */
2573                 struct snd_pcm_substream *substream;
2574                 int idx;
2575                 for (idx = 0; idx < 2; ++idx) {
2576                         substream = pcm_oss_file->streams[idx];
2577                         if (substream != NULL)
2578                                 break;
2579                 }
2580                 if (snd_BUG_ON(idx >= 2))
2581                         return -ENXIO;
2582                 return snd_mixer_oss_ioctl_card(substream->pcm->card, cmd, arg);
2583         }
2584 #endif
2585         if (((cmd >> 8) & 0xff) != 'P')
2586                 return -EINVAL;
2587 #ifdef OSS_DEBUG
2588         pr_debug("pcm_oss: ioctl = 0x%x\n", cmd);
2589 #endif
2590         switch (cmd) {
2591         case SNDCTL_DSP_RESET:
2592                 return snd_pcm_oss_reset(pcm_oss_file);
2593         case SNDCTL_DSP_SYNC:
2594                 return snd_pcm_oss_sync(pcm_oss_file);
2595         case SNDCTL_DSP_SPEED:
2596                 if (get_user(res, p))
2597                         return -EFAULT;
2598                 if ((res = snd_pcm_oss_set_rate(pcm_oss_file, res))<0)
2599                         return res;
2600                 return put_user(res, p);
2601         case SOUND_PCM_READ_RATE:
2602                 res = snd_pcm_oss_get_rate(pcm_oss_file);
2603                 if (res < 0)
2604                         return res;
2605                 return put_user(res, p);
2606         case SNDCTL_DSP_STEREO:
2607                 if (get_user(res, p))
2608                         return -EFAULT;
2609                 res = res > 0 ? 2 : 1;
2610                 if ((res = snd_pcm_oss_set_channels(pcm_oss_file, res)) < 0)
2611                         return res;
2612                 return put_user(--res, p);
2613         case SNDCTL_DSP_GETBLKSIZE:
2614                 res = snd_pcm_oss_get_block_size(pcm_oss_file);
2615                 if (res < 0)
2616                         return res;
2617                 return put_user(res, p);
2618         case SNDCTL_DSP_SETFMT:
2619                 if (get_user(res, p))
2620                         return -EFAULT;
2621                 res = snd_pcm_oss_set_format(pcm_oss_file, res);
2622                 if (res < 0)
2623                         return res;
2624                 return put_user(res, p);
2625         case SOUND_PCM_READ_BITS:
2626                 res = snd_pcm_oss_get_format(pcm_oss_file);
2627                 if (res < 0)
2628                         return res;
2629                 return put_user(res, p);
2630         case SNDCTL_DSP_CHANNELS:
2631                 if (get_user(res, p))
2632                         return -EFAULT;
2633                 res = snd_pcm_oss_set_channels(pcm_oss_file, res);
2634                 if (res < 0)
2635                         return res;
2636                 return put_user(res, p);
2637         case SOUND_PCM_READ_CHANNELS:
2638                 res = snd_pcm_oss_get_channels(pcm_oss_file);
2639                 if (res < 0)
2640                         return res;
2641                 return put_user(res, p);
2642         case SOUND_PCM_WRITE_FILTER:
2643         case SOUND_PCM_READ_FILTER:
2644                 return -EIO;
2645         case SNDCTL_DSP_POST:
2646                 return snd_pcm_oss_post(pcm_oss_file);
2647         case SNDCTL_DSP_SUBDIVIDE:
2648                 if (get_user(res, p))
2649                         return -EFAULT;
2650                 res = snd_pcm_oss_set_subdivide(pcm_oss_file, res);
2651                 if (res < 0)
2652                         return res;
2653                 return put_user(res, p);
2654         case SNDCTL_DSP_SETFRAGMENT:
2655                 if (get_user(res, p))
2656                         return -EFAULT;
2657                 return snd_pcm_oss_set_fragment(pcm_oss_file, res);
2658         case SNDCTL_DSP_GETFMTS:
2659                 res = snd_pcm_oss_get_formats(pcm_oss_file);
2660                 if (res < 0)
2661                         return res;
2662                 return put_user(res, p);
2663         case SNDCTL_DSP_GETOSPACE:
2664         case SNDCTL_DSP_GETISPACE:
2665                 return snd_pcm_oss_get_space(pcm_oss_file,
2666                         cmd == SNDCTL_DSP_GETISPACE ?
2667                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2668                         (struct audio_buf_info __user *) arg);
2669         case SNDCTL_DSP_NONBLOCK:
2670                 return snd_pcm_oss_nonblock(file);
2671         case SNDCTL_DSP_GETCAPS:
2672                 res = snd_pcm_oss_get_caps(pcm_oss_file);
2673                 if (res < 0)
2674                         return res;
2675                 return put_user(res, p);
2676         case SNDCTL_DSP_GETTRIGGER:
2677                 res = snd_pcm_oss_get_trigger(pcm_oss_file);
2678                 if (res < 0)
2679                         return res;
2680                 return put_user(res, p);
2681         case SNDCTL_DSP_SETTRIGGER:
2682                 if (get_user(res, p))
2683                         return -EFAULT;
2684                 return snd_pcm_oss_set_trigger(pcm_oss_file, res);
2685         case SNDCTL_DSP_GETIPTR:
2686         case SNDCTL_DSP_GETOPTR:
2687                 return snd_pcm_oss_get_ptr(pcm_oss_file,
2688                         cmd == SNDCTL_DSP_GETIPTR ?
2689                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2690                         (struct count_info __user *) arg);
2691         case SNDCTL_DSP_MAPINBUF:
2692         case SNDCTL_DSP_MAPOUTBUF:
2693                 return snd_pcm_oss_get_mapbuf(pcm_oss_file,
2694                         cmd == SNDCTL_DSP_MAPINBUF ?
2695                                 SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK,
2696                         (struct buffmem_desc __user *) arg);
2697         case SNDCTL_DSP_SETSYNCRO:
2698                 /* stop DMA now.. */
2699                 return 0;
2700         case SNDCTL_DSP_SETDUPLEX:
2701                 if (snd_pcm_oss_get_caps(pcm_oss_file) & DSP_CAP_DUPLEX)
2702                         return 0;
2703                 return -EIO;
2704         case SNDCTL_DSP_GETODELAY:
2705                 res = snd_pcm_oss_get_odelay(pcm_oss_file);
2706                 if (res < 0) {
2707                         /* it's for sure, some broken apps don't check for error codes */
2708                         put_user(0, p);
2709                         return res;
2710                 }
2711                 return put_user(res, p);
2712         case SNDCTL_DSP_PROFILE:
2713                 return 0;       /* silently ignore */
2714         default:
2715                 pr_debug("pcm_oss: unknown command = 0x%x\n", cmd);
2716         }
2717         return -EINVAL;
2718 }
2719
2720 #ifdef CONFIG_COMPAT
2721 /* all compatible */
2722 static long snd_pcm_oss_ioctl_compat(struct file *file, unsigned int cmd,
2723                                      unsigned long arg)
2724 {
2725         /*
2726          * Everything is compatbile except SNDCTL_DSP_MAPINBUF/SNDCTL_DSP_MAPOUTBUF,
2727          * which are not implemented for the native case either
2728          */
2729         return snd_pcm_oss_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
2730 }
2731 #else
2732 #define snd_pcm_oss_ioctl_compat        NULL
2733 #endif
2734
2735 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
2736 {
2737         struct snd_pcm_oss_file *pcm_oss_file;
2738         struct snd_pcm_substream *substream;
2739
2740         pcm_oss_file = file->private_data;
2741         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2742         if (substream == NULL)
2743                 return -ENXIO;
2744         substream->f_flags = file->f_flags & O_NONBLOCK;
2745 #ifndef OSS_DEBUG
2746         return snd_pcm_oss_read1(substream, buf, count);
2747 #else
2748         {
2749                 ssize_t res = snd_pcm_oss_read1(substream, buf, count);
2750                 pcm_dbg(substream->pcm,
2751                         "pcm_oss: read %li bytes (returned %li bytes)\n",
2752                         (long)count, (long)res);
2753                 return res;
2754         }
2755 #endif
2756 }
2757
2758 static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
2759 {
2760         struct snd_pcm_oss_file *pcm_oss_file;
2761         struct snd_pcm_substream *substream;
2762         long result;
2763
2764         pcm_oss_file = file->private_data;
2765         substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2766         if (substream == NULL)
2767                 return -ENXIO;
2768         substream->f_flags = file->f_flags & O_NONBLOCK;
2769         result = snd_pcm_oss_write1(substream, buf, count);
2770 #ifdef OSS_DEBUG
2771         pcm_dbg(substream->pcm, "pcm_oss: write %li bytes (wrote %li bytes)\n",
2772                (long)count, (long)result);
2773 #endif
2774         return result;
2775 }
2776
2777 static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
2778 {
2779         struct snd_pcm_runtime *runtime = substream->runtime;
2780         if (atomic_read(&substream->mmap_count))
2781                 return runtime->oss.prev_hw_ptr_period !=
2782                                                 get_hw_ptr_period(runtime);
2783         else
2784                 return snd_pcm_playback_avail(runtime) >=
2785                                                 runtime->oss.period_frames;
2786 }
2787
2788 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
2789 {
2790         struct snd_pcm_runtime *runtime = substream->runtime;
2791         if (atomic_read(&substream->mmap_count))
2792                 return runtime->oss.prev_hw_ptr_period !=
2793                                                 get_hw_ptr_period(runtime);
2794         else
2795                 return snd_pcm_capture_avail(runtime) >=
2796                                                 runtime->oss.period_frames;
2797 }
2798
2799 static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
2800 {
2801         struct snd_pcm_oss_file *pcm_oss_file;
2802         __poll_t mask;
2803         struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
2804         
2805         pcm_oss_file = file->private_data;
2806
2807         psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2808         csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2809
2810         mask = 0;
2811         if (psubstream != NULL) {
2812                 struct snd_pcm_runtime *runtime = psubstream->runtime;
2813                 poll_wait(file, &runtime->sleep, wait);
2814                 snd_pcm_stream_lock_irq(psubstream);
2815                 if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
2816                     (runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
2817                      snd_pcm_oss_playback_ready(psubstream)))
2818                         mask |= EPOLLOUT | EPOLLWRNORM;
2819                 snd_pcm_stream_unlock_irq(psubstream);
2820         }
2821         if (csubstream != NULL) {
2822                 struct snd_pcm_runtime *runtime = csubstream->runtime;
2823                 snd_pcm_state_t ostate;
2824                 poll_wait(file, &runtime->sleep, wait);
2825                 snd_pcm_stream_lock_irq(csubstream);
2826                 if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING ||
2827                     snd_pcm_oss_capture_ready(csubstream))
2828                         mask |= EPOLLIN | EPOLLRDNORM;
2829                 snd_pcm_stream_unlock_irq(csubstream);
2830                 if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
2831                         struct snd_pcm_oss_file ofile;
2832                         memset(&ofile, 0, sizeof(ofile));
2833                         ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2834                         runtime->oss.trigger = 0;
2835                         snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
2836                 }
2837         }
2838
2839         return mask;
2840 }
2841
2842 static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
2843 {
2844         struct snd_pcm_oss_file *pcm_oss_file;
2845         struct snd_pcm_substream *substream = NULL;
2846         struct snd_pcm_runtime *runtime;
2847         int err;
2848
2849 #ifdef OSS_DEBUG
2850         pr_debug("pcm_oss: mmap begin\n");
2851 #endif
2852         pcm_oss_file = file->private_data;
2853         switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
2854         case VM_READ | VM_WRITE:
2855                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2856                 if (substream)
2857                         break;
2858                 fallthrough;
2859         case VM_READ:
2860                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
2861                 break;
2862         case VM_WRITE:
2863                 substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
2864                 break;
2865         default:
2866                 return -EINVAL;
2867         }
2868         /* set VM_READ access as well to fix memset() routines that do
2869            reads before writes (to improve performance) */
2870         area->vm_flags |= VM_READ;
2871         if (substream == NULL)
2872                 return -ENXIO;
2873         runtime = substream->runtime;
2874         if (!(runtime->info & SNDRV_PCM_INFO_MMAP_VALID))
2875                 return -EIO;
2876         if (runtime->info & SNDRV_PCM_INFO_INTERLEAVED)
2877                 runtime->access = SNDRV_PCM_ACCESS_MMAP_INTERLEAVED;
2878         else
2879                 return -EIO;
2880         
2881         if (runtime->oss.params) {
2882                 /* use mutex_trylock() for params_lock for avoiding a deadlock
2883                  * between mmap_lock and params_lock taken by
2884                  * copy_from/to_user() in snd_pcm_oss_write/read()
2885                  */
2886                 err = snd_pcm_oss_change_params(substream, true);
2887                 if (err < 0)
2888                         return err;
2889         }
2890 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2891         if (runtime->oss.plugin_first != NULL)
2892                 return -EIO;
2893 #endif
2894
2895         if (area->vm_pgoff != 0)
2896                 return -EINVAL;
2897
2898         err = snd_pcm_mmap_data(substream, file, area);
2899         if (err < 0)
2900                 return err;
2901         runtime->oss.mmap_bytes = area->vm_end - area->vm_start;
2902         runtime->silence_threshold = 0;
2903         runtime->silence_size = 0;
2904 #ifdef OSS_DEBUG
2905         pr_debug("pcm_oss: mmap ok, bytes = 0x%x\n",
2906                runtime->oss.mmap_bytes);
2907 #endif
2908         /* In mmap mode we never stop */
2909         runtime->stop_threshold = runtime->boundary;
2910
2911         return 0;
2912 }
2913
2914 #ifdef CONFIG_SND_VERBOSE_PROCFS
2915 /*
2916  *  /proc interface
2917  */
2918
2919 static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
2920                                   struct snd_info_buffer *buffer)
2921 {
2922         struct snd_pcm_str *pstr = entry->private_data;
2923         struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
2924         mutex_lock(&pstr->oss.setup_mutex);
2925         while (setup) {
2926                 snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
2927                             setup->task_name,
2928                             setup->periods,
2929                             setup->period_size,
2930                             setup->disable ? " disable" : "",
2931                             setup->direct ? " direct" : "",
2932                             setup->block ? " block" : "",
2933                             setup->nonblock ? " non-block" : "",
2934                             setup->partialfrag ? " partial-frag" : "",
2935                             setup->nosilence ? " no-silence" : "");
2936                 setup = setup->next;
2937         }
2938         mutex_unlock(&pstr->oss.setup_mutex);
2939 }
2940
2941 static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
2942 {
2943         struct snd_pcm_oss_setup *setup, *setupn;
2944
2945         for (setup = pstr->oss.setup_list, pstr->oss.setup_list = NULL;
2946              setup; setup = setupn) {
2947                 setupn = setup->next;
2948                 kfree(setup->task_name);
2949                 kfree(setup);
2950         }
2951         pstr->oss.setup_list = NULL;
2952 }
2953
2954 static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
2955                                    struct snd_info_buffer *buffer)
2956 {
2957         struct snd_pcm_str *pstr = entry->private_data;
2958         char line[128], str[32], task_name[32];
2959         const char *ptr;
2960         int idx1;
2961         struct snd_pcm_oss_setup *setup, *setup1, template;
2962
2963         while (!snd_info_get_line(buffer, line, sizeof(line))) {
2964                 mutex_lock(&pstr->oss.setup_mutex);
2965                 memset(&template, 0, sizeof(template));
2966                 ptr = snd_info_get_str(task_name, line, sizeof(task_name));
2967                 if (!strcmp(task_name, "clear") || !strcmp(task_name, "erase")) {
2968                         snd_pcm_oss_proc_free_setup_list(pstr);
2969                         mutex_unlock(&pstr->oss.setup_mutex);
2970                         continue;
2971                 }
2972                 for (setup = pstr->oss.setup_list; setup; setup = setup->next) {
2973                         if (!strcmp(setup->task_name, task_name)) {
2974                                 template = *setup;
2975                                 break;
2976                         }
2977                 }
2978                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2979                 template.periods = simple_strtoul(str, NULL, 10);
2980                 ptr = snd_info_get_str(str, ptr, sizeof(str));
2981                 template.period_size = simple_strtoul(str, NULL, 10);
2982                 for (idx1 = 31; idx1 >= 0; idx1--)
2983                         if (template.period_size & (1 << idx1))
2984                                 break;
2985                 for (idx1--; idx1 >= 0; idx1--)
2986                         template.period_size &= ~(1 << idx1);
2987                 do {
2988                         ptr = snd_info_get_str(str, ptr, sizeof(str));
2989                         if (!strcmp(str, "disable")) {
2990                                 template.disable = 1;
2991                         } else if (!strcmp(str, "direct")) {
2992                                 template.direct = 1;
2993                         } else if (!strcmp(str, "block")) {
2994                                 template.block = 1;
2995                         } else if (!strcmp(str, "non-block")) {
2996                                 template.nonblock = 1;
2997                         } else if (!strcmp(str, "partial-frag")) {
2998                                 template.partialfrag = 1;
2999                         } else if (!strcmp(str, "no-silence")) {
3000                                 template.nosilence = 1;
3001                         } else if (!strcmp(str, "buggy-ptr")) {
3002                                 template.buggyptr = 1;
3003                         }
3004                 } while (*str);
3005                 if (setup == NULL) {
3006                         setup = kmalloc(sizeof(*setup), GFP_KERNEL);
3007                         if (! setup) {
3008                                 buffer->error = -ENOMEM;
3009                                 mutex_unlock(&pstr->oss.setup_mutex);
3010                                 return;
3011                         }
3012                         if (pstr->oss.setup_list == NULL)
3013                                 pstr->oss.setup_list = setup;
3014                         else {
3015                                 for (setup1 = pstr->oss.setup_list;
3016                                      setup1->next; setup1 = setup1->next);
3017                                 setup1->next = setup;
3018                         }
3019                         template.task_name = kstrdup(task_name, GFP_KERNEL);
3020                         if (! template.task_name) {
3021                                 kfree(setup);
3022                                 buffer->error = -ENOMEM;
3023                                 mutex_unlock(&pstr->oss.setup_mutex);
3024                                 return;
3025                         }
3026                 }
3027                 *setup = template;
3028                 mutex_unlock(&pstr->oss.setup_mutex);
3029         }
3030 }
3031
3032 static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
3033 {
3034         int stream;
3035         for (stream = 0; stream < 2; ++stream) {
3036                 struct snd_info_entry *entry;
3037                 struct snd_pcm_str *pstr = &pcm->streams[stream];
3038                 if (pstr->substream_count == 0)
3039                         continue;
3040                 if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
3041                         entry->content = SNDRV_INFO_CONTENT_TEXT;
3042                         entry->mode = S_IFREG | 0644;
3043                         entry->c.text.read = snd_pcm_oss_proc_read;
3044                         entry->c.text.write = snd_pcm_oss_proc_write;
3045                         entry->private_data = pstr;
3046                         if (snd_info_register(entry) < 0) {
3047                                 snd_info_free_entry(entry);
3048                                 entry = NULL;
3049                         }
3050                 }
3051                 pstr->oss.proc_entry = entry;
3052         }
3053 }
3054
3055 static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
3056 {
3057         int stream;
3058         for (stream = 0; stream < 2; ++stream) {
3059                 struct snd_pcm_str *pstr = &pcm->streams[stream];
3060                 snd_info_free_entry(pstr->oss.proc_entry);
3061                 pstr->oss.proc_entry = NULL;
3062                 snd_pcm_oss_proc_free_setup_list(pstr);
3063         }
3064 }
3065 #else /* !CONFIG_SND_VERBOSE_PROCFS */
3066 #define snd_pcm_oss_proc_init(pcm)
3067 #define snd_pcm_oss_proc_done(pcm)
3068 #endif /* CONFIG_SND_VERBOSE_PROCFS */
3069
3070 /*
3071  *  ENTRY functions
3072  */
3073
3074 static const struct file_operations snd_pcm_oss_f_reg =
3075 {
3076         .owner =        THIS_MODULE,
3077         .read =         snd_pcm_oss_read,
3078         .write =        snd_pcm_oss_write,
3079         .open =         snd_pcm_oss_open,
3080         .release =      snd_pcm_oss_release,
3081         .llseek =       no_llseek,
3082         .poll =         snd_pcm_oss_poll,
3083         .unlocked_ioctl =       snd_pcm_oss_ioctl,
3084         .compat_ioctl = snd_pcm_oss_ioctl_compat,
3085         .mmap =         snd_pcm_oss_mmap,
3086 };
3087
3088 static void register_oss_dsp(struct snd_pcm *pcm, int index)
3089 {
3090         if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3091                                     pcm->card, index, &snd_pcm_oss_f_reg,
3092                                     pcm) < 0) {
3093                 pcm_err(pcm, "unable to register OSS PCM device %i:%i\n",
3094                            pcm->card->number, pcm->device);
3095         }
3096 }
3097
3098 static int snd_pcm_oss_register_minor(struct snd_pcm *pcm)
3099 {
3100         pcm->oss.reg = 0;
3101         if (dsp_map[pcm->card->number] == (int)pcm->device) {
3102                 char name[128];
3103                 int duplex;
3104                 register_oss_dsp(pcm, 0);
3105                 duplex = (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count > 0 && 
3106                               pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count && 
3107                               !(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));
3108                 sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");
3109 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
3110                 snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
3111                                       pcm->card->number,
3112                                       name);
3113 #endif
3114                 pcm->oss.reg++;
3115                 pcm->oss.reg_mask |= 1;
3116         }
3117         if (adsp_map[pcm->card->number] == (int)pcm->device) {
3118                 register_oss_dsp(pcm, 1);
3119                 pcm->oss.reg++;
3120                 pcm->oss.reg_mask |= 2;
3121         }
3122
3123         if (pcm->oss.reg)
3124                 snd_pcm_oss_proc_init(pcm);
3125
3126         return 0;
3127 }
3128
3129 static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm)
3130 {
3131         if (pcm->oss.reg) {
3132                 if (pcm->oss.reg_mask & 1) {
3133                         pcm->oss.reg_mask &= ~1;
3134                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3135                                                   pcm->card, 0);
3136                 }
3137                 if (pcm->oss.reg_mask & 2) {
3138                         pcm->oss.reg_mask &= ~2;
3139                         snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
3140                                                   pcm->card, 1);
3141                 }
3142                 if (dsp_map[pcm->card->number] == (int)pcm->device) {
3143 #ifdef SNDRV_OSS_INFO_DEV_AUDIO
3144                         snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
3145 #endif
3146                 }
3147                 pcm->oss.reg = 0;
3148         }
3149         return 0;
3150 }
3151
3152 static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm)
3153 {
3154         snd_pcm_oss_disconnect_minor(pcm);
3155         snd_pcm_oss_proc_done(pcm);
3156         return 0;
3157 }
3158
3159 static struct snd_pcm_notify snd_pcm_oss_notify =
3160 {
3161         .n_register =   snd_pcm_oss_register_minor,
3162         .n_disconnect = snd_pcm_oss_disconnect_minor,
3163         .n_unregister = snd_pcm_oss_unregister_minor,
3164 };
3165
3166 static int __init alsa_pcm_oss_init(void)
3167 {
3168         int i;
3169         int err;
3170
3171         /* check device map table */
3172         for (i = 0; i < SNDRV_CARDS; i++) {
3173                 if (dsp_map[i] < 0 || dsp_map[i] >= SNDRV_PCM_DEVICES) {
3174                         pr_err("ALSA: pcm_oss: invalid dsp_map[%d] = %d\n",
3175                                    i, dsp_map[i]);
3176                         dsp_map[i] = 0;
3177                 }
3178                 if (adsp_map[i] < 0 || adsp_map[i] >= SNDRV_PCM_DEVICES) {
3179                         pr_err("ALSA: pcm_oss: invalid adsp_map[%d] = %d\n",
3180                                    i, adsp_map[i]);
3181                         adsp_map[i] = 1;
3182                 }
3183         }
3184         if ((err = snd_pcm_notify(&snd_pcm_oss_notify, 0)) < 0)
3185                 return err;
3186         return 0;
3187 }
3188
3189 static void __exit alsa_pcm_oss_exit(void)
3190 {
3191         snd_pcm_notify(&snd_pcm_oss_notify, 1);
3192 }
3193
3194 module_init(alsa_pcm_oss_init)
3195 module_exit(alsa_pcm_oss_exit)