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