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