summaryrefslogtreecommitdiffstats
path: root/drivers/sound/pas2_mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sound/pas2_mixer.c')
-rw-r--r--drivers/sound/pas2_mixer.c206
1 files changed, 92 insertions, 114 deletions
diff --git a/drivers/sound/pas2_mixer.c b/drivers/sound/pas2_mixer.c
index 335e7dd39..7c0687b77 100644
--- a/drivers/sound/pas2_mixer.c
+++ b/drivers/sound/pas2_mixer.c
@@ -12,6 +12,9 @@
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
+/*
+ * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
+ */
#include <linux/config.h>
#include "sound_config.h"
@@ -211,122 +214,97 @@ pas_mixer_reset(void)
set_mode(0x04 | 0x01);
}
-static int
-pas_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+static int pas_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
{
- DEB(printk("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
-
- if (cmd == SOUND_MIXER_PRIVATE1) /* Set loudness bit */
- {
- int level;
-
- level = *(int *) arg;
-
- if (level == -1) /* Return current settings */
- {
- if (mode_control & 0x04)
- return (*(int *) arg = 1);
- else
- return (*(int *) arg = 0);
- } else
- {
- mode_control &= ~0x04;
- if (level)
- mode_control |= 0x04;
- set_mode(mode_control);
- return (*(int *) arg = !!level); /* 0 or 1 */
- }
- }
- if (cmd == SOUND_MIXER_PRIVATE2) /* Set enhance bit */
- {
- int level;
+ int level,v ;
- level = *(int *) arg;
-
- if (level == -1) /* Return current settings */
- {
- if (!(mode_control & 0x03))
- return (*(int *) arg = 0);
- return (*(int *) arg = ((mode_control & 0x03) + 1) * 20);
- } else
- {
- int i = 0;
-
- level &= 0x7f;
- if (level)
- i = (level / 20) - 1;
-
- mode_control &= ~0x03;
- mode_control |= i & 0x03;
- set_mode(mode_control);
-
- if (i)
- i = (i + 1) * 20;
-
- return i;
- }
- }
- if (cmd == SOUND_MIXER_PRIVATE3) /* Set mute bit */
- {
- int level;
-
- level = *(int *) arg;
-
- if (level == -1) /* Return current settings */
- {
- return (*(int *) arg = !(pas_read(0x0B8A) & 0x20));
- } else
- {
- if (level)
- pas_write(pas_read(0x0B8A) & (~0x20),
- 0x0B8A);
- else
- pas_write(pas_read(0x0B8A) | 0x20,
- 0x0B8A);
-
- return !(pas_read(0x0B8A) & 0x20);
- }
- }
- if (((cmd >> 8) & 0xff) == 'M')
- {
- int v;
-
- v = *(int *) arg;
-
- if (_SIOC_DIR(cmd) & _SIOC_WRITE)
- return (*(int *) arg = pas_mixer_set(cmd & 0xff, v));
- else
- {
-
- switch (cmd & 0xff)
- {
-
- case SOUND_MIXER_RECSRC:
- return (*(int *) arg = rec_devices);
- break;
-
- case SOUND_MIXER_STEREODEVS:
- return (*(int *) arg = SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
- break;
-
- case SOUND_MIXER_DEVMASK:
- return (*(int *) arg = SUPPORTED_MIXER_DEVICES);
- break;
-
- case SOUND_MIXER_RECMASK:
- return (*(int *) arg = POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
- break;
-
- case SOUND_MIXER_CAPS:
- return (*(int *) arg = 0); /* No special capabilities */
- break;
-
-
- default:
- return (*(int *) arg = levels[cmd & 0xff]);
- }
- }
- }
+ DEB(printk("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
+ if (cmd == SOUND_MIXER_PRIVATE1) { /* Set loudness bit */
+ if (get_user(level, (int *)arg))
+ return -EFAULT;
+ if (level == -1) /* Return current settings */
+ level = (mode_control & 0x04);
+ else {
+ mode_control &= ~0x04;
+ if (level)
+ mode_control |= 0x04;
+ set_mode(mode_control);
+ }
+ level = !!level;
+ return put_user(level, (int *)arg);
+ }
+ if (cmd == SOUND_MIXER_PRIVATE2) { /* Set enhance bit */
+ if (get_user(level, (int *)arg))
+ return -EFAULT;
+ if (level == -1) { /* Return current settings */
+ if (!(mode_control & 0x03))
+ level = 0;
+ else
+ level = ((mode_control & 0x03) + 1) * 20;
+ } else {
+ int i = 0;
+
+ level &= 0x7f;
+ if (level)
+ i = (level / 20) - 1;
+ mode_control &= ~0x03;
+ mode_control |= i & 0x03;
+ set_mode(mode_control);
+ if (i)
+ i = (i + 1) * 20;
+ level = i;
+ }
+ return put_user(level, (int *)arg);
+ }
+ if (cmd == SOUND_MIXER_PRIVATE3) { /* Set mute bit */
+ if (get_user(level, (int *)arg))
+ return -EFAULT;
+ if (level == -1) /* Return current settings */
+ level = !(pas_read(0x0B8A) & 0x20);
+ else {
+ if (level)
+ pas_write(pas_read(0x0B8A) & (~0x20), 0x0B8A);
+ else
+ pas_write(pas_read(0x0B8A) | 0x20, 0x0B8A);
+
+ level = !(pas_read(0x0B8A) & 0x20);
+ }
+ return put_user(level, (int *)arg);
+ }
+ if (((cmd >> 8) & 0xff) == 'M') {
+ if (get_user(v, (int *)arg))
+ return -EFAULT;
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
+ v = pas_mixer_set(cmd & 0xff, v);
+ } else {
+ switch (cmd & 0xff) {
+ case SOUND_MIXER_RECSRC:
+ v = rec_devices;
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ v = SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE);
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ v = SUPPORTED_MIXER_DEVICES;
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ v = POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ v = 0; /* No special capabilities */
+ break;
+
+ default:
+ v = levels[cmd & 0xff];
+ break;
+ }
+ }
+ return put_user(v, (int *)arg);
+ }
return -EINVAL;
}