Commit b8877144 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge http://linux-sound.bkbits.net/linux-sound

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 975d6b21 8d6ff919
......@@ -129,7 +129,7 @@ enum {
* *
*****************************************************************************/
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2)
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3)
typedef unsigned long sndrv_pcm_uframes_t;
typedef long sndrv_pcm_sframes_t;
......@@ -423,6 +423,7 @@ enum {
SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct sndrv_pcm_sw_params),
SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct sndrv_pcm_status),
SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, sndrv_pcm_sframes_t),
SNDRV_PCM_IOCTL_HWSYNC = _IO('A', 0x22),
SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct sndrv_pcm_channel_info),
SNDRV_PCM_IOCTL_PREPARE = _IO('A', 0x40),
SNDRV_PCM_IOCTL_RESET = _IO('A', 0x41),
......
......@@ -225,7 +225,6 @@ int snd_minor_info_oss_init(void);
int snd_minor_info_oss_done(void);
int snd_oss_init_module(void);
void snd_oss_cleanup_module(void);
#endif
......
......@@ -164,7 +164,7 @@ static inline int snd_info_card_unregister(snd_card_t * card) { return 0; }
static inline int snd_info_register(snd_info_entry_t * entry) { return 0; }
static inline int snd_info_unregister(snd_info_entry_t * entry) { return 0; }
static inline struct proc_dir_entry *snd_create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent) { return 0; }
static inline struct proc_dir_entry *snd_create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent) { return NULL; }
static inline void snd_remove_proc_entry(struct proc_dir_entry *parent,
struct proc_dir_entry *de) { ; }
......@@ -174,7 +174,7 @@ static inline void snd_remove_proc_entry(struct proc_dir_entry *parent,
* OSS info part
*/
#ifdef CONFIG_SND_OSSEMUL
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
#define SNDRV_OSS_INFO_DEV_AUDIO 0
#define SNDRV_OSS_INFO_DEV_SYNTH 1
......@@ -187,6 +187,6 @@ static inline void snd_remove_proc_entry(struct proc_dir_entry *parent,
extern int snd_oss_info_register(int dev, int num, char *string);
#define snd_oss_info_unregister(dev, num) snd_oss_info_register(dev, num, NULL)
#endif /* CONFIG_SND_OSSEMUL */
#endif /* CONFIG_SND_OSSEMUL && CONFIG_PROC_FS */
#endif /* __SOUND_INFO_H */
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc3"
#define CONFIG_SND_DATE " (Fri Oct 04 13:09:13 2002 UTC)"
#define CONFIG_SND_DATE " (Mon Oct 14 16:41:26 2002 UTC)"
......@@ -426,52 +426,59 @@ static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *_info)
static int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *_control)
{
snd_ctl_elem_value_t control;
snd_ctl_elem_value_t *control;
snd_kcontrol_t *kctl;
int result, indirect;
if (copy_from_user(&control, _control, sizeof(control)))
control = kmalloc(sizeof(*control), GFP_KERNEL);
if (control == NULL)
return -ENOMEM;
if (copy_from_user(control, _control, sizeof(*control)))
return -EFAULT;
read_lock(&card->control_rwlock);
kctl = snd_ctl_find_id(card, &control.id);
kctl = snd_ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
indirect = kctl->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
if (control.indirect != indirect) {
if (control->indirect != indirect) {
result = -EACCES;
} else {
if ((kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get != NULL) {
result = kctl->get(kctl, &control);
result = kctl->get(kctl, control);
if (result >= 0)
control.id = kctl->id;
control->id = kctl->id;
} else
result = -EPERM;
}
}
read_unlock(&card->control_rwlock);
if (result >= 0)
if (copy_to_user(_control, &control, sizeof(control)))
if (copy_to_user(_control, control, sizeof(*control)))
return -EFAULT;
kfree(control);
return result;
}
static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_control)
{
snd_card_t *card = file->card;
snd_ctl_elem_value_t control;
snd_ctl_elem_value_t *control;
snd_kcontrol_t *kctl;
int result, indirect;
if (copy_from_user(&control, _control, sizeof(control)))
control = kmalloc(sizeof(*control), GFP_KERNEL);
if (control == NULL)
return -ENOMEM;
if (copy_from_user(control, _control, sizeof(*control)))
return -EFAULT;
read_lock(&card->control_rwlock);
kctl = snd_ctl_find_id(card, &control.id);
kctl = snd_ctl_find_id(card, &control->id);
if (kctl == NULL) {
result = -ENOENT;
} else {
indirect = kctl->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0;
if (control.indirect != indirect) {
if (control->indirect != indirect) {
result = -EACCES;
} else {
read_lock(&card->control_owner_lock);
......@@ -480,9 +487,9 @@ static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_contr
(kctl->owner != NULL && kctl->owner != file)) {
result = -EPERM;
} else {
result = kctl->put(kctl, &control);
result = kctl->put(kctl, control);
if (result >= 0)
control.id = kctl->id;
control->id = kctl->id;
}
read_unlock(&card->control_owner_lock);
if (result > 0) {
......@@ -496,8 +503,9 @@ static int snd_ctl_elem_write(snd_ctl_file_t *file, snd_ctl_elem_value_t *_contr
read_unlock(&card->control_rwlock);
__unlocked:
if (result >= 0)
if (copy_to_user(_control, &control, sizeof(control)))
if (copy_to_user(_control, control, sizeof(*control)))
return -EFAULT;
kfree(control);
return result;
}
......
......@@ -28,7 +28,7 @@
#include <sound/version.h>
#include <linux/utsname.h>
#ifdef CONFIG_SND_OSSEMUL
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
/*
* OSS compatible part
......
......@@ -216,7 +216,7 @@ static void snd_card_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
snd_iprintf(buffer, "--- no soundcards ---\n");
}
#ifdef CONFIG_SND_OSSEMUL
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
void snd_card_info_read_oss(snd_info_buffer_t * buffer)
{
......
......@@ -23,6 +23,7 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <sound/core.h>
#include <sound/control.h>
......@@ -264,46 +265,56 @@ static int get_ctl_type(struct file *file, snd_ctl_elem_id_t *id)
static int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
// too big?
struct sndrv_ctl_elem_value data;
struct sndrv_ctl_elem_value32 data32;
struct sndrv_ctl_elem_value *data;
struct sndrv_ctl_elem_value32 *data32;
int err, i;
int type;
mm_segment_t oldseg;
/* FIXME: check the sane ioctl.. */
if (copy_from_user(&data32, (void*)arg, sizeof(data32)))
return -EFAULT;
memset(&data, 0, sizeof(data));
data.id = data32.id;
data.indirect = data32.indirect;
if (data.indirect) /* FIXME: this is not correct for long arrays */
data.value.integer.value_ptr = (void*)TO_PTR(data32.value.integer.value_ptr);
type = get_ctl_type(file, &data.id);
if (type < 0)
return type;
if (! data.indirect) {
data = kmalloc(sizeof(*data), GFP_KERNEL);
data32 = kmalloc(sizeof(*data32), GFP_KERNEL);
if (data == NULL || data32 == NULL) {
err = -ENOMEM;
goto __end;
}
if (copy_from_user(data32, (void*)arg, sizeof(*data32))) {
err = -EFAULT;
goto __end;
}
memset(data, 0, sizeof(*data));
data->id = data32->id;
data->indirect = data32->indirect;
if (data->indirect) /* FIXME: this is not correct for long arrays */
data->value.integer.value_ptr = (void*)TO_PTR(data32->value.integer.value_ptr);
type = get_ctl_type(file, &data->id);
if (type < 0) {
err = type;
goto __end;
}
if (! data->indirect) {
switch (type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
for (i = 0; i < 128; i++)
data.value.integer.value[i] = data32.value.integer.value[i];
data->value.integer.value[i] = data32->value.integer.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
for (i = 0; i < 64; i++)
data.value.integer64.value[i] = data32.value.integer64.value[i];
data->value.integer64.value[i] = data32->value.integer64.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
for (i = 0; i < 128; i++)
data.value.enumerated.item[i] = data32.value.enumerated.item[i];
data->value.enumerated.item[i] = data32->value.enumerated.item[i];
break;
case SNDRV_CTL_ELEM_TYPE_BYTES:
memcpy(data.value.bytes.data, data32.value.bytes.data,
sizeof(data.value.bytes.data));
memcpy(data->value.bytes.data, data32->value.bytes.data,
sizeof(data->value.bytes.data));
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
data.value.iec958 = data32.value.iec958;
data->value.iec958 = data32->value.iec958;
break;
default:
printk("unknown type %d\n", type);
......@@ -313,40 +324,46 @@ static int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsign
oldseg = get_fs();
set_fs(KERNEL_DS);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
set_fs(oldseg);
if (err < 0)
return err;
goto __end;
/* restore info to 32bit */
if (! data.indirect) {
if (! data->indirect) {
switch (type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
case SNDRV_CTL_ELEM_TYPE_INTEGER:
for (i = 0; i < 128; i++)
data32.value.integer.value[i] = data.value.integer.value[i];
data32->value.integer.value[i] = data->value.integer.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
for (i = 0; i < 64; i++)
data32.value.integer64.value[i] = data.value.integer64.value[i];
data32->value.integer64.value[i] = data->value.integer64.value[i];
break;
case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
for (i = 0; i < 128; i++)
data32.value.enumerated.item[i] = data.value.enumerated.item[i];
data32->value.enumerated.item[i] = data->value.enumerated.item[i];
break;
case SNDRV_CTL_ELEM_TYPE_BYTES:
memcpy(data32.value.bytes.data, data.value.bytes.data,
sizeof(data.value.bytes.data));
memcpy(data32->value.bytes.data, data->value.bytes.data,
sizeof(data->value.bytes.data));
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
data32.value.iec958 = data.value.iec958;
data32->value.iec958 = data->value.iec958;
break;
default:
break;
}
}
if (copy_to_user((void*)arg, &data32, sizeof(data32)))
return -EFAULT;
return 0;
err = 0;
if (copy_to_user((void*)arg, data32, sizeof(*data32)))
err = -EFAULT;
__end:
if (data32)
kfree(data32);
if (data)
kfree(data);
return err;
}
DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ);
......
......@@ -79,6 +79,44 @@ static int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long
return 0;\
}
#define DEFINE_ALSA_IOCTL_BIG(type) \
static int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
{\
struct sndrv_##type##32 *data32;\
struct sndrv_##type *data;\
mm_segment_t oldseg;\
int err;\
data32 = kmalloc(sizeof(*data32), GFP_KERNEL); \
data = kmalloc(sizeof(*data), GFP_KERNEL); \
if (data32 == NULL || data == NULL) { \
err = -ENOMEM; \
goto __end; \
}\
if (copy_from_user(data32, (void*)arg, sizeof(*data32))) { \
err = -EFAULT; \
goto __end; \
}\
memset(data, 0, sizeof(*data));\
convert_from_32(type, data, data32);\
oldseg = get_fs();\
set_fs(KERNEL_DS);\
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
if (err < 0) \
goto __end;\
err = 0;\
if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
convert_to_32(type, data32, data);\
if (copy_to_user((void*)arg, data32, sizeof(*data32)))\
err = -EFAULT;\
}\
__end:\
if (data)\
kfree(data);\
if (data32)\
kfree(data32);\
return err;\
}
#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\
return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\
......
......@@ -20,6 +20,7 @@
#include <sound/driver.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "ioctl32.h"
......@@ -172,7 +173,7 @@ struct sndrv_pcm_status32 {
DEFINE_ALSA_IOCTL(pcm_uframes_str);
DEFINE_ALSA_IOCTL(pcm_sframes_str);
DEFINE_ALSA_IOCTL(pcm_hw_params);
DEFINE_ALSA_IOCTL_BIG(pcm_hw_params);
DEFINE_ALSA_IOCTL(pcm_sw_params);
DEFINE_ALSA_IOCTL(pcm_channel_info);
DEFINE_ALSA_IOCTL(pcm_status);
......@@ -230,7 +231,7 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
snd_pcm_file_t *pcm_file;
snd_pcm_substream_t *substream;
struct sndrv_xfern32 data32, *srcptr = (struct sndrv_xfern32*)arg;
void *bufs[128];
void **bufs = NULL;
int err = 0, ch, i;
u32 *bufptr;
mm_segment_t oldseg;
......@@ -260,6 +261,9 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
return -EFAULT;
__get_user(data32.bufs, &srcptr->bufs);
bufptr = (u32*)TO_PTR(data32.bufs);
bufs = kmalloc(sizeof(void *) * 128, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < ch; i++) {
u32 ptr;
if (get_user(ptr, bufptr))
......@@ -278,10 +282,11 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
break;
}
set_fs(oldseg);
if (err < 0)
return err;
if (put_user(err, &srcptr->result))
return -EFAULT;
if (err >= 0) {
if (put_user(err, &srcptr->result))
err = -EFAULT;
}
kfree(bufs);
return 0;
}
......@@ -343,24 +348,38 @@ static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old32 *o
static int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
{
struct sndrv_pcm_hw_params_old32 data32;
struct sndrv_pcm_hw_params data;
struct sndrv_pcm_hw_params_old32 *data32;
struct sndrv_pcm_hw_params *data;
mm_segment_t oldseg;
int err;
if (copy_from_user(&data32, (void*)arg, sizeof(data32)))
return -EFAULT;
snd_pcm_hw_convert_from_old_params(&data, &data32);
data32 = snd_kcalloc(sizeof(*data32), GFP_KERNEL);
data = snd_kcalloc(sizeof(*data), GFP_KERNEL);
if (data32 == NULL || data == NULL) {
err = -ENOMEM;
goto __end;
}
if (copy_from_user(data32, (void*)arg, sizeof(*data32))) {
err = -EFAULT;
goto __end;
}
snd_pcm_hw_convert_from_old_params(data, data32);
oldseg = get_fs();
set_fs(KERNEL_DS);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)&data);
err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
set_fs(oldseg);
if (err < 0)
return err;
snd_pcm_hw_convert_to_old_params(&data32, &data);
if (copy_to_user((void*)arg, &data32, sizeof(data32)))
return -EFAULT;
return 0;
goto __end;
snd_pcm_hw_convert_to_old_params(data32, data);
err = 0;
if (copy_to_user((void*)arg, data32, sizeof(*data32)))
err = -EFAULT;
__end:
if (data)
kfree(data);
if (data32)
kfree(data32);
return err;
}
......
......@@ -499,10 +499,10 @@ char *snd_kmalloc_strdup(const char *string, int flags)
int copy_to_user_fromio(void *dst, unsigned long src, size_t count)
{
#if defined(__i386_) || defined(CONFIG_SPARC32)
#if defined(__i386__) || defined(CONFIG_SPARC32)
return copy_to_user(dst, (const void*)src, count) ? -EFAULT : 0;
#else
char buf[1024];
char buf[256];
while (count) {
size_t c = count;
if (c > sizeof(buf))
......@@ -520,10 +520,10 @@ int copy_to_user_fromio(void *dst, unsigned long src, size_t count)
int copy_from_user_toio(unsigned long dst, const void *src, size_t count)
{
#if defined(__i386_) || defined(CONFIG_SPARC32)
#if defined(__i386__) || defined(CONFIG_SPARC32)
return copy_from_user((void*)dst, src, count) ? -EFAULT : 0;
#else
char buf[1024];
char buf[256];
while (count) {
size_t c = count;
if (c > sizeof(buf))
......
......@@ -495,18 +495,25 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
snd_kcontrol_t *kctl,
int *left, int *right)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
snd_runtime_check(!kctl->get(kctl, &uctl), return);
snd_runtime_check(uinfo.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo.value.integer.min != 0 || uinfo.value.integer.max != 1, return);
*left = snd_mixer_oss_conv1(uctl.value.integer.value[0], uinfo.value.integer.min, uinfo.value.integer.max, &pslot->volume[0]);
if (uinfo.count > 1)
*right = snd_mixer_oss_conv1(uctl.value.integer.value[1], uinfo.value.integer.min, uinfo.value.integer.max, &pslot->volume[1]);
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
*left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
if (uinfo->count > 1)
*right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
......@@ -515,21 +522,28 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
int *left, int *right,
int route)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
snd_runtime_check(!kctl->get(kctl, &uctl), return);
if (!uctl.value.integer.value[0]) {
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
if (!uctl->value.integer.value[0]) {
*left = 0;
if (uinfo.count == 1)
if (uinfo->count == 1)
*right = 0;
}
if (uinfo.count > 1 && !uctl.value.integer.value[route ? 3 : 1])
if (uinfo->count > 1 && !uctl->value.integer.value[route ? 3 : 1])
*right = 0;
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer,
......@@ -566,21 +580,28 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
snd_kcontrol_t *kctl,
int left, int right)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int res;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
snd_runtime_check(uinfo.type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo.value.integer.min != 0 || uinfo.value.integer.max != 1, return);
uctl.value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo.value.integer.min, uinfo.value.integer.max);
if (uinfo.count > 1)
uctl.value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo.value.integer.min, uinfo.value.integer.max);
snd_runtime_check((res = kctl->put(kctl, &uctl)) >= 0, return);
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
if (uinfo->count > 1)
uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc);
if (res > 0)
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
......@@ -589,27 +610,34 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
int left, int right,
int route)
{
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int res;
snd_runtime_check(kctl != NULL, return);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!kctl->info(kctl, &uinfo), return);
if (uinfo.count > 1) {
uctl.value.integer.value[0] = left > 0 ? 1 : 0;
uctl.value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0;
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
if (uinfo->count > 1) {
uctl->value.integer.value[0] = left > 0 ? 1 : 0;
uctl->value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0;
if (route) {
uctl.value.integer.value[1] =
uctl.value.integer.value[2] = 0;
uctl->value.integer.value[1] =
uctl->value.integer.value[2] = 0;
}
} else {
uctl.value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0;
uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0;
}
snd_runtime_check((res = kctl->put(kctl, &uctl)) >= 0, return);
snd_runtime_check((res = kctl->put(kctl, uctl)) >= 0, goto __unalloc);
if (res > 0)
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
}
static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer,
......@@ -718,17 +746,21 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, int *active_i
snd_kcontrol_t *kctl;
snd_mixer_oss_slot_t *pslot;
struct slot *slot;
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int err, idx;
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
}
read_lock(&card->control_rwlock);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, return -ENOENT);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!(err = kctl->info(kctl, &uinfo)), read_unlock(&card->control_rwlock); return err);
snd_runtime_check(!(err = kctl->get(kctl, &uctl)), read_unlock(&card->control_rwlock); return err);
snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock);
snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock);
snd_runtime_check(!(err = kctl->get(kctl, uctl)), goto __unlock);
read_unlock(&card->control_rwlock);
for (idx = 0; idx < 32; idx++) {
if (!(mixer->mask_recsrc & (1 << idx)))
......@@ -739,12 +771,21 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, int *active_i
continue;
if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
continue;
if (slot->capture_item == uctl.value.enumerated.item[0]) {
if (slot->capture_item == uctl->value.enumerated.item[0]) {
*active_index = idx;
break;
}
}
return 0;
err = 0;
goto __unalloc;
__unlock:
read_unlock(&card->control_rwlock);
__unalloc:
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
return err;
}
static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_index)
......@@ -754,16 +795,20 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_in
snd_kcontrol_t *kctl;
snd_mixer_oss_slot_t *pslot;
struct slot *slot = NULL;
snd_ctl_elem_info_t uinfo;
snd_ctl_elem_value_t uctl;
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
int err, idx;
uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL) {
err = -ENOMEM;
goto __unlock;
}
read_lock(&card->control_rwlock);
kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
snd_runtime_check(kctl != NULL, read_unlock(&card->control_rwlock); return -ENOENT);
memset(&uinfo, 0, sizeof(uinfo));
memset(&uctl, 0, sizeof(uctl));
snd_runtime_check(!(err = kctl->info(kctl, &uinfo)), read_unlock(&card->control_rwlock); return err);
snd_runtime_check(kctl != NULL, err = -ENOENT; goto __unlock);
snd_runtime_check(!(err = kctl->info(kctl, uinfo)), goto __unlock);
for (idx = 0; idx < 32; idx++) {
if (!(mixer->mask_recsrc & (1 << idx)))
continue;
......@@ -778,14 +823,19 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, int active_in
slot = NULL;
}
snd_runtime_check(slot != NULL, goto __unlock);
for (idx = 0; idx < uinfo.count; idx++)
uctl.value.enumerated.item[idx] = slot->capture_item;
snd_runtime_check((err = kctl->put(kctl, &uctl)) >= 0, );
for (idx = 0; idx < uinfo->count; idx++)
uctl->value.enumerated.item[idx] = slot->capture_item;
snd_runtime_check((err = kctl->put(kctl, uctl)) >= 0, );
if (err > 0)
snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
err = 0;
__unlock:
read_unlock(&card->control_rwlock);
return 0;
if (uctl)
kfree(uctl);
if (uinfo)
kfree(uinfo);
return err;
}
struct snd_mixer_oss_assign_table {
......@@ -1176,9 +1226,11 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int free_flag)
mixer->name[sizeof(mixer->name)-1] = 0;
} else
strcpy(mixer->name, name);
#ifdef SNDRV_OSS_INFO_DEV_MIXERS
snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS,
card->number,
mixer->name);
#endif
for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++)
mixer->slots[idx].number = idx;
card->mixer_oss = mixer;
......@@ -1188,7 +1240,9 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int free_flag)
snd_mixer_oss_t *mixer = card->mixer_oss;
if (mixer == NULL)
return 0;
#ifdef SNDRV_OSS_INFO_DEV_MIXERS
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number);
#endif
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0);
snd_mixer_oss_proc_done(mixer);
return snd_mixer_oss_free1(mixer);
......
......@@ -2123,9 +2123,11 @@ static int snd_pcm_oss_register_minor(unsigned short native_minor,
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count &&
!(pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX));
sprintf(name, "%s%s", pcm->name, duplex ? " (DUPLEX)" : "");
#ifdef SNDRV_OSS_INFO_DEV_AUDIO
snd_oss_info_register(SNDRV_OSS_INFO_DEV_AUDIO,
pcm->card->number,
name);
#endif
pcm->oss.reg++;
}
if (snd_adsp_map[pcm->card->number] == pcm->device) {
......@@ -2146,7 +2148,9 @@ static int snd_pcm_oss_unregister_minor(unsigned short native_minor,
if (snd_dsp_map[pcm->card->number] == pcm->device) {
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
pcm->card, 0);
#ifdef SNDRV_OSS_INFO_DEV_AUDIO
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number);
#endif
}
if (snd_adsp_map[pcm->card->number] == pcm->device)
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
......
......@@ -1473,7 +1473,7 @@ static int boundary_nearer(int min, int mindir,
int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var, unsigned int best, int *dir)
{
snd_pcm_hw_params_t save;
snd_pcm_hw_params_t *save = NULL;
int v;
unsigned int saved_min;
int last = 0;
......@@ -1493,30 +1493,42 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
maxdir = 1;
max--;
}
save = *params;
save = kmalloc(sizeof(*save), GFP_KERNEL);
if (save == NULL)
return -ENOMEM;
*save = *params;
saved_min = min;
min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
if (min >= 0) {
snd_pcm_hw_params_t params1;
snd_pcm_hw_params_t *params1;
if (max < 0)
goto _end;
if ((unsigned int)min == saved_min && mindir == valdir)
goto _end;
params1 = save;
max = snd_pcm_hw_param_max(pcm, &params1, var, max, &maxdir);
if (max < 0)
params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
if (params1 == NULL) {
kfree(save);
return -ENOMEM;
}
*params1 = *save;
max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
if (max < 0) {
kfree(params1);
goto _end;
}
if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
*params = params1;
*params = *params1;
last = 1;
}
kfree(params1);
} else {
*params = save;
*params = *save;
max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
assert(max >= 0);
last = 1;
}
_end:
kfree(save);
if (last)
v = snd_pcm_hw_param_last(pcm, params, var, dir);
else
......@@ -1842,16 +1854,11 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED ||
runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
if (avail < runtime->xfer_align) {
err = -EPIPE;
goto _end_unlock;
}
} else if (((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align))) {
if (((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align))) {
wait_queue_t wait;
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
if (nonblock) {
err = -EAGAIN;
goto _end_unlock;
......@@ -1868,8 +1875,11 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
spin_unlock_irq(&runtime->lock);
if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock);
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
}
}
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
......@@ -1916,10 +1926,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
if (frames > cont)
frames = cont;
if (frames == 0 && runtime->status->state == SNDRV_PCM_STATE_PAUSED) {
err = -EPIPE;
goto _end_unlock;
}
snd_assert(frames != 0,
spin_unlock_irq(&runtime->lock);
return -EINVAL);
......@@ -2135,21 +2141,16 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (avail < runtime->xfer_align) {
err = -EPIPE;
goto _end_unlock;
}
} else if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (avail < runtime->xfer_align) {
runtime->status->state = SNDRV_PCM_STATE_SETUP;
err = -EPIPE;
goto _end_unlock;
}
} else if ((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align)) {
wait_queue_t wait;
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
if (nonblock) {
err = -EAGAIN;
goto _end_unlock;
......@@ -2166,8 +2167,11 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
spin_unlock_irq(&runtime->lock);
if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock);
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
}
}
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
......
......@@ -1848,7 +1848,10 @@ int snd_pcm_release(struct inode *inode, struct file *file)
snd_assert(substream != NULL, return -ENXIO);
snd_assert(!atomic_read(&substream->runtime->mmap_count), );
pcm = substream->pcm;
snd_pcm_capture_drop(substream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_pcm_playback_drop(substream);
else
snd_pcm_capture_drop(substream);
fasync_helper(-1, file, 0, &substream->runtime->fasync);
down(&pcm->open_mutex);
snd_pcm_release_file(pcm_file);
......@@ -1959,34 +1962,29 @@ snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm
return ret;
}
static int snd_pcm_playback_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
static int snd_pcm_hwsync(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int err = 0;
snd_pcm_sframes_t n;
int err;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
if (snd_pcm_update_hw_ptr(substream) >= 0) {
n = snd_pcm_playback_hw_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
case SNDRV_PCM_STATE_RUNNING:
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
} else {
err = SNDRV_PCM_STATE_RUNNING ? -EPIPE : -EBADFD;
}
break;
/* Fall through */
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_SUSPENDED:
if (runtime->status->suspended_state == SNDRV_PCM_STATE_RUNNING) {
n = snd_pcm_playback_hw_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
} else {
err = -EBADFD;
}
err = 0;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
default:
__badfd:
err = -EBADFD;
break;
}
......@@ -1994,41 +1992,43 @@ static int snd_pcm_playback_delay(snd_pcm_substream_t *substream, snd_pcm_sframe
return err;
}
static int snd_pcm_capture_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int err = 0;
int err;
snd_pcm_sframes_t n;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_DRAINING:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
case SNDRV_PCM_STATE_RUNNING:
if (snd_pcm_update_hw_ptr(substream) >= 0) {
n = snd_pcm_capture_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
}
/* Fall through */
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_SUSPENDED:
if (runtime->status->suspended_state == SNDRV_PCM_STATE_RUNNING) {
err = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
} else {
err = -EBADFD;
}
if (put_user(n, res))
err = -EFAULT;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
default:
__badfd:
err = -EBADFD;
break;
}
spin_unlock_irq(&runtime->lock);
return err;
}
static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
unsigned int cmd, void *arg);
static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
......@@ -2076,6 +2076,10 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_resume(substream);
case SNDRV_PCM_IOCTL_XRUN:
return snd_pcm_xrun(substream);
case SNDRV_PCM_IOCTL_HWSYNC:
return snd_pcm_hwsync(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_delay(substream, (snd_pcm_sframes_t *) arg);
case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
return snd_pcm_hw_refine_old_user(substream, (struct sndrv_pcm_hw_params_old *) arg);
case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
......@@ -2110,7 +2114,7 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
{
snd_xfern_t xfern, *_xfern = arg;
snd_pcm_runtime_t *runtime = substream->runtime;
void *bufs[128];
void *bufs;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
......@@ -2120,9 +2124,15 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
if (copy_from_user(bufs, xfern.bufs, sizeof(*bufs) * runtime->channels))
bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
kfree(bufs);
return -EFAULT;
}
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
return result < 0 ? result : 0;
}
......@@ -2150,8 +2160,6 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_playback_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_playback_drop(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_playback_delay(substream, (snd_pcm_sframes_t*) arg);
}
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
......@@ -2181,7 +2189,7 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
{
snd_xfern_t xfern, *_xfern = arg;
snd_pcm_runtime_t *runtime = substream->runtime;
void *bufs[128];
void *bufs;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
......@@ -2191,9 +2199,15 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
if (copy_from_user(bufs, xfern.bufs, sizeof(*bufs) * runtime->channels))
bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
kfree(bufs);
return -EFAULT;
}
result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
return result < 0 ? result : 0;
}
......@@ -2213,8 +2227,6 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_capture_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_capture_drop(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_capture_delay(substream, (snd_pcm_sframes_t*) arg);
}
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
......@@ -2311,7 +2323,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
snd_pcm_runtime_t *runtime;
snd_pcm_sframes_t result;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
up(&file->f_dentry->d_inode->i_sem);
#endif
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end);
......@@ -2329,7 +2343,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
if (result > 0)
result = frames_to_bytes(runtime, result);
end:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
down(&file->f_dentry->d_inode->i_sem);
#endif
return result;
}
......@@ -2343,7 +2359,7 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
snd_pcm_runtime_t *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void *bufs[128];
void **bufs;
snd_pcm_uframes_t frames;
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
......@@ -2352,16 +2368,20 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (count > 128 || count != runtime->channels)
if (count > 1024 || count != runtime->channels)
return -EINVAL;
if (!frame_aligned(runtime, _vector->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, _vector->iov_len);
bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < count; ++i)
bufs[i] = _vector[i].iov_base;
result = snd_pcm_lib_readv(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
kfree(bufs);
return result;
}
......@@ -2373,10 +2393,12 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
snd_pcm_runtime_t *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void *bufs[128];
void **bufs;
snd_pcm_uframes_t frames;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
up(&file->f_dentry->d_inode->i_sem);
#endif
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end);
......@@ -2391,13 +2413,19 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
goto end;
}
frames = bytes_to_samples(runtime, _vector->iov_len);
bufs = kmalloc(sizeof(void *) * count, GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < count; ++i)
bufs[i] = _vector[i].iov_base;
result = snd_pcm_lib_writev(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
kfree(bufs);
end:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
down(&file->f_dentry->d_inode->i_sem);
#endif
return result;
}
#endif
......@@ -2422,6 +2450,8 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
avail = snd_pcm_playback_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = POLLOUT | POLLWRNORM;
break;
......@@ -2430,12 +2460,6 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
case SNDRV_PCM_STATE_DRAINING:
mask = 0;
break;
case SNDRV_PCM_STATE_PREPARED:
if (avail > 0) {
mask = POLLOUT | POLLWRNORM;
break;
}
/* Fall through */
default:
mask = POLLOUT | POLLWRNORM | POLLERR;
break;
......@@ -2464,6 +2488,8 @@ unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
avail = snd_pcm_capture_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = POLLIN | POLLRDNORM;
break;
......
......@@ -1425,7 +1425,9 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
} else {
rmidi->ossreg++;
#ifdef SNDRV_OSS_INFO_DEV_MIDI
snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number, rmidi->name);
#endif
}
}
if (rmidi->device == snd_amidi_map[rmidi->card->number]) {
......@@ -1436,7 +1438,7 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
rmidi->ossreg++;
}
}
#endif
#endif /* CONFIG_SND_OSSEMUL */
up(&register_mutex);
sprintf(name, "midi%d", rmidi->device);
entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);
......@@ -1484,13 +1486,15 @@ static int snd_rawmidi_dev_unregister(snd_device_t *device)
if (rmidi->ossreg) {
if (rmidi->device == snd_midi_map[rmidi->card->number]) {
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 0);
#ifdef SNDRV_OSS_INFO_DEV_MIDI
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number);
#endif
}
if (rmidi->device == snd_amidi_map[rmidi->card->number])
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 1);
rmidi->ossreg = 0;
}
#endif
#endif /* CONFIG_SND_OSSEMUL */
if (rmidi->ops && rmidi->ops->dev_unregister)
rmidi->ops->dev_unregister(rmidi);
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
......
......@@ -159,9 +159,10 @@ snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags)
spin_lock_irqsave(&q->lock, *rflags);
if (q->qlen == 0) {
if (blocking) {
snd_seq_sleep_timeout_in_lock(&q->midi_sleep,
&q->lock,
q->pre_event_timeout);
spin_unlock(&q->lock);
interruptible_sleep_on_timeout(&q->midi_sleep,
q->pre_event_timeout);
spin_lock(&q->lock);
}
if (q->qlen == 0) {
spin_unlock_irqrestore(&q->lock, *rflags);
......
......@@ -146,8 +146,10 @@ snd_seq_oss_synth_register(snd_seq_device_t *dev)
debug_printk(("synth %s registered %d\n", rec->name, i));
spin_unlock_irqrestore(&register_lock, flags);
dev->driver_data = rec;
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (i < SNDRV_CARDS)
snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
#endif
return 0;
}
......@@ -178,8 +180,10 @@ snd_seq_oss_synth_unregister(snd_seq_device_t *dev)
max_synth_devs = index + 1;
}
spin_unlock_irqrestore(&register_lock, flags);
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
if (rec->seq_device < SNDRV_CARDS)
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_SYNTH, rec->seq_device);
#endif
snd_use_lock_sync(&rec->use_lock);
kfree(rec);
......
......@@ -122,7 +122,9 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
}
/* wait for echo event */
snd_seq_sleep_timeout_in_lock(&q->sync_sleep, &q->sync_lock, HZ);
spin_unlock(&q->sync_lock);
interruptible_sleep_on_timeout(&q->sync_sleep, HZ);
spin_lock(&q->sync_lock);
if (signal_pending(current)) {
/* interrupted - return 0 to finish sync */
q->sync_event_put = 0;
......
......@@ -135,7 +135,7 @@ EXPORT_SYMBOL(snd_seq_event_port_attach);
EXPORT_SYMBOL(snd_seq_event_port_detach);
/* seq_lock.c */
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
EXPORT_SYMBOL(snd_seq_sleep_in_lock);
EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);
/*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/
/*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/
EXPORT_SYMBOL(snd_use_lock_sync_helper);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment