* [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;
as well as URLs for NNTP newsgroup(s).