#include <linux/fs.h>
#include <sound/core.h>
#include <sound/control.h>
-#include <sound/minors.h>
#include <asm/uaccess.h>
#include "ioctl32.h"
-
/*
* register/unregister mappers
* exported for other modules
unsigned char reserved[50];
} /* don't set packed attribute here */;
-static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+#define CVT_sndrv_ctl_elem_list()\
+{\
+ COPY(offset);\
+ COPY(space);\
+ COPY(used);\
+ COPY(count);\
+ CPTR(pids);\
+}
+
+static int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
- struct sndrv_ctl_elem_list32 __user *data32;
- struct sndrv_ctl_elem_list __user *data;
- compat_caddr_t ptr;
+ struct sndrv_ctl_elem_list32 data32;
+ struct sndrv_ctl_elem_list data;
+ mm_segment_t oldseg;
int err;
- data32 = compat_ptr(arg);
- data = compat_alloc_user_space(sizeof(*data));
-
- /* offset, space, used, count */
- if (copy_in_user(data, data32, 4 * sizeof(u32)))
+ if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
return -EFAULT;
- /* pids */
- if (__get_user(ptr, &data32->pids) ||
- __put_user(compat_ptr(ptr), &data->pids))
- return -EFAULT;
- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+ memset(&data, 0, sizeof(data));
+ data.offset = data32.offset;
+ data.space = data32.space;
+ data.used = data32.used;
+ data.count = data32.count;
+ data.pids = compat_ptr(data32.pids);
+ oldseg = get_fs();
+ set_fs(KERNEL_DS);
+ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+ set_fs(oldseg);
if (err < 0)
return err;
/* copy the result */
- if (copy_in_user(data32, data, 4 * sizeof(u32)))
+ data32.offset = data.offset;
+ data32.space = data.space;
+ data32.used = data.used;
+ data32.count = data.count;
+ //data.pids = data.pids;
+ if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
return -EFAULT;
return 0;
}
unsigned char reserved[64];
} __attribute__((packed));
-static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
- struct sndrv_ctl_elem_info __user *data, *src;
- struct sndrv_ctl_elem_info32 __user *data32, *dst;
- unsigned int type;
+ struct sndrv_ctl_elem_info data;
+ struct sndrv_ctl_elem_info32 data32;
int err;
+ mm_segment_t oldseg;
- data32 = compat_ptr(arg);
- data = compat_alloc_user_space(sizeof(*data));
-
- /* copy id */
- if (copy_in_user(&data->id, &data32->id, sizeof(data->id)))
+ if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
return -EFAULT;
+ memset(&data, 0, sizeof(data));
+ data.id = data32.id;
/* we need to copy the item index.
* hope this doesn't break anything..
*/
- if (copy_in_user(&data->value.enumerated.item,
- &data32->value.enumerated.item,
- sizeof(data->value.enumerated.item)))
- return -EFAULT;
- err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+ data.value.enumerated.item = data32.value.enumerated.item;
+ oldseg = get_fs();
+ set_fs(KERNEL_DS);
+ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
+ set_fs(oldseg);
if (err < 0)
return err;
/* restore info to 32bit */
- /* for COPY_CVT macro */
- src = data;
- dst = data32;
- /* id, type, access, count */
- if (copy_in_user(&data32->id, &data->id, sizeof(data->id)) ||
- copy_in_user(&data32->type, &data->type, 3 * sizeof(u32)))
- return -EFAULT;
- COPY_CVT(owner);
- __get_user(type, &data->type);
- switch (type) {
+ data32.id = data.id;
+ data32.type = data.type;
+ data32.access = data.access;
+ data32.count = data.count;
+ data32.owner = data.owner;
+ switch (data.type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
- COPY_CVT(value.integer.min);
- COPY_CVT(value.integer.max);
- COPY_CVT(value.integer.step);
+ data32.value.integer.min = data.value.integer.min;
+ data32.value.integer.max = data.value.integer.max;
+ data32.value.integer.step = data.value.integer.step;
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (copy_in_user(&data32->value.integer64,
- &data->value.integer64,
- sizeof(data->value.integer64)))
- return -EFAULT;
+ data32.value.integer64.min = data.value.integer64.min;
+ data32.value.integer64.max = data.value.integer64.max;
+ data32.value.integer64.step = data.value.integer64.step;
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (copy_in_user(&data32->value.enumerated,
- &data->value.enumerated,
- sizeof(data->value.enumerated)))
- return -EFAULT;
+ data32.value.enumerated.items = data.value.enumerated.items;
+ data32.value.enumerated.item = data.value.enumerated.item;
+ memcpy(data32.value.enumerated.name, data.value.enumerated.name,
+ sizeof(data.value.enumerated.name));
break;
default:
break;
}
+ if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
+ return -EFAULT;
return 0;
}
struct sndrv_aes_iec958 iec958;
} value;
unsigned char reserved[128];
-};
+} __attribute__((packed));
/* hmm, it's so hard to retrieve the value type from the control id.. */
-static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id)
+static int get_ctl_type(struct file *file, snd_ctl_elem_id_t *id)
{
+ snd_ctl_file_t *ctl;
snd_kcontrol_t *kctl;
snd_ctl_elem_info_t info;
int err;
- down_read(&card->controls_rwsem);
- kctl = snd_ctl_find_id(card, id);
+ ctl = file->private_data;
+
+ down_read(&ctl->card->controls_rwsem);
+ kctl = snd_ctl_find_id(ctl->card, id);
if (! kctl) {
- up_read(&card->controls_rwsem);
+ up_read(&ctl->card->controls_rwsem);
return -ENXIO;
}
info.id = *id;
err = kctl->info(kctl, &info);
- up_read(&card->controls_rwsem);
+ up_read(&ctl->card->controls_rwsem);
if (err >= 0)
err = info.type;
return err;
}
-extern int snd_major;
-static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
+static int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
struct sndrv_ctl_elem_value *data;
- struct sndrv_ctl_elem_value32 __user *data32;
- snd_ctl_file_t *ctl;
+ struct sndrv_ctl_elem_value32 *data32;
int err, i;
int type;
+ mm_segment_t oldseg;
- /* sanity check */
- if (imajor(file->f_dentry->d_inode) != snd_major ||
- SNDRV_MINOR_DEVICE(iminor(file->f_dentry->d_inode)) != SNDRV_MINOR_CONTROL)
- return -ENOTTY;
+ /* FIXME: check the sane ioctl.. */
- if ((ctl = file->private_data) == NULL)
- return -ENOTTY;
-
- data32 = compat_ptr(arg);
data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
-
- if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) {
- err = -EFAULT;
+ data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
+ if (data == NULL || data32 == NULL) {
+ err = -ENOMEM;
goto __end;
}
- if (__get_user(data->indirect, &data32->indirect)) {
+
+ if (copy_from_user(data32, (void __user *)arg, sizeof(*data32))) {
err = -EFAULT;
goto __end;
}
- /* FIXME: indirect access is not supported */
- if (data->indirect) {
- err = -EINVAL;
- goto __end;
- }
- type = get_ctl_type(ctl->card, &data->id);
+ memset(data, 0, sizeof(*data));
+ data->id = data32->id;
+ data->indirect = data32->indirect;
+ if (data->indirect) /* FIXME: this is not correct for long arrays */
+ data->value.integer.value_ptr = compat_ptr(data32->value.integer.value_ptr);
+ type = get_ctl_type(file, &data->id);
if (type < 0) {
err = type;
goto __end;
}
-
- switch (type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- for (i = 0; i < 128; i++) {
- int val;
- if (__get_user(val, &data32->value.integer.value[i])) {
- err = -EFAULT;
- goto __end;
- }
- data->value.integer.value[i] = val;
+ if (! data->indirect) {
+ switch (type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ for (i = 0; i < 128; i++)
+ data->value.integer.value[i] = data32->value.integer.value[i];
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ for (i = 0; i < 64; i++)
+ data->value.integer64.value[i] = data32->value.integer64.value[i];
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ for (i = 0; i < 128; i++)
+ data->value.enumerated.item[i] = data32->value.enumerated.item[i];
+ break;
+ case SNDRV_CTL_ELEM_TYPE_BYTES:
+ memcpy(data->value.bytes.data, data32->value.bytes.data,
+ sizeof(data->value.bytes.data));
+ break;
+ case SNDRV_CTL_ELEM_TYPE_IEC958:
+ data->value.iec958 = data32->value.iec958;
+ break;
+ default:
+ printk("unknown type %d\n", type);
+ break;
}
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (__copy_from_user(data->value.integer64.value,
- data32->value.integer64.value,
- sizeof(data->value.integer64.value))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (__copy_from_user(data->value.enumerated.item,
- data32->value.enumerated.item,
- sizeof(data32->value.enumerated.item))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_BYTES:
- if (__copy_from_user(data->value.bytes.data,
- data32->value.bytes.data,
- sizeof(data32->value.bytes.data))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_IEC958:
- if (__copy_from_user(&data->value.iec958,
- &data32->value.iec958,
- sizeof(data32->value.iec958))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- default:
- printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
- err = -EINVAL;
- goto __end;
}
- if (native_ctl == SNDRV_CTL_IOCTL_ELEM_READ)
- err = snd_ctl_elem_read(ctl->card, data);
- else
- err = snd_ctl_elem_write(ctl, data);
+ oldseg = get_fs();
+ set_fs(KERNEL_DS);
+ err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
+ set_fs(oldseg);
if (err < 0)
goto __end;
/* restore info to 32bit */
- switch (type) {
- case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
- case SNDRV_CTL_ELEM_TYPE_INTEGER:
- for (i = 0; i < 128; i++) {
- int val;
- val = data->value.integer.value[i];
- if (__put_user(val, &data32->value.integer.value[i])) {
- err = -EFAULT;
- goto __end;
- }
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_INTEGER64:
- if (__copy_to_user(data32->value.integer64.value,
- data->value.integer64.value,
- sizeof(data32->value.integer64.value))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
- if (__copy_to_user(data32->value.enumerated.item,
- data->value.enumerated.item,
- sizeof(data32->value.enumerated.item))) {
- err = -EFAULT;
- goto __end;
+ if (! data->indirect) {
+ switch (type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ for (i = 0; i < 128; i++)
+ data32->value.integer.value[i] = data->value.integer.value[i];
+ break;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+ for (i = 0; i < 64; i++)
+ data32->value.integer64.value[i] = data->value.integer64.value[i];
+ break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ for (i = 0; i < 128; i++)
+ data32->value.enumerated.item[i] = data->value.enumerated.item[i];
+ break;
+ case SNDRV_CTL_ELEM_TYPE_BYTES:
+ memcpy(data32->value.bytes.data, data->value.bytes.data,
+ sizeof(data->value.bytes.data));
+ break;
+ case SNDRV_CTL_ELEM_TYPE_IEC958:
+ data32->value.iec958 = data->value.iec958;
+ break;
+ default:
+ break;
}
- break;
- case SNDRV_CTL_ELEM_TYPE_BYTES:
- if (__copy_to_user(data32->value.bytes.data,
- data->value.bytes.data,
- sizeof(data32->value.bytes.data))) {
- err = -EFAULT;
- goto __end;
- }
- break;
- case SNDRV_CTL_ELEM_TYPE_IEC958:
- if (__copy_to_user(&data32->value.iec958,
- &data->value.iec958,
- sizeof(data32->value.iec958))) {
- err = -EFAULT;
- goto __end;
- }
- break;
}
err = 0;
+ if (copy_to_user((void __user *)arg, data32, sizeof(*data32)))
+ err = -EFAULT;
__end:
+ if (data32)
+ kfree(data32);
if (data)
kfree(data);
return err;