X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=sound%2Fcore%2Fcontrol.c;h=01a1a5af47bb7749e90370c7ff92dbae528b6199;hb=ab69b3cf1219e0d07bb4ea373f36b1de38af531c;hp=1f1ab9c1b668c5704badb84379f809439b085c09;hpb=38cb162b7585d837083b8365da1eb32687c5164c;p=linux-2.6-omap-h63xx.git diff --git a/sound/core/control.c b/sound/core/control.c index 1f1ab9c1b66..01a1a5af47b 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1,6 +1,6 @@ /* * Routines for driver control interface - * Copyright (c) by Jaroslav Kysela + * Copyright (c) by Jaroslav Kysela * * * This program is free software; you can redistribute it and/or modify @@ -19,7 +19,6 @@ * */ -#include #include #include #include @@ -93,15 +92,16 @@ static int snd_ctl_open(struct inode *inode, struct file *file) static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl) { + unsigned long flags; struct snd_kctl_event *cread; - spin_lock(&ctl->read_lock); + spin_lock_irqsave(&ctl->read_lock, flags); while (!list_empty(&ctl->events)) { cread = snd_kctl_event(ctl->events.next); list_del(&cread->list); kfree(cread); } - spin_unlock(&ctl->read_lock); + spin_unlock_irqrestore(&ctl->read_lock, flags); } static int snd_ctl_release(struct inode *inode, struct file *file) @@ -231,8 +231,6 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| SNDRV_CTL_ELEM_ACCESS_INACTIVE| - SNDRV_CTL_ELEM_ACCESS_DINDIRECT| - SNDRV_CTL_ELEM_ACCESS_INDIRECT| SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); kctl.info = ncontrol->info; @@ -691,7 +689,7 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control) struct snd_kcontrol *kctl; struct snd_kcontrol_volatile *vd; unsigned int index_offset; - int result, indirect; + int result; down_read(&card->controls_rwsem); kctl = snd_ctl_find_id(card, &control->id); @@ -700,24 +698,17 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control) } else { index_offset = snd_ctl_get_ioff(kctl, &control->id); vd = &kctl->vd[index_offset]; - indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0; - if (control->indirect != indirect) { - result = -EACCES; - } else { - if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && kctl->get != NULL) { - snd_ctl_build_ioff(&control->id, kctl, index_offset); - result = kctl->get(kctl, control); - } else { - result = -EPERM; - } - } + if ((vd->access & SNDRV_CTL_ELEM_ACCESS_READ) && + kctl->get != NULL) { + snd_ctl_build_ioff(&control->id, kctl, index_offset); + result = kctl->get(kctl, control); + } else + result = -EPERM; } up_read(&card->controls_rwsem); return result; } -EXPORT_SYMBOL(snd_ctl_elem_read); - static int snd_ctl_elem_read_user(struct snd_card *card, struct snd_ctl_elem_value __user *_control) { @@ -749,7 +740,7 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, struct snd_kcontrol *kctl; struct snd_kcontrol_volatile *vd; unsigned int index_offset; - int result, indirect; + int result; down_read(&card->controls_rwsem); kctl = snd_ctl_find_id(card, &control->id); @@ -758,31 +749,25 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, } else { index_offset = snd_ctl_get_ioff(kctl, &control->id); vd = &kctl->vd[index_offset]; - indirect = vd->access & SNDRV_CTL_ELEM_ACCESS_INDIRECT ? 1 : 0; - if (control->indirect != indirect) { - result = -EACCES; + if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || + kctl->put == NULL || + (file && vd->owner && vd->owner != file)) { + result = -EPERM; } else { - if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) || - kctl->put == NULL || - (file && vd->owner != NULL && vd->owner != file)) { - result = -EPERM; - } else { - snd_ctl_build_ioff(&control->id, kctl, index_offset); - result = kctl->put(kctl, control); - } - if (result > 0) { - up_read(&card->controls_rwsem); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &control->id); - return 0; - } + snd_ctl_build_ioff(&control->id, kctl, index_offset); + result = kctl->put(kctl, control); + } + if (result > 0) { + up_read(&card->controls_rwsem); + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, + &control->id); + return 0; } } up_read(&card->controls_rwsem); return result; } -EXPORT_SYMBOL(snd_ctl_elem_write); - static int snd_ctl_elem_write_user(struct snd_ctl_file *file, struct snd_ctl_elem_value __user *_control) { @@ -1486,3 +1471,30 @@ int snd_ctl_create(struct snd_card *card) snd_assert(card != NULL, return -ENXIO); return snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); } + +/* + * Frequently used control callbacks + */ +int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +EXPORT_SYMBOL(snd_ctl_boolean_mono_info); + +int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);