* [PATCH 0/3] Conversion to compat_ioctl for ALSA drivers @ 2005-01-18 16:32 Takashi Iwai 2005-01-18 16:35 ` [PATCH 1/3] " Takashi Iwai 2005-01-30 18:02 ` [PATCH 0/3] " Brian Gerst 0 siblings, 2 replies; 7+ messages in thread From: Takashi Iwai @ 2005-01-18 16:32 UTC (permalink / raw) To: akpm; +Cc: linux-kernel, ak, perex Hi, the following three patches convert the 32bit ioctl layer of ALSA to the new compat_ioctl (and unlocked_ioctl for native ioctls). The first patch covers the basic entries and control API. The second patch is for PCM API. The last one is for other APIs including OSS-emulation modules. After these patches are applied, remove the whole subtree in sound/core/ioctl32. The files in this directory are no longer necessary. Takashi ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/3] Conversion to compat_ioctl for ALSA drivers 2005-01-18 16:32 [PATCH 0/3] Conversion to compat_ioctl for ALSA drivers Takashi Iwai @ 2005-01-18 16:35 ` Takashi Iwai 2005-01-18 16:36 ` [PATCH 2/3] " Takashi Iwai 2005-01-30 18:02 ` [PATCH 0/3] " Brian Gerst 1 sibling, 1 reply; 7+ messages in thread From: Takashi Iwai @ 2005-01-18 16:35 UTC (permalink / raw) To: akpm; +Cc: linux-kernel, ak, perex This patch modifies Kconfig and Makefile to remove snd-ioctl32. It convers to unlocked_ioctl, and adds the compat_ioctl entries. New register/unregister functions for compat ioctl are added. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- linux/sound/core/Kconfig 23 Nov 2004 14:49:03 -0000 1.7 +++ linux/sound/core/Kconfig 12 Jan 2005 22:49:21 -0000 @@ -81,20 +81,6 @@ To compile this driver as a module, choose M here: the module will be called snd-seq-oss. -config SND_BIT32_EMUL - tristate "Emulation for 32-bit applications" - depends on SND && COMPAT - select SND_PCM - select SND_RAWMIDI - select SND_TIMER - select SND_HWDEP - help - Say Y here to enable the emulation for 32-bit ALSA-native - applications. - - To compile this driver as a module, choose M here: the module - will be called snd-ioctl32. - config SND_RTCTIMER tristate "RTC Timer support" depends on SND && RTC --- linux/sound/core/Makefile 3 Mar 2004 10:46:16 -0000 1.49 +++ linux/sound/core/Makefile 12 Jan 2005 22:49:21 -0000 @@ -31,4 +31,3 @@ obj-$(CONFIG_SND_OSSEMUL) += oss/ obj-$(CONFIG_SND_SEQUENCER) += seq/ -obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/ --- linux/sound/core/control.c 3 Jan 2005 14:27:52 -0000 1.49 +++ linux/sound/core/control.c 18 Jan 2005 14:52:43 -0000 @@ -43,6 +43,9 @@ static DECLARE_RWSEM(snd_ioctl_rwsem); static LIST_HEAD(snd_control_ioctls); +#ifdef CONFIG_COMPAT +static LIST_HEAD(snd_control_compat_ioctls); +#endif static int snd_ctl_open(struct inode *inode, struct file *file) { @@ -595,43 +598,51 @@ return 0; } -static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info) +static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info) { snd_card_t *card = ctl->card; - snd_ctl_elem_info_t info; snd_kcontrol_t *kctl; snd_kcontrol_volatile_t *vd; unsigned int index_offset; int result; - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; down_read(&card->controls_rwsem); - kctl = snd_ctl_find_id(card, &info.id); + kctl = snd_ctl_find_id(card, &info->id); if (kctl == NULL) { up_read(&card->controls_rwsem); return -ENOENT; } #ifdef CONFIG_SND_DEBUG - info.access = 0; + info->access = 0; #endif - result = kctl->info(kctl, &info); + result = kctl->info(kctl, info); if (result >= 0) { - snd_assert(info.access == 0, ); - index_offset = snd_ctl_get_ioff(kctl, &info.id); + snd_assert(info->access == 0, ); + index_offset = snd_ctl_get_ioff(kctl, &info->id); vd = &kctl->vd[index_offset]; - snd_ctl_build_ioff(&info.id, kctl, index_offset); - info.access = vd->access; + snd_ctl_build_ioff(&info->id, kctl, index_offset); + info->access = vd->access; if (vd->owner) { - info.access |= SNDRV_CTL_ELEM_ACCESS_LOCK; + info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; if (vd->owner == ctl) - info.access |= SNDRV_CTL_ELEM_ACCESS_OWNER; - info.owner = vd->owner_pid; + info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; + info->owner = vd->owner_pid; } else { - info.owner = -1; + info->owner = -1; } } up_read(&card->controls_rwsem); + return result; +} + +static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info) +{ + snd_ctl_elem_info_t info; + int result; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + result = snd_ctl_elem_info(ctl, &info); if (result >= 0) if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -816,14 +827,6 @@ struct user_element *ue = kcontrol->private_data; *uinfo = ue->info; - if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { - uinfo->value.enumerated.items = ue->info.value.enumerated.items; - if (uinfo->value.enumerated.item >= ue->info.value.enumerated.items) - uinfo->value.enumerated.item = 0; - strlcpy(uinfo->value.enumerated.name, - (char *)ue->priv_data + uinfo->value.enumerated.item * 64, - 64); - } return 0; } @@ -851,28 +854,25 @@ kfree(kcontrol->private_data); } -static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace) +static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int replace) { snd_card_t *card = file->card; - snd_ctl_elem_info_t info; snd_kcontrol_t kctl, *_kctl; unsigned int access; - long private_size, extra_size; + long private_size; struct user_element *ue; int idx, err; if (card->user_ctl_count >= MAX_USER_CONTROLS) return -ENOMEM; - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - if (info.count > 1024) + if (info->count > 1024) return -EINVAL; - access = info.access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : - (info.access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE)); - info.id.numid = 0; + access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : + (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE)); + info->id.numid = 0; memset(&kctl, 0, sizeof(kctl)); down_write(&card->controls_rwsem); - _kctl = snd_ctl_find_id(card, &info.id); + _kctl = snd_ctl_find_id(card, &info->id); err = 0; if (_kctl) { if (replace) @@ -886,67 +886,50 @@ up_write(&card->controls_rwsem); if (err < 0) return err; - memcpy(&kctl.id, &info.id, sizeof(info.id)); - kctl.count = info.owner ? info.owner : 1; + memcpy(&kctl.id, &info->id, sizeof(info->id)); + kctl.count = info->owner ? info->owner : 1; access |= SNDRV_CTL_ELEM_ACCESS_USER; kctl.info = snd_ctl_elem_user_info; if (access & SNDRV_CTL_ELEM_ACCESS_READ) kctl.get = snd_ctl_elem_user_get; if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) kctl.put = snd_ctl_elem_user_put; - extra_size = 0; - switch (info.type) { + switch (info->type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: private_size = sizeof(char); - if (info.count > 128) + if (info->count > 128) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_INTEGER: private_size = sizeof(long); - if (info.count > 128) + if (info->count > 128) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_INTEGER64: private_size = sizeof(long long); - if (info.count > 64) + if (info->count > 64) return -EINVAL; break; - case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - private_size = sizeof(unsigned int); - if (info.count > 128) - return -EINVAL; - if (info.value.enumerated.items > 128) - return -EINVAL; - extra_size = info.value.enumerated.items * 64; - break; case SNDRV_CTL_ELEM_TYPE_BYTES: private_size = sizeof(unsigned char); - if (info.count > 512) + if (info->count > 512) return -EINVAL; break; case SNDRV_CTL_ELEM_TYPE_IEC958: private_size = sizeof(struct sndrv_aes_iec958); - if (info.count != 1) + if (info->count != 1) return -EINVAL; break; default: return -EINVAL; } - private_size *= info.count; - ue = kcalloc(1, sizeof(struct user_element) + private_size + extra_size, GFP_KERNEL); + private_size *= info->count; + ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL); if (ue == NULL) return -ENOMEM; - ue->info = info; + ue->info = *info; ue->elem_data = (char *)ue + sizeof(ue); ue->elem_data_size = private_size; - if (extra_size) { - ue->priv_data = (char *)ue + sizeof(ue) + private_size; - ue->priv_data_size = extra_size; - if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) { - if (copy_from_user(ue->priv_data, *(char __user **)info.value.enumerated.name, extra_size)) - return -EFAULT; - } - } kctl.private_free = snd_ctl_elem_user_free; _kctl = snd_ctl_new(&kctl, access); if (_kctl == NULL) { @@ -969,6 +952,14 @@ return 0; } +static int snd_ctl_elem_add_user(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace) +{ + snd_ctl_elem_info_t info; + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + return snd_ctl_elem_add(file, &info, replace); +} + static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id) { snd_ctl_elem_id_t id; @@ -1039,8 +1030,7 @@ } #endif -static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_ctl_file_t *ctl; snd_card_t *card; @@ -1061,7 +1051,7 @@ case SNDRV_CTL_IOCTL_ELEM_LIST: return snd_ctl_elem_list(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_INFO: - return snd_ctl_elem_info(ctl, argp); + return snd_ctl_elem_info_user(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_READ: return snd_ctl_elem_read_user(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_WRITE: @@ -1071,7 +1061,7 @@ case SNDRV_CTL_IOCTL_ELEM_UNLOCK: return snd_ctl_elem_unlock(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_ADD: - return snd_ctl_elem_add(ctl, argp, 0); + return snd_ctl_elem_add_user(ctl, argp, 0); case SNDRV_CTL_IOCTL_ELEM_REPLACE: return snd_ctl_elem_add(ctl, argp, 1); case SNDRV_CTL_IOCTL_ELEM_REMOVE: @@ -1113,17 +1103,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_ctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_ctl_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset) { snd_ctl_file_t *ctl; @@ -1199,7 +1178,7 @@ * register the device-specific control-ioctls. * called from each device manager like pcm.c, hwdep.c, etc. */ -int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) +static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) { snd_kctl_ioctl_t *pn; @@ -1208,22 +1187,34 @@ return -ENOMEM; pn->fioctl = fcn; down_write(&snd_ioctl_rwsem); - list_add_tail(&pn->list, &snd_control_ioctls); + list_add_tail(&pn->list, lists); up_write(&snd_ioctl_rwsem); return 0; } +int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); +} + +#ifdef CONFIG_COMPAT +int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); +} +#endif + /* * de-register the device-specific control-ioctls. */ -int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) +static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists) { struct list_head *list; snd_kctl_ioctl_t *p; snd_runtime_check(fcn != NULL, return -EINVAL); down_write(&snd_ioctl_rwsem); - list_for_each(list, &snd_control_ioctls) { + list_for_each(list, lists) { p = list_entry(list, snd_kctl_ioctl_t, list); if (p->fioctl == fcn) { list_del(&p->list); @@ -1237,6 +1228,19 @@ return -EINVAL; } +int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); +} + +#ifdef CONFIG_COMPAT +int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) +{ + return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); +} + +#endif + static int snd_ctl_fasync(int fd, struct file * file, int on) { snd_ctl_file_t *ctl; @@ -1249,6 +1253,15 @@ } /* + * ioctl32 compat + */ +#ifdef CONFIG_COMPAT +#include "control_compat.c" +#else +#define snd_ctl_ioctl_compat NULL +#endif + +/* * INIT PART */ @@ -1259,7 +1272,8 @@ .open = snd_ctl_open, .release = snd_ctl_release, .poll = snd_ctl_poll, - .ioctl = snd_ctl_ioctl, + .unlocked_ioctl = snd_ctl_ioctl, + .compat_ioctl = snd_ctl_ioctl_compat, .fasync = snd_ctl_fasync, }; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/control_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,412 @@ +/* + * compat ioctls for control API + * + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* this file included from control.c */ + +#include <linux/compat.h> + +struct sndrv_ctl_elem_list32 { + u32 offset; + u32 space; + u32 used; + u32 count; + u32 pids; + unsigned char reserved[50]; +} /* don't set packed attribute here */; + +static int snd_ctl_elem_list_compat(snd_card_t *card, struct sndrv_ctl_elem_list32 __user *data32) +{ + struct sndrv_ctl_elem_list __user *data; + compat_caddr_t ptr; + int err; + + data = compat_alloc_user_space(sizeof(*data)); + + /* offset, space, used, count */ + if (copy_in_user(data, data32, 4 * sizeof(u32))) + return -EFAULT; + /* pids */ + if (get_user(ptr, &data32->pids) || + put_user(compat_ptr(ptr), &data->pids)) + return -EFAULT; + err = snd_ctl_elem_list(card, data); + if (err < 0) + return err; + /* copy the result */ + if (copy_in_user(data32, data, 4 * sizeof(u32))) + return -EFAULT; + return 0; +} + +/* + * control element info + * it uses union, so the things are not easy.. + */ + +struct sndrv_ctl_elem_info32 { + struct sndrv_ctl_elem_id id; // the size of struct is same + s32 type; + u32 access; + u32 count; + s32 owner; + union { + struct { + s32 min; + s32 max; + s32 step; + } integer; + struct { + u64 min; + u64 max; + u64 step; + } integer64; + struct { + u32 items; + u32 item; + char name[64]; + } enumerated; + unsigned char reserved[128]; + } value; + unsigned char reserved[64]; +} __attribute__((packed)); + +static int snd_ctl_elem_info_compat(snd_ctl_file_t *ctl, struct sndrv_ctl_elem_info32 __user *data32) +{ + struct sndrv_ctl_elem_info *data; + int err; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (! data) + return -ENOMEM; + + err = -EFAULT; + /* copy id */ + if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) + goto error; + /* we need to copy the item index. + * hope this doesn't break anything.. + */ + if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) + goto error; + err = snd_ctl_elem_info(ctl, data); + if (err < 0) + goto error; + /* restore info to 32bit */ + err = -EFAULT; + /* id, type, access, count */ + if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) || + copy_to_user(&data32->type, &data->type, 3 * sizeof(u32))) + goto error; + if (put_user(data->owner, &data32->owner)) + goto error; + switch (data->type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + case SNDRV_CTL_ELEM_TYPE_INTEGER: + if (put_user(data->value.integer.min, &data32->value.integer.min) || + put_user(data->value.integer.max, &data32->value.integer.max) || + put_user(data->value.integer.step, &data32->value.integer.step)) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_INTEGER64: + if (copy_to_user(&data32->value.integer64, + &data->value.integer64, + sizeof(data->value.integer64))) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + if (copy_to_user(&data32->value.enumerated, + &data->value.enumerated, + sizeof(data->value.enumerated))) + goto error; + break; + default: + break; + } + err = 0; + error: + kfree(data); + return err; +} + +/* read / write */ +struct sndrv_ctl_elem_value32 { + struct sndrv_ctl_elem_id id; + unsigned int indirect; /* bit-field causes misalignment */ + union { + s32 integer[128]; + unsigned char data[512]; +#ifndef CONFIG_X86_64 + s64 integer64[64]; +#endif + } value; + unsigned char reserved[128]; +}; + + +/* get the value type and count of the control */ +static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id, int *countp) +{ + snd_kcontrol_t *kctl; + snd_ctl_elem_info_t info; + int err; + + down_read(&card->controls_rwsem); + kctl = snd_ctl_find_id(card, id); + if (! kctl) { + up_read(&card->controls_rwsem); + return -ENXIO; + } + info.id = *id; + err = kctl->info(kctl, &info); + up_read(&card->controls_rwsem); + if (err >= 0) { + err = info.type; + *countp = info.count; + } + return err; +} + +static int get_elem_size(int type, int count) +{ + switch (type) { + case SNDRV_CTL_ELEM_TYPE_INTEGER64: + return sizeof(s64) * count; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + return sizeof(int) * count; + case SNDRV_CTL_ELEM_TYPE_BYTES: + return 512; + case SNDRV_CTL_ELEM_TYPE_IEC958: + return sizeof(struct sndrv_aes_iec958); + default: + return -1; + } +} + +static int copy_ctl_value_from_user(snd_card_t *card, + struct sndrv_ctl_elem_value *data, + struct sndrv_ctl_elem_value32 __user *data32, + int *typep, int *countp) +{ + int i, type, count, size; + unsigned int indirect; + + if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) + return -EFAULT; + if (get_user(indirect, &data32->indirect)) + return -EFAULT; + if (indirect) + return -EINVAL; + type = get_ctl_type(card, &data->id, &count); + if (type < 0) + return type; + + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || + type == SNDRV_CTL_ELEM_TYPE_INTEGER) { + for (i = 0; i < count; i++) { + int val; + if (get_user(val, &data32->value.integer[i])) + return -EFAULT; + data->value.integer.value[i] = val; + } + } else { + size = get_elem_size(type, count); + if (size < 0) { + printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type); + return -EINVAL; + } + if (copy_from_user(data->value.bytes.data, + data32->value.data, size)) + return -EFAULT; + } + + *typep = type; + *countp = count; + return 0; +} + +/* restore the value to 32bit */ +static int copy_ctl_value_to_user(struct sndrv_ctl_elem_value32 __user *data32, + struct sndrv_ctl_elem_value *data, + int type, int count) +{ + int i, size; + + if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || + type == SNDRV_CTL_ELEM_TYPE_INTEGER) { + for (i = 0; i < count; i++) { + int val; + val = data->value.integer.value[i]; + if (put_user(val, &data32->value.integer[i])) + return -EFAULT; + } + } else { + size = get_elem_size(type, count); + if (copy_to_user(data32->value.data, + data->value.bytes.data, size)) + return -EFAULT; + } + return 0; +} + +static int snd_ctl_elem_read_user_compat(snd_card_t *card, + struct sndrv_ctl_elem_value32 __user *data32) +{ + struct sndrv_ctl_elem_value *data; + int err, type, count; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0) + goto error; + if ((err = snd_ctl_elem_read(card, data)) < 0) + goto error; + err = copy_ctl_value_to_user(data32, data, type, count); + error: + kfree(data); + return err; +} + +static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file, + struct sndrv_ctl_elem_value32 __user *data32) +{ + struct sndrv_ctl_elem_value *data; + int err, type, count; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + if ((err = copy_ctl_value_from_user(file->card, data, data32, &type, &count)) < 0) + goto error; + if ((err = snd_ctl_elem_write(file->card, file, data)) < 0) + goto error; + err = copy_ctl_value_to_user(data32, data, type, count); + error: + kfree(data); + return err; +} + +/* add or replace a user control */ +static int snd_ctl_elem_add_compat(snd_ctl_file_t *file, + struct sndrv_ctl_elem_info32 __user *data32, + int replace) +{ + struct sndrv_ctl_elem_info *data; + int err; + + data = kcalloc(1, sizeof(*data), GFP_KERNEL); + if (! data) + return -ENOMEM; + + err = -EFAULT; + /* id, type, access, count */ \ + if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || + copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) + goto error; + if (get_user(data->owner, &data32->owner) || + get_user(data->type, &data32->type)) + goto error; + switch (data->type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: + case SNDRV_CTL_ELEM_TYPE_INTEGER: + if (get_user(data->value.integer.min, &data32->value.integer.min) || + get_user(data->value.integer.max, &data32->value.integer.max) || + get_user(data->value.integer.step, &data32->value.integer.step)) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_INTEGER64: + if (copy_from_user(&data->value.integer64, + &data32->value.integer64, + sizeof(data->value.integer64))) + goto error; + break; + case SNDRV_CTL_ELEM_TYPE_ENUMERATED: + if (copy_from_user(&data->value.enumerated, + &data32->value.enumerated, + sizeof(data->value.enumerated))) + goto error; + break; + default: + break; + } + err = snd_ctl_elem_add(file, data, replace); + error: + kfree(data); + return err; +} + +enum { + SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct sndrv_ctl_elem_list32), + SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct sndrv_ctl_elem_info32), + SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct sndrv_ctl_elem_value32), + SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct sndrv_ctl_elem_value32), + SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct sndrv_ctl_elem_info32), + SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct sndrv_ctl_elem_info32), +}; + +static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + snd_ctl_file_t *ctl; + struct list_head *list; + void __user *argp = compat_ptr(arg); + int err; + + ctl = file->private_data; + snd_assert(ctl && ctl->card, return -ENXIO); + + switch (cmd) { + case SNDRV_CTL_IOCTL_PVERSION: + case SNDRV_CTL_IOCTL_CARD_INFO: + case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: + case SNDRV_CTL_IOCTL_POWER: + case SNDRV_CTL_IOCTL_POWER_STATE: + case SNDRV_CTL_IOCTL_ELEM_LOCK: + case SNDRV_CTL_IOCTL_ELEM_UNLOCK: + return snd_ctl_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_CTL_IOCTL_ELEM_LIST32: + return snd_ctl_elem_list_compat(ctl->card, argp); + case SNDRV_CTL_IOCTL_ELEM_INFO32: + return snd_ctl_elem_info_compat(ctl, argp); + case SNDRV_CTL_IOCTL_ELEM_READ32: + return snd_ctl_elem_read_user_compat(ctl->card, argp); + case SNDRV_CTL_IOCTL_ELEM_WRITE32: + return snd_ctl_elem_write_user_compat(ctl, argp); + case SNDRV_CTL_IOCTL_ELEM_ADD32: + return snd_ctl_elem_add_compat(ctl, argp, 0); + case SNDRV_CTL_IOCTL_ELEM_REPLACE32: + return snd_ctl_elem_add_compat(ctl, argp, 1); + } + + down_read(&snd_ioctl_rwsem); + list_for_each(list, &snd_control_compat_ioctls) { + snd_kctl_ioctl_t *p = list_entry(list, snd_kctl_ioctl_t, list); + if (p->fioctl) { + err = p->fioctl(ctl->card, ctl, cmd, arg); + if (err != -ENOIOCTLCMD) { + up_read(&snd_ioctl_rwsem); + return err; + } + } + } + up_read(&snd_ioctl_rwsem); + return -ENOIOCTLCMD; +} --- linux/sound/core/sound.c 22 Dec 2004 15:57:37 -0000 1.66 +++ linux/sound/core/sound.c 18 Jan 2005 15:37:49 -0000 @@ -467,6 +467,10 @@ EXPORT_SYMBOL(snd_ctl_notify); EXPORT_SYMBOL(snd_ctl_register_ioctl); EXPORT_SYMBOL(snd_ctl_unregister_ioctl); +#ifdef CONFIG_COMPAT +EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); +EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); +#endif EXPORT_SYMBOL(snd_ctl_elem_read); EXPORT_SYMBOL(snd_ctl_elem_write); /* misc.c */ --- linux/include/sound/control.h 23 Dec 2004 14:49:28 -0000 1.12 +++ linux/include/sound/control.h 12 Jan 2005 22:49:21 -0000 @@ -119,6 +119,13 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn); int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn); +#ifdef CONFIG_COMPAT +int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn); +int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn); +#else +#define snd_ctl_register_ioctl_compat(fcn) +#define snd_ctl_unregister_ioctl_compat(fcn) +#endif int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control); int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control); ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/3] Conversion to compat_ioctl for ALSA drivers 2005-01-18 16:35 ` [PATCH 1/3] " Takashi Iwai @ 2005-01-18 16:36 ` Takashi Iwai 2005-01-18 16:37 ` [PATCH 3/3] " Takashi Iwai 0 siblings, 1 reply; 7+ messages in thread From: Takashi Iwai @ 2005-01-18 16:36 UTC (permalink / raw) To: akpm; +Cc: linux-kernel, ak, perex This patch converts to unlocked_ioctl and adds the compat ioctl layer for ALSA PCM API. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- linux/sound/core/pcm.c 30 Nov 2004 19:58:22 -0000 1.47 +++ linux/sound/core/pcm.c 12 Jan 2005 22:49:21 -0000 @@ -1004,6 +1004,7 @@ snd_info_entry_t *entry; snd_ctl_register_ioctl(snd_pcm_control_ioctl); + snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl); if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read); if (snd_info_register(entry) < 0) { @@ -1018,6 +1019,7 @@ static void __exit alsa_pcm_exit(void) { snd_ctl_unregister_ioctl(snd_pcm_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl); if (snd_pcm_proc_entry) { snd_info_unregister(snd_pcm_proc_entry); snd_pcm_proc_entry = NULL; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/pcm_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,513 @@ +/* + * 32bit -> 64bit ioctl wrapper for PCM API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from pcm_native.c */ + +#include <linux/compat.h> + +static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream, + s32 __user *src) +{ + snd_pcm_sframes_t delay; + mm_segment_t fs; + int err; + + fs = snd_enter_user(); + err = snd_pcm_delay(substream, &delay); + snd_leave_user(fs); + if (err < 0) + return err; + if (put_user(delay, src)) + return -EFAULT; + return err; +} + +static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream, + u32 __user *src) +{ + snd_pcm_uframes_t frames; + int err; + + if (get_user(frames, src)) + return -EFAULT; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_playback_rewind(substream, frames); + else + err = snd_pcm_capture_rewind(substream, frames); + if (put_user(err, src)) + return -EFAULT; + return err < 0 ? err : 0; +} + +static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream, + u32 __user *src) +{ + snd_pcm_uframes_t frames; + int err; + + if (get_user(frames, src)) + return -EFAULT; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_playback_forward(substream, frames); + else + err = snd_pcm_capture_forward(substream, frames); + if (put_user(err, src)) + return -EFAULT; + return err < 0 ? err : 0; +} + +struct sndrv_pcm_hw_params32 { + u32 flags; + struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */ + struct sndrv_mask mres[5]; /* reserved masks */ + struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; + struct sndrv_interval ires[9]; /* reserved intervals */ + u32 rmask; + u32 cmask; + u32 info; + u32 msbits; + u32 rate_num; + u32 rate_den; + u32 fifo_size; + unsigned char reserved[64]; +}; + +struct sndrv_pcm_sw_params32 { + s32 tstamp_mode; + u32 period_step; + u32 sleep_min; + u32 avail_min; + u32 xfer_align; + u32 start_threshold; + u32 stop_threshold; + u32 silence_threshold; + u32 silence_size; + u32 boundary; + unsigned char reserved[64]; +}; + +static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_sw_params32 __user *src) +{ + snd_pcm_sw_params_t params; + int err; + + memset(¶ms, 0, sizeof(params)); + if (get_user(params.tstamp_mode, &src->tstamp_mode) || + get_user(params.period_step, &src->period_step) || + get_user(params.sleep_min, &src->sleep_min) || + get_user(params.avail_min, &src->avail_min) || + get_user(params.xfer_align, &src->xfer_align) || + get_user(params.start_threshold, &src->start_threshold) || + get_user(params.stop_threshold, &src->stop_threshold) || + get_user(params.silence_threshold, &src->silence_threshold) || + get_user(params.silence_size, &src->silence_size)) + return -EFAULT; + err = snd_pcm_sw_params(substream, ¶ms); + if (err < 0) + return err; + if (put_user(params.boundary, &src->boundary)) + return -EFAULT; + return err; +} + +struct sndrv_pcm_channel_info32 { + u32 channel; + u32 offset; + u32 first; + u32 step; +}; + +static int snd_pcm_ioctl_channel_info_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_channel_info32 __user *src) +{ + snd_pcm_channel_info_t info; + int err; + + if (get_user(info.channel, &src->channel) || + get_user(info.offset, &src->offset) || + get_user(info.first, &src->first) || + get_user(info.step, &src->step)) + return -EFAULT; + err = snd_pcm_channel_info(substream, &info); + if (err < 0) + return err; + if (put_user(info.channel, &src->channel) || + put_user(info.offset, &src->offset) || + put_user(info.first, &src->first) || + put_user(info.step, &src->step)) + return -EFAULT; + return err; +} + +struct sndrv_pcm_status32 { + s32 state; + struct compat_timespec trigger_tstamp; + struct compat_timespec tstamp; + u32 appl_ptr; + u32 hw_ptr; + s32 delay; + u32 avail; + u32 avail_max; + u32 overrange; + s32 suspended_state; + unsigned char reserved[60]; +} __attribute__((packed)); + + +static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_status32 __user *src) +{ + snd_pcm_status_t status; + int err; + + err = snd_pcm_status(substream, &status); + if (err < 0) + return err; + + if (put_user(status.state, &src->state) || + put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) || + put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) || + put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + put_user(status.appl_ptr, &src->appl_ptr) || + put_user(status.hw_ptr, &src->hw_ptr) || + put_user(status.delay, &src->delay) || + put_user(status.avail, &src->avail) || + put_user(status.avail_max, &src->avail_max) || + put_user(status.overrange, &src->overrange) || + put_user(status.suspended_state, &src->suspended_state)) + return -EFAULT; + + return err; +} + +/* recalcuate the boundary within 32bit */ +static void recalculate_boundary(snd_pcm_runtime_t *runtime) +{ + if (! runtime->buffer_size) + return; + runtime->boundary = runtime->buffer_size; + while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) + runtime->boundary *= 2; +} + +/* both for HW_PARAMS and HW_REFINE */ +static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream, + int refine, + struct sndrv_pcm_hw_params32 __user *data32) +{ + struct sndrv_pcm_hw_params *data; + snd_pcm_runtime_t *runtime; + int err; + + if (! (runtime = substream->runtime)) + return -ENOTTY; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + /* only fifo_size is different, so just copy all */ + if (copy_from_user(data, data32, sizeof(*data32))) { + err = -EFAULT; + goto error; + } + if (refine) + err = snd_pcm_hw_refine(substream, data); + else + err = snd_pcm_hw_params(substream, data); + if (err < 0) + goto error; + if (copy_to_user(data32, data, sizeof(*data32)) || + put_user(data->fifo_size, &data32->fifo_size)) { + err = -EFAULT; + goto error; + } + + if (! refine) + recalculate_boundary(runtime); + error: + kfree(data); + return err; +} + + +/* + */ +struct sndrv_xferi32 { + s32 result; + u32 buf; + u32 frames; +}; + +static int snd_pcm_ioctl_xferi_compat(snd_pcm_substream_t *substream, + int dir, struct sndrv_xferi32 __user *data32) +{ + compat_caddr_t buf; + u32 frames; + int err; + + if (! substream->runtime) + return -ENOTTY; + if (substream->stream != dir) + return -EINVAL; + if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + return -EBADFD; + + if (get_user(buf, &data32->buf) || + get_user(frames, &data32->frames)) + return -EFAULT; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_lib_write(substream, compat_ptr(buf), frames); + else + err = snd_pcm_lib_read(substream, compat_ptr(buf), frames); + if (err < 0) + return err; + /* copy the result */ + if (put_user(err, &data32->result)) + return -EFAULT; + return 0; +} + + +/* snd_xfern needs remapping of bufs */ +struct sndrv_xfern32 { + s32 result; + u32 bufs; /* this is void **; */ + u32 frames; +}; + +/* + * xfern ioctl nees to copy (up to) 128 pointers on stack. + * although we may pass the copied pointers through f_op->ioctl, but the ioctl + * handler there expands again the same 128 pointers on stack, so it is better + * to handle the function (calling pcm_readv/writev) directly in this handler. + */ +static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream, + int dir, struct sndrv_xfern32 __user *data32) +{ + compat_caddr_t buf; + compat_caddr_t __user *bufptr; + u32 frames; + void __user **bufs; + int err, ch, i; + + if (! substream->runtime) + return -ENOTTY; + if (substream->stream != dir) + return -EINVAL; + + if ((ch = substream->runtime->channels) > 128) + return -EINVAL; + if (get_user(buf, &data32->bufs) || + get_user(frames, &data32->frames)) + return -EFAULT; + bufptr = compat_ptr(buf); + bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL); + if (bufs == NULL) + return -ENOMEM; + for (i = 0; i < ch; i++) { + u32 ptr; + if (get_user(ptr, bufptr)) { + kfree(bufs); + return -EFAULT; + } + bufs[ch] = compat_ptr(ptr); + bufptr++; + } + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + err = snd_pcm_lib_writev(substream, bufs, frames); + else + err = snd_pcm_lib_readv(substream, bufs, frames); + if (err >= 0) { + if (put_user(err, &data32->result)) + err = -EFAULT; + } + kfree(bufs); + return err; +} + + +struct sndrv_pcm_mmap_status32 { + s32 state; + s32 pad1; + u32 hw_ptr; + struct compat_timespec tstamp; + s32 suspended_state; +} __attribute__((packed)); + +struct sndrv_pcm_mmap_control32 { + u32 appl_ptr; + u32 avail_min; +}; + +struct sndrv_pcm_sync_ptr32 { + u32 flags; + union { + struct sndrv_pcm_mmap_status32 status; + unsigned char reserved[64]; + } s; + union { + struct sndrv_pcm_mmap_control32 control; + unsigned char reserved[64]; + } c; +} __attribute__((packed)); + +static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream, + struct sndrv_pcm_sync_ptr32 __user *src) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + volatile struct sndrv_pcm_mmap_status *status; + volatile struct sndrv_pcm_mmap_control *control; + u32 sflags; + struct sndrv_pcm_mmap_control scontrol; + struct sndrv_pcm_mmap_status sstatus; + int err; + + snd_assert(runtime, return -EINVAL); + + if (get_user(sflags, &src->flags) || + get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || + get_user(scontrol.avail_min, &src->c.control.avail_min)) + return -EFAULT; + if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { + err = snd_pcm_hwsync(substream); + if (err < 0) + return err; + } + status = runtime->status; + control = runtime->control; + snd_pcm_stream_lock_irq(substream); + if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) + control->appl_ptr = scontrol.appl_ptr; + else + scontrol.appl_ptr = control->appl_ptr; + if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) + control->avail_min = scontrol.avail_min; + else + scontrol.avail_min = control->avail_min; + sstatus.state = status->state; + sstatus.hw_ptr = status->hw_ptr; + sstatus.tstamp = status->tstamp; + sstatus.suspended_state = status->suspended_state; + snd_pcm_stream_unlock_irq(substream); + if (put_user(sstatus.state, &src->s.status.state) || + put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || + put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) || + put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) || + put_user(sstatus.suspended_state, &src->s.status.suspended_state) || + put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || + put_user(scontrol.avail_min, &src->c.control.avail_min)) + return -EFAULT; + + return 0; +} + + +/* + */ +enum { + SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32), + SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32), + SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32), + SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32), + SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32), + SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32), + SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32), + SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32), + SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32), + SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32), + SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32), + SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32), + SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32), + +}; + +static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + snd_pcm_file_t *pcm_file; + snd_pcm_substream_t *substream; + void __user *argp = compat_ptr(arg); + + pcm_file = file->private_data; + if (! pcm_file) + return -ENOTTY; + substream = pcm_file->substream; + if (! substream) + return -ENOTTY; + + /* + * When PCM is used on 32bit mode, we need to disable + * mmap of PCM status/control records because of the size + * incompatibility. + */ + substream->no_mmap_ctrl = 1; + + switch (cmd) { + case SNDRV_PCM_IOCTL_PVERSION: + case SNDRV_PCM_IOCTL_INFO: + case SNDRV_PCM_IOCTL_TSTAMP: + case SNDRV_PCM_IOCTL_HWSYNC: + case SNDRV_PCM_IOCTL_PREPARE: + case SNDRV_PCM_IOCTL_RESET: + case SNDRV_PCM_IOCTL_START: + case SNDRV_PCM_IOCTL_DROP: + case SNDRV_PCM_IOCTL_DRAIN: + case SNDRV_PCM_IOCTL_PAUSE: + case SNDRV_PCM_IOCTL_HW_FREE: + case SNDRV_PCM_IOCTL_RESUME: + case SNDRV_PCM_IOCTL_XRUN: + case SNDRV_PCM_IOCTL_LINK: + case SNDRV_PCM_IOCTL_UNLINK: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + return snd_pcm_playback_ioctl1(substream, cmd, argp); + else + return snd_pcm_capture_ioctl1(substream, cmd, argp); + case SNDRV_PCM_IOCTL_HW_REFINE32: + return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); + case SNDRV_PCM_IOCTL_HW_PARAMS32: + return snd_pcm_ioctl_hw_params_compat(substream, 0, argp); + case SNDRV_PCM_IOCTL_SW_PARAMS32: + return snd_pcm_ioctl_sw_params_compat(substream, argp); + case SNDRV_PCM_IOCTL_STATUS32: + return snd_pcm_status_user_compat(substream, argp); + case SNDRV_PCM_IOCTL_SYNC_PTR32: + return snd_pcm_ioctl_sync_ptr_compat(substream, argp); + case SNDRV_PCM_IOCTL_CHANNEL_INFO32: + return snd_pcm_ioctl_channel_info_compat(substream, argp); + case SNDRV_PCM_IOCTL_WRITEI_FRAMES32: + return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); + case SNDRV_PCM_IOCTL_READI_FRAMES32: + return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); + case SNDRV_PCM_IOCTL_WRITEN_FRAMES32: + return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp); + case SNDRV_PCM_IOCTL_READN_FRAMES32: + return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp); + case SNDRV_PCM_IOCTL_DELAY32: + return snd_pcm_ioctl_delay_compat(substream, argp); + case SNDRV_PCM_IOCTL_REWIND32: + return snd_pcm_ioctl_rewind_compat(substream, argp); + case SNDRV_PCM_IOCTL_FORWARD32: + return snd_pcm_ioctl_forward_compat(substream, argp); + } + + return -ENOIOCTLCMD; +} --- linux/sound/core/pcm_native.c 30 Nov 2004 19:58:22 -0000 1.88 +++ linux/sound/core/pcm_native.c 18 Jan 2005 14:52:43 -0000 @@ -65,7 +65,7 @@ * */ -rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(snd_pcm_link_rwlock); static DECLARE_RWSEM(snd_pcm_link_rwsem); @@ -2640,40 +2640,28 @@ return snd_pcm_common_ioctl1(substream, cmd, arg); } -static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } -static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_file_t *pcm_file; - int err; pcm_file = file->private_data; if (((cmd >> 8) & 0xff) != 'A') return -ENOTTY; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); - lock_kernel(); - return err; + return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); } int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, @@ -3198,6 +3186,15 @@ } /* + * ioctl32 compat + */ +#ifdef CONFIG_COMPAT +#include "pcm_compat.c" +#else +#define snd_pcm_ioctl_compat NULL +#endif + +/* * To be removed helpers to keep binary compatibility */ @@ -3318,7 +3315,8 @@ .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_playback_poll, - .ioctl = snd_pcm_playback_ioctl, + .unlocked_ioctl = snd_pcm_playback_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, }; @@ -3330,7 +3328,8 @@ .open = snd_pcm_open, .release = snd_pcm_release, .poll = snd_pcm_capture_poll, - .ioctl = snd_pcm_capture_ioctl, + .unlocked_ioctl = snd_pcm_capture_ioctl, + .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, }; ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/3] Conversion to compat_ioctl for ALSA drivers 2005-01-18 16:36 ` [PATCH 2/3] " Takashi Iwai @ 2005-01-18 16:37 ` Takashi Iwai 2005-01-18 18:51 ` [PATCH 3/3] Resend: " Takashi Iwai 0 siblings, 1 reply; 7+ messages in thread From: Takashi Iwai @ 2005-01-18 16:37 UTC (permalink / raw) To: akpm; +Cc: linux-kernel, ak, perex The last patch covers the rest of ALSA APIs: hwdep, rawmidi, timer and seq. Also it covers the OSS emulation modules. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- linux/sound/core/hwdep.c 30 Nov 2004 19:58:21 -0000 1.24 +++ linux/sound/core/hwdep.c 18 Jan 2005 14:52:43 -0000 @@ -232,8 +232,7 @@ return 0; } -static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) +static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg) { snd_hwdep_t *hw = file->private_data; void __user *argp = (void __user *)arg; @@ -252,17 +251,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_hwdep_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_hwdep_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma) { snd_hwdep_t *hw = file->private_data; @@ -315,6 +303,12 @@ return -ENOIOCTLCMD; } +#ifdef CONFIG_COMPAT +#include "hwdep_compat.c" +#else +#define snd_hwdep_ioctl_compat NULL +#endif + /* */ @@ -328,7 +322,8 @@ .open = snd_hwdep_open, .release = snd_hwdep_release, .poll = snd_hwdep_poll, - .ioctl = snd_hwdep_ioctl, + .unlocked_ioctl = snd_hwdep_ioctl, + .compat_ioctl = snd_hwdep_ioctl_compat, .mmap = snd_hwdep_mmap, }; @@ -509,12 +504,14 @@ } snd_hwdep_proc_entry = entry; snd_ctl_register_ioctl(snd_hwdep_control_ioctl); + snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl); return 0; } static void __exit alsa_hwdep_exit(void) { snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl); if (snd_hwdep_proc_entry) { snd_info_unregister(snd_hwdep_proc_entry); snd_hwdep_proc_entry = NULL; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/hwdep_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,77 @@ +/* + * 32bit -> 64bit ioctl wrapper for hwdep API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file is included from hwdep.c */ + +#include <linux/compat.h> + +struct sndrv_hwdep_dsp_image32 { + u32 index; + unsigned char name[64]; + u32 image; /* pointer */ + u32 length; + u32 driver_data; +} /* don't set packed attribute here */; + +static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw, + struct sndrv_hwdep_dsp_image32 __user *src) +{ + struct sndrv_hwdep_dsp_image *dst; + compat_caddr_t ptr; + u32 val; + + dst = compat_alloc_user_space(sizeof(*dst)); + + /* index and name */ + if (copy_in_user(dst, src, 4 + 64)) + return -EFAULT; + if (get_user(ptr, &src->image) || + put_user(compat_ptr(ptr), &dst->image)) + return -EFAULT; + if (get_user(val, &src->length) || + put_user(val, &dst->length)) + return -EFAULT; + if (get_user(val, &src->driver_data) || + put_user(val, &dst->driver_data)) + return -EFAULT; + + return snd_hwdep_dsp_load(hw, dst); +} + +enum { + SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32) +}; + +static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg) +{ + snd_hwdep_t *hw = file->private_data; + void __user *argp = compat_ptr(arg); + switch (cmd) { + case SNDRV_HWDEP_IOCTL_PVERSION: + case SNDRV_HWDEP_IOCTL_INFO: + case SNDRV_HWDEP_IOCTL_DSP_STATUS: + return snd_hwdep_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_HWDEP_IOCTL_DSP_LOAD32: + return snd_hwdep_dsp_load_compat(hw, argp); + } + if (hw->ops.ioctl_compat) + return hw->ops.ioctl_compat(hw, file, cmd, arg); + return -ENOIOCTLCMD; +} --- linux/sound/core/rawmidi.c 5 Jan 2005 21:55:20 -0000 1.46 +++ linux/sound/core/rawmidi.c 18 Jan 2005 14:52:43 -0000 @@ -673,8 +673,7 @@ return 0; } -static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_rawmidi_file_t *rfile; void __user *argp = (void __user *)arg; @@ -784,17 +783,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_rawmidi_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_rawmidi_control_ioctl(snd_card_t * card, snd_ctl_file_t * control, unsigned int cmd, @@ -1278,6 +1266,14 @@ } /* + */ +#ifdef CONFIG_COMPAT +#include "rawmidi_compat.c" +#else +#define snd_rawmidi_ioctl_comapt NULL +#endif + +/* */ @@ -1347,7 +1343,8 @@ .open = snd_rawmidi_open, .release = snd_rawmidi_release, .poll = snd_rawmidi_poll, - .ioctl = snd_rawmidi_ioctl, + .unlocked_ioctl = snd_rawmidi_ioctl, + .compat_ioctl = snd_rawmidi_ioctl_compat, }; static snd_minor_t snd_rawmidi_reg = @@ -1628,6 +1625,7 @@ { snd_ctl_register_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl); #ifdef CONFIG_SND_OSSEMUL { int i; /* check device map table */ @@ -1649,6 +1647,7 @@ static void __exit alsa_rawmidi_exit(void) { snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl); } module_init(alsa_rawmidi_init) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/rawmidi_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,120 @@ +/* + * 32bit -> 64bit ioctl wrapper for raw MIDI API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from rawmidi.c */ + +#include <linux/compat.h> + +struct sndrv_rawmidi_params32 { + s32 stream; + u32 buffer_size; + u32 avail_min; + unsigned int no_active_sensing; /* avoid bit-field */ + unsigned char reserved[16]; +} __attribute__((packed)); + +static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile, + struct sndrv_rawmidi_params32 __user *src) +{ + snd_rawmidi_params_t params; + unsigned int val; + + if (rfile->output == NULL) + return -EINVAL; + if (get_user(params.stream, &src->stream) || + get_user(params.buffer_size, &src->buffer_size) || + get_user(params.avail_min, &src->avail_min) || + get_user(val, &src->no_active_sensing)) + return -EFAULT; + params.no_active_sensing = val; + switch (params.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + return snd_rawmidi_output_params(rfile->output, ¶ms); + case SNDRV_RAWMIDI_STREAM_INPUT: + return snd_rawmidi_input_params(rfile->input, ¶ms); + } + return -EINVAL; +} + +struct sndrv_rawmidi_status32 { + s32 stream; + struct compat_timespec tstamp; + u32 avail; + u32 xruns; + unsigned char reserved[16]; +} __attribute__((packed)); + +static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile, + struct sndrv_rawmidi_status32 __user *src) +{ + int err; + snd_rawmidi_status_t status; + + if (rfile->output == NULL) + return -EINVAL; + if (get_user(status.stream, &src->stream)) + return -EFAULT; + + switch (status.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + err = snd_rawmidi_output_status(rfile->output, &status); + break; + case SNDRV_RAWMIDI_STREAM_INPUT: + err = snd_rawmidi_input_status(rfile->input, &status); + break; + default: + return -EINVAL; + } + if (err < 0) + return err; + + if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + put_user(status.avail, &src->avail) || + put_user(status.xruns, &src->xruns)) + return -EFAULT; + + return 0; +} + +enum { + SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32), + SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32), +}; + +static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + snd_rawmidi_file_t *rfile; + void __user *argp = compat_ptr(arg); + + rfile = file->private_data; + switch (cmd) { + case SNDRV_RAWMIDI_IOCTL_PVERSION: + case SNDRV_RAWMIDI_IOCTL_INFO: + case SNDRV_RAWMIDI_IOCTL_DROP: + case SNDRV_RAWMIDI_IOCTL_DRAIN: + return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_RAWMIDI_IOCTL_PARAMS32: + return snd_rawmidi_ioctl_params_compat(rfile, argp); + case SNDRV_RAWMIDI_IOCTL_STATUS32: + return snd_rawmidi_ioctl_status_compat(rfile, argp); + } + return -ENOIOCTLCMD; +} --- linux/sound/core/timer.c 29 Nov 2004 14:03:52 -0000 1.48 +++ linux/sound/core/timer.c 18 Jan 2005 14:52:43 -0000 @@ -76,7 +76,7 @@ static LIST_HEAD(snd_timer_slave_list); /* lock for slave active lists */ -static spinlock_t slave_active_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(slave_active_lock); static DECLARE_MUTEX(register_mutex); @@ -1653,8 +1653,7 @@ return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; } -static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_timer_user_t *tu; void __user *argp = (void __user *)arg; @@ -1701,17 +1700,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_timer_user_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_timer_user_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_timer_user_fasync(int fd, struct file * file, int on) { snd_timer_user_t *tu; @@ -1803,6 +1791,12 @@ return mask; } +#ifdef CONFIG_COMPAT +#include "timer_compat.c" +#else +#define snd_timer_user_ioctl_compat NULL +#endif + static struct file_operations snd_timer_f_ops = { .owner = THIS_MODULE, @@ -1810,7 +1804,8 @@ .open = snd_timer_user_open, .release = snd_timer_user_release, .poll = snd_timer_user_poll, - .ioctl = snd_timer_user_ioctl, + .unlocked_ioctl = snd_timer_user_ioctl, + .compat_ioctl = snd_timer_user_ioctl_compat, .fasync = snd_timer_user_fasync, }; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/timer_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,119 @@ +/* + * 32bit -> 64bit ioctl wrapper for timer API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from timer.c */ + +#include <linux/compat.h> + +struct sndrv_timer_info32 { + u32 flags; + s32 card; + unsigned char id[64]; + unsigned char name[80]; + u32 reserved0; + u32 resolution; + unsigned char reserved[64]; +}; + +static int snd_timer_user_info_compat(struct file *file, + struct sndrv_timer_info32 __user *_info) +{ + snd_timer_user_t *tu; + struct sndrv_timer_info32 info; + snd_timer_t *t; + + tu = file->private_data; + snd_assert(tu->timeri != NULL, return -ENXIO); + t = tu->timeri->timer; + snd_assert(t != NULL, return -ENXIO); + memset(&info, 0, sizeof(info)); + info.card = t->card ? t->card->number : -1; + if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) + info.flags |= SNDRV_TIMER_FLG_SLAVE; + strlcpy(info.id, t->id, sizeof(info.id)); + strlcpy(info.name, t->name, sizeof(info.name)); + info.resolution = t->hw.resolution; + if (copy_to_user(_info, &info, sizeof(*_info))) + return -EFAULT; + return 0; +} + +struct sndrv_timer_status32 { + struct compat_timespec tstamp; + u32 resolution; + u32 lost; + u32 overrun; + u32 queue; + unsigned char reserved[64]; +}; + +static int snd_timer_user_status_compat(struct file *file, + struct sndrv_timer_status32 __user *_status) +{ + snd_timer_user_t *tu; + snd_timer_status_t status; + + tu = file->private_data; + snd_assert(tu->timeri != NULL, return -ENXIO); + memset(&status, 0, sizeof(status)); + status.tstamp = tu->tstamp; + status.resolution = snd_timer_resolution(tu->timeri); + status.lost = tu->timeri->lost; + status.overrun = tu->overrun; + spin_lock_irq(&tu->qlock); + status.queue = tu->qused; + spin_unlock_irq(&tu->qlock); + if (copy_to_user(_status, &status, sizeof(status))) + return -EFAULT; + return 0; +} + +/* + */ + +enum { + SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32), + SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32), +}; + +static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *argp = compat_ptr(arg); + + switch (cmd) { + case SNDRV_TIMER_IOCTL_PVERSION: + case SNDRV_TIMER_IOCTL_TREAD: + case SNDRV_TIMER_IOCTL_GINFO: + case SNDRV_TIMER_IOCTL_GPARAMS: + case SNDRV_TIMER_IOCTL_GSTATUS: + case SNDRV_TIMER_IOCTL_SELECT: + case SNDRV_TIMER_IOCTL_PARAMS: + case SNDRV_TIMER_IOCTL_START: + case SNDRV_TIMER_IOCTL_STOP: + case SNDRV_TIMER_IOCTL_CONTINUE: + case SNDRV_TIMER_IOCTL_NEXT_DEVICE: + return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_TIMER_IOCTL_INFO32: + return snd_timer_user_info_compat(file, argp); + case SNDRV_TIMER_IOCTL_STATUS32: + return snd_timer_user_status_compat(file, argp); + } + return -ENOIOCTLCMD; +} --- linux/sound/core/oss/mixer_oss.c 30 Nov 2004 19:58:22 -0000 1.33 +++ linux/sound/core/oss/mixer_oss.c 18 Jan 2005 14:44:19 -0000 @@ -359,16 +359,9 @@ return -ENXIO; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int err; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg); - lock_kernel(); - return err; + return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg); } int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg) @@ -384,6 +377,13 @@ return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); } +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl +#else +#define snd_mixer_oss_ioctl_compat NULL +#endif + /* * REGISTRATION PART */ @@ -393,7 +393,8 @@ .owner = THIS_MODULE, .open = snd_mixer_oss_open, .release = snd_mixer_oss_release, - .ioctl = snd_mixer_oss_ioctl, + .unlocked_ioctl = snd_mixer_oss_ioctl, + .compat_ioctl = snd_mixer_oss_ioctl_compat, }; static snd_minor_t snd_mixer_oss_reg = --- linux/sound/core/oss/pcm_oss.c 30 Nov 2004 19:58:22 -0000 1.68 +++ linux/sound/core/oss/pcm_oss.c 18 Jan 2005 14:45:08 -0000 @@ -1913,8 +1913,7 @@ return 0; } -static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_oss_file_t *pcm_oss_file; int __user *p = (int __user *)arg; @@ -2073,16 +2072,12 @@ return -EINVAL; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_pcm_oss_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl +#else +#define snd_pcm_oss_ioctl_compat NULL +#endif static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { @@ -2410,7 +2405,8 @@ .open = snd_pcm_oss_open, .release = snd_pcm_oss_release, .poll = snd_pcm_oss_poll, - .ioctl = snd_pcm_oss_ioctl, + .unlocked_ioctl = snd_pcm_oss_ioctl, + .compat_ioctl = snd_pcm_oss_ioctl_compat, .mmap = snd_pcm_oss_mmap, }; --- linux/sound/core/seq/seq_clientmgr.c 30 Nov 2004 19:58:22 -0000 1.40 +++ linux/sound/core/seq/seq_clientmgr.c 18 Jan 2005 14:52:51 -0000 @@ -51,7 +51,7 @@ #define SNDRV_SEQ_LFLG_OUTPUT 0x0002 #define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT) -static spinlock_t clients_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(clients_lock); static DECLARE_MUTEX(register_mutex); /* @@ -2131,21 +2131,20 @@ } -static int snd_seq_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { client_t *client = (client_t *) file->private_data; - int err; snd_assert(client != NULL, return -ENXIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_do_ioctl(client, cmd, (void __user *) arg); - lock_kernel(); - return err; + return snd_seq_do_ioctl(client, cmd, (void __user *) arg); } +#ifdef CONFIG_COMPAT +#include "seq_compat.c" +#else +#define snd_seq_ioctl_compat NULL +#endif /* -------------------------------------------------------- */ @@ -2462,7 +2461,8 @@ .open = snd_seq_open, .release = snd_seq_release, .poll = snd_seq_poll, - .ioctl = snd_seq_ioctl, + .unlocked_ioctl = snd_seq_ioctl, + .compat_ioctl = snd_seq_ioctl_compat, }; static snd_minor_t snd_seq_reg = --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/seq/seq_compat.c 18 Jan 2005 15:37:41 -0000 @@ -0,0 +1,137 @@ +/* + * 32bit -> 64bit ioctl wrapper for sequencer API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from seq.c */ + +#include <linux/compat.h> + +struct sndrv_seq_port_info32 { + struct sndrv_seq_addr addr; /* client/port numbers */ + char name[64]; /* port name */ + + u32 capability; /* port capability bits */ + u32 type; /* port type bits */ + s32 midi_channels; /* channels per MIDI port */ + s32 midi_voices; /* voices per MIDI port */ + s32 synth_voices; /* voices per SYNTH port */ + + s32 read_use; /* R/O: subscribers for output (from this port) */ + s32 write_use; /* R/O: subscribers for input (to this port) */ + + u32 kernel; /* reserved for kernel use (must be NULL) */ + u32 flags; /* misc. conditioning */ + unsigned char time_queue; /* queue # for timestamping */ + char reserved[59]; /* for future use */ +}; + +static int snd_seq_call_port_info_ioctl(client_t *client, unsigned int cmd, + struct sndrv_seq_port_info32 __user *data32) +{ + int err = -EFAULT; + snd_seq_port_info_t *data; + mm_segment_t fs; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (! data) + return -ENOMEM; + + if (copy_from_user(data, data32, sizeof(*data32)) || + get_user(data->flags, &data32->flags) || + get_user(data->time_queue, &data32->time_queue)) + goto error; + data->kernel = NULL; + + fs = snd_enter_user(); + err = snd_seq_do_ioctl(client, cmd, data); + snd_leave_user(fs); + if (err < 0) + goto error; + + if (copy_to_user(data32, data, sizeof(*data32)) || + put_user(data->flags, &data32->flags) || + put_user(data->time_queue, &data32->time_queue)) + err = -EFAULT; + + error: + kfree(data); + return err; +} + + + +/* + */ + +enum { + SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32), +}; + +static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + client_t *client = (client_t *) file->private_data; + void __user *argp = compat_ptr(arg); + + snd_assert(client != NULL, return -ENXIO); + + switch (cmd) { + case SNDRV_SEQ_IOCTL_PVERSION: + case SNDRV_SEQ_IOCTL_CLIENT_ID: + case SNDRV_SEQ_IOCTL_SYSTEM_INFO: + case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO: + case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO: + case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT: + case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT: + case SNDRV_SEQ_IOCTL_CREATE_QUEUE: + case SNDRV_SEQ_IOCTL_DELETE_QUEUE: + case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO: + case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO: + case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE: + case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS: + case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO: + case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO: + case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER: + case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER: + case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT: + case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT: + case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL: + case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL: + case SNDRV_SEQ_IOCTL_REMOVE_EVENTS: + case SNDRV_SEQ_IOCTL_QUERY_SUBS: + case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: + case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: + case SNDRV_SEQ_IOCTL_RUNNING_MODE: + return snd_seq_do_ioctl(client, cmd, argp); + case SNDRV_SEQ_IOCTL_CREATE_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); + case SNDRV_SEQ_IOCTL_DELETE_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp); + case SNDRV_SEQ_IOCTL_GET_PORT_INFO32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp); + case SNDRV_SEQ_IOCTL_SET_PORT_INFO32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp); + case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp); + } + return -ENOIOCTLCMD; +} --- linux/sound/core/seq/oss/seq_oss.c 4 Oct 2004 10:06:21 -0000 1.14 +++ linux/sound/core/seq/oss/seq_oss.c 18 Jan 2005 14:49:15 -0000 @@ -59,7 +59,7 @@ static int odev_release(struct inode *inode, struct file *file); static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset); static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset); -static int odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static unsigned int odev_poll(struct file *file, poll_table * wait); #ifdef CONFIG_PROC_FS static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf); @@ -177,20 +177,20 @@ return snd_seq_oss_write(dp, buf, count, file); } -static int -odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long +odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { seq_oss_devinfo_t *dp; - int err; dp = file->private_data; snd_assert(dp != NULL, return -EIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_oss_ioctl(dp, cmd, arg); - lock_kernel(); - return err; + return snd_seq_oss_ioctl(dp, cmd, arg); } +#ifdef CONFIG_COMPAT +#define odev_ioctl_compat odev_ioctl +#else +#define odev_ioctl_compat NULL +#endif static unsigned int odev_poll(struct file *file, poll_table * wait) @@ -213,7 +213,8 @@ .open = odev_open, .release = odev_release, .poll = odev_poll, - .ioctl = odev_ioctl, + .unlocked_ioctl = odev_ioctl, + .compat_ioctl = odev_ioctl_compat, }; static snd_minor_t seq_oss_reg = { --- linux/include/sound/hwdep.h 23 Jun 2004 13:34:03 -0000 1.5 +++ linux/include/sound/hwdep.h 18 Jan 2005 14:53:20 -0000 @@ -38,6 +38,7 @@ int (*release) (snd_hwdep_t * hw, struct file * file); unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait); int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg); + int (*ioctl_compat) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg); int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma); int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status); int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image); ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/3] Resend: Conversion to compat_ioctl for ALSA drivers 2005-01-18 16:37 ` [PATCH 3/3] " Takashi Iwai @ 2005-01-18 18:51 ` Takashi Iwai 0 siblings, 0 replies; 7+ messages in thread From: Takashi Iwai @ 2005-01-18 18:51 UTC (permalink / raw) To: akpm; +Cc: linux-kernel, ak, perex Sorry, the last patch I sent included a typo. (Thanks Mathieu Segaud to point it out) The fixed version is below: ================ The last patch covers the rest of ALSA APIs: hwdep, rawmidi, timer and seq. Also it covers the OSS emulation modules. Signed-off-by: Takashi Iwai <tiwai@suse.de> --- linux/sound/core/hwdep.c 30 Nov 2004 19:58:21 -0000 1.24 +++ linux/sound/core/hwdep.c 18 Jan 2005 14:52:43 -0000 @@ -232,8 +232,7 @@ return 0; } -static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) +static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg) { snd_hwdep_t *hw = file->private_data; void __user *argp = (void __user *)arg; @@ -252,17 +251,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_hwdep_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_hwdep_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma) { snd_hwdep_t *hw = file->private_data; @@ -315,6 +303,12 @@ return -ENOIOCTLCMD; } +#ifdef CONFIG_COMPAT +#include "hwdep_compat.c" +#else +#define snd_hwdep_ioctl_compat NULL +#endif + /* */ @@ -328,7 +322,8 @@ .open = snd_hwdep_open, .release = snd_hwdep_release, .poll = snd_hwdep_poll, - .ioctl = snd_hwdep_ioctl, + .unlocked_ioctl = snd_hwdep_ioctl, + .compat_ioctl = snd_hwdep_ioctl_compat, .mmap = snd_hwdep_mmap, }; @@ -509,12 +504,14 @@ } snd_hwdep_proc_entry = entry; snd_ctl_register_ioctl(snd_hwdep_control_ioctl); + snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl); return 0; } static void __exit alsa_hwdep_exit(void) { snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl); if (snd_hwdep_proc_entry) { snd_info_unregister(snd_hwdep_proc_entry); snd_hwdep_proc_entry = NULL; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/hwdep_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,77 @@ +/* + * 32bit -> 64bit ioctl wrapper for hwdep API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file is included from hwdep.c */ + +#include <linux/compat.h> + +struct sndrv_hwdep_dsp_image32 { + u32 index; + unsigned char name[64]; + u32 image; /* pointer */ + u32 length; + u32 driver_data; +} /* don't set packed attribute here */; + +static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw, + struct sndrv_hwdep_dsp_image32 __user *src) +{ + struct sndrv_hwdep_dsp_image *dst; + compat_caddr_t ptr; + u32 val; + + dst = compat_alloc_user_space(sizeof(*dst)); + + /* index and name */ + if (copy_in_user(dst, src, 4 + 64)) + return -EFAULT; + if (get_user(ptr, &src->image) || + put_user(compat_ptr(ptr), &dst->image)) + return -EFAULT; + if (get_user(val, &src->length) || + put_user(val, &dst->length)) + return -EFAULT; + if (get_user(val, &src->driver_data) || + put_user(val, &dst->driver_data)) + return -EFAULT; + + return snd_hwdep_dsp_load(hw, dst); +} + +enum { + SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32) +}; + +static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg) +{ + snd_hwdep_t *hw = file->private_data; + void __user *argp = compat_ptr(arg); + switch (cmd) { + case SNDRV_HWDEP_IOCTL_PVERSION: + case SNDRV_HWDEP_IOCTL_INFO: + case SNDRV_HWDEP_IOCTL_DSP_STATUS: + return snd_hwdep_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_HWDEP_IOCTL_DSP_LOAD32: + return snd_hwdep_dsp_load_compat(hw, argp); + } + if (hw->ops.ioctl_compat) + return hw->ops.ioctl_compat(hw, file, cmd, arg); + return -ENOIOCTLCMD; +} --- linux/sound/core/rawmidi.c 5 Jan 2005 21:55:20 -0000 1.46 +++ linux/sound/core/rawmidi.c 18 Jan 2005 14:52:43 -0000 @@ -673,8 +673,7 @@ return 0; } -static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_rawmidi_file_t *rfile; void __user *argp = (void __user *)arg; @@ -784,17 +783,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_rawmidi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_rawmidi_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_rawmidi_control_ioctl(snd_card_t * card, snd_ctl_file_t * control, unsigned int cmd, @@ -1278,6 +1266,14 @@ } /* + */ +#ifdef CONFIG_COMPAT +#include "rawmidi_compat.c" +#else +#define snd_rawmidi_ioctl_compat NULL +#endif + +/* */ @@ -1347,7 +1343,8 @@ .open = snd_rawmidi_open, .release = snd_rawmidi_release, .poll = snd_rawmidi_poll, - .ioctl = snd_rawmidi_ioctl, + .unlocked_ioctl = snd_rawmidi_ioctl, + .compat_ioctl = snd_rawmidi_ioctl_compat, }; static snd_minor_t snd_rawmidi_reg = @@ -1628,6 +1625,7 @@ { snd_ctl_register_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl); #ifdef CONFIG_SND_OSSEMUL { int i; /* check device map table */ @@ -1649,6 +1647,7 @@ static void __exit alsa_rawmidi_exit(void) { snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl); + snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl); } module_init(alsa_rawmidi_init) --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/rawmidi_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,120 @@ +/* + * 32bit -> 64bit ioctl wrapper for raw MIDI API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from rawmidi.c */ + +#include <linux/compat.h> + +struct sndrv_rawmidi_params32 { + s32 stream; + u32 buffer_size; + u32 avail_min; + unsigned int no_active_sensing; /* avoid bit-field */ + unsigned char reserved[16]; +} __attribute__((packed)); + +static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile, + struct sndrv_rawmidi_params32 __user *src) +{ + snd_rawmidi_params_t params; + unsigned int val; + + if (rfile->output == NULL) + return -EINVAL; + if (get_user(params.stream, &src->stream) || + get_user(params.buffer_size, &src->buffer_size) || + get_user(params.avail_min, &src->avail_min) || + get_user(val, &src->no_active_sensing)) + return -EFAULT; + params.no_active_sensing = val; + switch (params.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + return snd_rawmidi_output_params(rfile->output, ¶ms); + case SNDRV_RAWMIDI_STREAM_INPUT: + return snd_rawmidi_input_params(rfile->input, ¶ms); + } + return -EINVAL; +} + +struct sndrv_rawmidi_status32 { + s32 stream; + struct compat_timespec tstamp; + u32 avail; + u32 xruns; + unsigned char reserved[16]; +} __attribute__((packed)); + +static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile, + struct sndrv_rawmidi_status32 __user *src) +{ + int err; + snd_rawmidi_status_t status; + + if (rfile->output == NULL) + return -EINVAL; + if (get_user(status.stream, &src->stream)) + return -EFAULT; + + switch (status.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: + err = snd_rawmidi_output_status(rfile->output, &status); + break; + case SNDRV_RAWMIDI_STREAM_INPUT: + err = snd_rawmidi_input_status(rfile->input, &status); + break; + default: + return -EINVAL; + } + if (err < 0) + return err; + + if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) || + put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) || + put_user(status.avail, &src->avail) || + put_user(status.xruns, &src->xruns)) + return -EFAULT; + + return 0; +} + +enum { + SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32), + SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32), +}; + +static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + snd_rawmidi_file_t *rfile; + void __user *argp = compat_ptr(arg); + + rfile = file->private_data; + switch (cmd) { + case SNDRV_RAWMIDI_IOCTL_PVERSION: + case SNDRV_RAWMIDI_IOCTL_INFO: + case SNDRV_RAWMIDI_IOCTL_DROP: + case SNDRV_RAWMIDI_IOCTL_DRAIN: + return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_RAWMIDI_IOCTL_PARAMS32: + return snd_rawmidi_ioctl_params_compat(rfile, argp); + case SNDRV_RAWMIDI_IOCTL_STATUS32: + return snd_rawmidi_ioctl_status_compat(rfile, argp); + } + return -ENOIOCTLCMD; +} --- linux/sound/core/timer.c 29 Nov 2004 14:03:52 -0000 1.48 +++ linux/sound/core/timer.c 18 Jan 2005 14:52:43 -0000 @@ -76,7 +76,7 @@ static LIST_HEAD(snd_timer_slave_list); /* lock for slave active lists */ -static spinlock_t slave_active_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(slave_active_lock); static DECLARE_MUTEX(register_mutex); @@ -1653,8 +1653,7 @@ return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; } -static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_timer_user_t *tu; void __user *argp = (void __user *)arg; @@ -1701,17 +1700,6 @@ return -ENOTTY; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_timer_user_ioctl(struct inode *inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_timer_user_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} - static int snd_timer_user_fasync(int fd, struct file * file, int on) { snd_timer_user_t *tu; @@ -1803,6 +1791,12 @@ return mask; } +#ifdef CONFIG_COMPAT +#include "timer_compat.c" +#else +#define snd_timer_user_ioctl_compat NULL +#endif + static struct file_operations snd_timer_f_ops = { .owner = THIS_MODULE, @@ -1810,7 +1804,8 @@ .open = snd_timer_user_open, .release = snd_timer_user_release, .poll = snd_timer_user_poll, - .ioctl = snd_timer_user_ioctl, + .unlocked_ioctl = snd_timer_user_ioctl, + .compat_ioctl = snd_timer_user_ioctl_compat, .fasync = snd_timer_user_fasync, }; --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/timer_compat.c 18 Jan 2005 14:52:14 -0000 @@ -0,0 +1,119 @@ +/* + * 32bit -> 64bit ioctl wrapper for timer API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from timer.c */ + +#include <linux/compat.h> + +struct sndrv_timer_info32 { + u32 flags; + s32 card; + unsigned char id[64]; + unsigned char name[80]; + u32 reserved0; + u32 resolution; + unsigned char reserved[64]; +}; + +static int snd_timer_user_info_compat(struct file *file, + struct sndrv_timer_info32 __user *_info) +{ + snd_timer_user_t *tu; + struct sndrv_timer_info32 info; + snd_timer_t *t; + + tu = file->private_data; + snd_assert(tu->timeri != NULL, return -ENXIO); + t = tu->timeri->timer; + snd_assert(t != NULL, return -ENXIO); + memset(&info, 0, sizeof(info)); + info.card = t->card ? t->card->number : -1; + if (t->hw.flags & SNDRV_TIMER_HW_SLAVE) + info.flags |= SNDRV_TIMER_FLG_SLAVE; + strlcpy(info.id, t->id, sizeof(info.id)); + strlcpy(info.name, t->name, sizeof(info.name)); + info.resolution = t->hw.resolution; + if (copy_to_user(_info, &info, sizeof(*_info))) + return -EFAULT; + return 0; +} + +struct sndrv_timer_status32 { + struct compat_timespec tstamp; + u32 resolution; + u32 lost; + u32 overrun; + u32 queue; + unsigned char reserved[64]; +}; + +static int snd_timer_user_status_compat(struct file *file, + struct sndrv_timer_status32 __user *_status) +{ + snd_timer_user_t *tu; + snd_timer_status_t status; + + tu = file->private_data; + snd_assert(tu->timeri != NULL, return -ENXIO); + memset(&status, 0, sizeof(status)); + status.tstamp = tu->tstamp; + status.resolution = snd_timer_resolution(tu->timeri); + status.lost = tu->timeri->lost; + status.overrun = tu->overrun; + spin_lock_irq(&tu->qlock); + status.queue = tu->qused; + spin_unlock_irq(&tu->qlock); + if (copy_to_user(_status, &status, sizeof(status))) + return -EFAULT; + return 0; +} + +/* + */ + +enum { + SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32), + SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32), +}; + +static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + void __user *argp = compat_ptr(arg); + + switch (cmd) { + case SNDRV_TIMER_IOCTL_PVERSION: + case SNDRV_TIMER_IOCTL_TREAD: + case SNDRV_TIMER_IOCTL_GINFO: + case SNDRV_TIMER_IOCTL_GPARAMS: + case SNDRV_TIMER_IOCTL_GSTATUS: + case SNDRV_TIMER_IOCTL_SELECT: + case SNDRV_TIMER_IOCTL_PARAMS: + case SNDRV_TIMER_IOCTL_START: + case SNDRV_TIMER_IOCTL_STOP: + case SNDRV_TIMER_IOCTL_CONTINUE: + case SNDRV_TIMER_IOCTL_NEXT_DEVICE: + return snd_timer_user_ioctl(file, cmd, (unsigned long)argp); + case SNDRV_TIMER_IOCTL_INFO32: + return snd_timer_user_info_compat(file, argp); + case SNDRV_TIMER_IOCTL_STATUS32: + return snd_timer_user_status_compat(file, argp); + } + return -ENOIOCTLCMD; +} --- linux/sound/core/oss/mixer_oss.c 30 Nov 2004 19:58:22 -0000 1.33 +++ linux/sound/core/oss/mixer_oss.c 18 Jan 2005 14:44:19 -0000 @@ -359,16 +359,9 @@ return -ENXIO; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int err; - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg); - lock_kernel(); - return err; + return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg); } int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg) @@ -384,6 +377,13 @@ return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); } +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl +#else +#define snd_mixer_oss_ioctl_compat NULL +#endif + /* * REGISTRATION PART */ @@ -393,7 +393,8 @@ .owner = THIS_MODULE, .open = snd_mixer_oss_open, .release = snd_mixer_oss_release, - .ioctl = snd_mixer_oss_ioctl, + .unlocked_ioctl = snd_mixer_oss_ioctl, + .compat_ioctl = snd_mixer_oss_ioctl_compat, }; static snd_minor_t snd_mixer_oss_reg = --- linux/sound/core/oss/pcm_oss.c 30 Nov 2004 19:58:22 -0000 1.68 +++ linux/sound/core/oss/pcm_oss.c 18 Jan 2005 14:45:08 -0000 @@ -1913,8 +1913,7 @@ return 0; } -static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { snd_pcm_oss_file_t *pcm_oss_file; int __user *p = (int __user *)arg; @@ -2073,16 +2072,12 @@ return -EINVAL; } -/* FIXME: need to unlock BKL to allow preemption */ -static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int err; - unlock_kernel(); - err = _snd_pcm_oss_ioctl(inode, file, cmd, arg); - lock_kernel(); - return err; -} +#ifdef CONFIG_COMPAT +/* all compatible */ +#define snd_pcm_oss_ioctl_compat snd_pcm_oss_ioctl +#else +#define snd_pcm_oss_ioctl_compat NULL +#endif static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { @@ -2410,7 +2405,8 @@ .open = snd_pcm_oss_open, .release = snd_pcm_oss_release, .poll = snd_pcm_oss_poll, - .ioctl = snd_pcm_oss_ioctl, + .unlocked_ioctl = snd_pcm_oss_ioctl, + .compat_ioctl = snd_pcm_oss_ioctl_compat, .mmap = snd_pcm_oss_mmap, }; --- linux/sound/core/seq/seq_clientmgr.c 30 Nov 2004 19:58:22 -0000 1.40 +++ linux/sound/core/seq/seq_clientmgr.c 18 Jan 2005 14:52:51 -0000 @@ -51,7 +51,7 @@ #define SNDRV_SEQ_LFLG_OUTPUT 0x0002 #define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT) -static spinlock_t clients_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(clients_lock); static DECLARE_MUTEX(register_mutex); /* @@ -2131,21 +2131,20 @@ } -static int snd_seq_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { client_t *client = (client_t *) file->private_data; - int err; snd_assert(client != NULL, return -ENXIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_do_ioctl(client, cmd, (void __user *) arg); - lock_kernel(); - return err; + return snd_seq_do_ioctl(client, cmd, (void __user *) arg); } +#ifdef CONFIG_COMPAT +#include "seq_compat.c" +#else +#define snd_seq_ioctl_compat NULL +#endif /* -------------------------------------------------------- */ @@ -2462,7 +2461,8 @@ .open = snd_seq_open, .release = snd_seq_release, .poll = snd_seq_poll, - .ioctl = snd_seq_ioctl, + .unlocked_ioctl = snd_seq_ioctl, + .compat_ioctl = snd_seq_ioctl_compat, }; static snd_minor_t snd_seq_reg = --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux/sound/core/seq/seq_compat.c 18 Jan 2005 15:37:41 -0000 @@ -0,0 +1,137 @@ +/* + * 32bit -> 64bit ioctl wrapper for sequencer API + * Copyright (c) by Takashi Iwai <tiwai@suse.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* This file included from seq.c */ + +#include <linux/compat.h> + +struct sndrv_seq_port_info32 { + struct sndrv_seq_addr addr; /* client/port numbers */ + char name[64]; /* port name */ + + u32 capability; /* port capability bits */ + u32 type; /* port type bits */ + s32 midi_channels; /* channels per MIDI port */ + s32 midi_voices; /* voices per MIDI port */ + s32 synth_voices; /* voices per SYNTH port */ + + s32 read_use; /* R/O: subscribers for output (from this port) */ + s32 write_use; /* R/O: subscribers for input (to this port) */ + + u32 kernel; /* reserved for kernel use (must be NULL) */ + u32 flags; /* misc. conditioning */ + unsigned char time_queue; /* queue # for timestamping */ + char reserved[59]; /* for future use */ +}; + +static int snd_seq_call_port_info_ioctl(client_t *client, unsigned int cmd, + struct sndrv_seq_port_info32 __user *data32) +{ + int err = -EFAULT; + snd_seq_port_info_t *data; + mm_segment_t fs; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (! data) + return -ENOMEM; + + if (copy_from_user(data, data32, sizeof(*data32)) || + get_user(data->flags, &data32->flags) || + get_user(data->time_queue, &data32->time_queue)) + goto error; + data->kernel = NULL; + + fs = snd_enter_user(); + err = snd_seq_do_ioctl(client, cmd, data); + snd_leave_user(fs); + if (err < 0) + goto error; + + if (copy_to_user(data32, data, sizeof(*data32)) || + put_user(data->flags, &data32->flags) || + put_user(data->time_queue, &data32->time_queue)) + err = -EFAULT; + + error: + kfree(data); + return err; +} + + + +/* + */ + +enum { + SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32), + SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32), +}; + +static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) +{ + client_t *client = (client_t *) file->private_data; + void __user *argp = compat_ptr(arg); + + snd_assert(client != NULL, return -ENXIO); + + switch (cmd) { + case SNDRV_SEQ_IOCTL_PVERSION: + case SNDRV_SEQ_IOCTL_CLIENT_ID: + case SNDRV_SEQ_IOCTL_SYSTEM_INFO: + case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO: + case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO: + case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT: + case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT: + case SNDRV_SEQ_IOCTL_CREATE_QUEUE: + case SNDRV_SEQ_IOCTL_DELETE_QUEUE: + case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO: + case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO: + case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE: + case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS: + case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO: + case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO: + case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER: + case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER: + case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT: + case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT: + case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL: + case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL: + case SNDRV_SEQ_IOCTL_REMOVE_EVENTS: + case SNDRV_SEQ_IOCTL_QUERY_SUBS: + case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION: + case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT: + case SNDRV_SEQ_IOCTL_RUNNING_MODE: + return snd_seq_do_ioctl(client, cmd, argp); + case SNDRV_SEQ_IOCTL_CREATE_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp); + case SNDRV_SEQ_IOCTL_DELETE_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp); + case SNDRV_SEQ_IOCTL_GET_PORT_INFO32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp); + case SNDRV_SEQ_IOCTL_SET_PORT_INFO32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp); + case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32: + return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp); + } + return -ENOIOCTLCMD; +} --- linux/sound/core/seq/oss/seq_oss.c 4 Oct 2004 10:06:21 -0000 1.14 +++ linux/sound/core/seq/oss/seq_oss.c 18 Jan 2005 14:49:15 -0000 @@ -59,7 +59,7 @@ static int odev_release(struct inode *inode, struct file *file); static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset); static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset); -static int odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg); static unsigned int odev_poll(struct file *file, poll_table * wait); #ifdef CONFIG_PROC_FS static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf); @@ -177,20 +177,20 @@ return snd_seq_oss_write(dp, buf, count, file); } -static int -odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static long +odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { seq_oss_devinfo_t *dp; - int err; dp = file->private_data; snd_assert(dp != NULL, return -EIO); - /* FIXME: need to unlock BKL to allow preemption */ - unlock_kernel(); - err = snd_seq_oss_ioctl(dp, cmd, arg); - lock_kernel(); - return err; + return snd_seq_oss_ioctl(dp, cmd, arg); } +#ifdef CONFIG_COMPAT +#define odev_ioctl_compat odev_ioctl +#else +#define odev_ioctl_compat NULL +#endif static unsigned int odev_poll(struct file *file, poll_table * wait) @@ -213,7 +213,8 @@ .open = odev_open, .release = odev_release, .poll = odev_poll, - .ioctl = odev_ioctl, + .unlocked_ioctl = odev_ioctl, + .compat_ioctl = odev_ioctl_compat, }; static snd_minor_t seq_oss_reg = { --- linux/include/sound/hwdep.h 23 Jun 2004 13:34:03 -0000 1.5 +++ linux/include/sound/hwdep.h 18 Jan 2005 14:53:20 -0000 @@ -38,6 +38,7 @@ int (*release) (snd_hwdep_t * hw, struct file * file); unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait); int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg); + int (*ioctl_compat) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg); int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma); int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status); int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] Conversion to compat_ioctl for ALSA drivers 2005-01-18 16:32 [PATCH 0/3] Conversion to compat_ioctl for ALSA drivers Takashi Iwai 2005-01-18 16:35 ` [PATCH 1/3] " Takashi Iwai @ 2005-01-30 18:02 ` Brian Gerst 2005-01-31 13:39 ` Takashi Iwai 1 sibling, 1 reply; 7+ messages in thread From: Brian Gerst @ 2005-01-30 18:02 UTC (permalink / raw) To: Takashi Iwai; +Cc: akpm, linux-kernel, ak, perex [-- Attachment #1: Type: text/plain, Size: 567 bytes --] Takashi Iwai wrote: > Hi, > > the following three patches convert the 32bit ioctl layer of ALSA to > the new compat_ioctl (and unlocked_ioctl for native ioctls). > > The first patch covers the basic entries and control API. > The second patch is for PCM API. > The last one is for other APIs including OSS-emulation modules. > > After these patches are applied, remove the whole subtree in > sound/core/ioctl32. The files in this directory are no longer > necessary. Fix 32-bit calls to snd_pcm_channel_info(). Signed-off-by: Brian Gerst <bgerst@didntduck.org> [-- Attachment #2: alsa-pcm-compat --] [-- Type: text/plain, Size: 1876 bytes --] --- linux/sound/core/pcm_native.c.bak 2005-01-30 11:15:24.000000000 -0500 +++ linux/sound/core/pcm_native.c 2005-01-30 11:17:31.000000000 -0500 @@ -602,17 +602,13 @@ return 0; } -static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info) { - snd_pcm_channel_info_t info; snd_pcm_runtime_t *runtime; - int res; unsigned int channel; snd_assert(substream != NULL, return -ENXIO); - if (copy_from_user(&info, _info, sizeof(info))) - return -EFAULT; - channel = info.channel; + channel = info->channel; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { @@ -622,9 +618,19 @@ snd_pcm_stream_unlock_irq(substream); if (channel >= runtime->channels) return -EINVAL; - memset(&info, 0, sizeof(info)); - info.channel = channel; - res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info); + memset(info, 0, sizeof(*info)); + info->channel = channel; + return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info); +} + +static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info) +{ + snd_pcm_channel_info_t info; + int res; + + if (copy_from_user(&info, _info, sizeof(info))) + return -EFAULT; + res = snd_pcm_channel_info(substream, &info); if (res < 0) return res; if (copy_to_user(_info, &info, sizeof(info))) @@ -2440,7 +2446,7 @@ case SNDRV_PCM_IOCTL_STATUS: return snd_pcm_status_user(substream, arg); case SNDRV_PCM_IOCTL_CHANNEL_INFO: - return snd_pcm_channel_info(substream, arg); + return snd_pcm_channel_info_user(substream, arg); case SNDRV_PCM_IOCTL_PREPARE: return snd_pcm_prepare(substream); case SNDRV_PCM_IOCTL_RESET: ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/3] Conversion to compat_ioctl for ALSA drivers 2005-01-30 18:02 ` [PATCH 0/3] " Brian Gerst @ 2005-01-31 13:39 ` Takashi Iwai 0 siblings, 0 replies; 7+ messages in thread From: Takashi Iwai @ 2005-01-31 13:39 UTC (permalink / raw) To: Brian Gerst; +Cc: akpm, linux-kernel, ak, perex At Sun, 30 Jan 2005 13:02:15 -0500, Brian Gerst wrote: > > Takashi Iwai wrote: > > Hi, > > > > the following three patches convert the 32bit ioctl layer of ALSA to > > the new compat_ioctl (and unlocked_ioctl for native ioctls). > > > > The first patch covers the basic entries and control API. > > The second patch is for PCM API. > > The last one is for other APIs including OSS-emulation modules. > > > > After these patches are applied, remove the whole subtree in > > sound/core/ioctl32. The files in this directory are no longer > > necessary. > > Fix 32-bit calls to snd_pcm_channel_info(). > > Signed-off-by: Brian Gerst <bgerst@didntduck.org> Thanks, applied to the ALSA tree. Takashi ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2005-01-31 13:39 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-01-18 16:32 [PATCH 0/3] Conversion to compat_ioctl for ALSA drivers Takashi Iwai 2005-01-18 16:35 ` [PATCH 1/3] " Takashi Iwai 2005-01-18 16:36 ` [PATCH 2/3] " Takashi Iwai 2005-01-18 16:37 ` [PATCH 3/3] " Takashi Iwai 2005-01-18 18:51 ` [PATCH 3/3] Resend: " Takashi Iwai 2005-01-30 18:02 ` [PATCH 0/3] " Brian Gerst 2005-01-31 13:39 ` Takashi Iwai
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox