Update of /cvsroot/alsa/alsa-kernel/core/oss
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv738/core/oss
Modified Files:
mixer_oss.c
Log Message:
- fixed the oops in OSS mixer when the control elements are dynamically
changed (e.g. emufx).
mixer_oss.c handles the numid instead of kcontrol_t pointers.
- snd_ctl_find_id and snd_ctl_find_numid don't issue contros_rwsem.
the caller has to handle it properly.
Index: mixer_oss.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/oss/mixer_oss.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- mixer_oss.c 9 Dec 2003 11:25:01 -0000 1.27
+++ mixer_oss.c 26 Jan 2004 11:48:40 -0000 1.28
@@ -469,12 +469,14 @@
unsigned int signature;
unsigned int present;
unsigned int channels;
- snd_kcontrol_t *kcontrol[SNDRV_MIXER_OSS_ITEM_COUNT];
+ unsigned int numid[SNDRV_MIXER_OSS_ITEM_COUNT];
unsigned int capture_item;
struct snd_mixer_oss_assign_table *assigned;
unsigned int allocated: 1;
};
+#define ID_UNKNOWN ((unsigned int)-1)
+
static snd_kcontrol_t *snd_mixer_oss_test_id(snd_mixer_oss_t *mixer, const char
*name, int index)
{
snd_card_t * card = mixer->card;
@@ -489,15 +491,23 @@
static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
snd_mixer_oss_slot_t *pslot,
- snd_kcontrol_t *kctl,
+ unsigned int numid,
int *left, int *right)
{
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
+ snd_kcontrol_t *kctl;
+ snd_card_t *card = fmixer->card;
- snd_runtime_check(kctl != NULL, return);
- uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
- uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
+ if (numid == ID_UNKNOWN)
+ return;
+ down_read(&card->controls_rwsem);
+ if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
+ up_read(&card->controls_rwsem);
+ return;
+ }
+ uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -507,6 +517,7 @@
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:
+ up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
@@ -515,16 +526,24 @@
static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
snd_mixer_oss_slot_t *pslot,
- snd_kcontrol_t *kctl,
+ unsigned int numid,
int *left, int *right,
int route)
{
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
+ snd_kcontrol_t *kctl;
+ snd_card_t *card = fmixer->card;
- snd_runtime_check(kctl != NULL, return);
- uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
- uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
+ if (numid == ID_UNKNOWN)
+ return;
+ down_read(&card->controls_rwsem);
+ if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
+ up_read(&card->controls_rwsem);
+ return;
+ }
+ uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -537,6 +556,7 @@
if (uinfo->count > 1 && !uctl->value.integer.value[route ? 3 : 1])
*right = 0;
__unalloc:
+ up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
@@ -547,43 +567,46 @@
snd_mixer_oss_slot_t *pslot,
int *left, int *right)
{
- snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
*left = *right = 100;
- down_read(&card->controls_rwsem);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
- snd_mixer_oss_get_volume1_vol(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
+ snd_mixer_oss_get_volume1_vol(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) {
- snd_mixer_oss_get_volume1_vol(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right);
+ snd_mixer_oss_get_volume1_vol(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) {
- snd_mixer_oss_get_volume1_vol(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right);
+ snd_mixer_oss_get_volume1_vol(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right);
}
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
+ snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
+ snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
+ snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) {
- snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
+ snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
}
- up_read(&card->controls_rwsem);
return 0;
}
static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
snd_mixer_oss_slot_t *pslot,
- snd_kcontrol_t *kctl,
+ unsigned int numid,
int left, int right)
{
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
+ snd_kcontrol_t *kctl;
+ snd_card_t *card = fmixer->card;
int res;
- snd_runtime_check(kctl != NULL, return);
- uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
- uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
+ if (numid == ID_UNKNOWN)
+ return;
+ down_read(&card->controls_rwsem);
+ if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
+ return;
+ uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -593,8 +616,9 @@
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);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
__unalloc:
+ up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
@@ -603,17 +627,25 @@
static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
snd_mixer_oss_slot_t *pslot,
- snd_kcontrol_t *kctl,
+ unsigned int numid,
int left, int right,
int route)
{
snd_ctl_elem_info_t *uinfo;
snd_ctl_elem_value_t *uctl;
+ snd_kcontrol_t *kctl;
+ snd_card_t *card = fmixer->card;
int res;
- snd_runtime_check(kctl != NULL, return);
- uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC);
- uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC);
+ if (numid == ID_UNKNOWN)
+ return;
+ down_read(&card->controls_rwsem);
+ if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
+ up_read(&fmixer->card->controls_rwsem);
+ return;
+ }
+ uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
+ uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
if (uinfo == NULL || uctl == NULL)
goto __unalloc;
snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -629,8 +661,9 @@
}
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);
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
__unalloc:
+ up_read(&card->controls_rwsem);
if (uctl)
kfree(uctl);
if (uinfo)
@@ -641,40 +674,37 @@
snd_mixer_oss_slot_t *pslot,
int left, int right)
{
- snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
- down_read(&card->controls_rwsem);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
- snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
+ snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME)
- snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right);
+ snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) {
- snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right);
+ snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) {
- snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right);
+ snd_mixer_oss_put_volume1_vol(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right);
}
if (left || right) {
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE)
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
} else {
if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1);
} else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) {
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1);
}
}
- up_read(&card->controls_rwsem);
return 0;
}
@@ -682,14 +712,11 @@
snd_mixer_oss_slot_t *pslot,
int *active)
{
- snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
int left, right;
left = right = 1;
- down_read(&card->controls_rwsem);
- snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0);
- up_read(&card->controls_rwsem);
+ snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0);
*active = (left || right) ? 1 : 0;
return 0;
}
@@ -698,14 +725,11 @@
snd_mixer_oss_slot_t *pslot,
int *active)
{
- snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
int left, right;
left = right = 1;
- down_read(&card->controls_rwsem);
- snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1);
- up_read(&card->controls_rwsem);
+ snd_mixer_oss_get_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1);
*active = (left || right) ? 1 : 0;
return 0;
}
@@ -714,12 +738,9 @@
snd_mixer_oss_slot_t *pslot,
int active)
{
- snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
- down_read(&card->controls_rwsem);
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
- up_read(&card->controls_rwsem);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
return 0;
}
@@ -727,12 +748,9 @@
snd_mixer_oss_slot_t *pslot,
int active)
{
- snd_card_t *card = fmixer->card;
struct slot *slot = (struct slot *)pslot->private_data;
- down_read(&card->controls_rwsem);
- snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
- up_read(&card->controls_rwsem);
+ snd_mixer_oss_put_volume1_sw(fmixer, pslot,
slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
return 0;
}
@@ -843,13 +861,21 @@
{
snd_ctl_elem_info_t info;
snd_kcontrol_t *kcontrol;
+ snd_card_t *card = mixer->card;
int err;
+ down_read(&card->controls_rwsem);
kcontrol = snd_mixer_oss_test_id(mixer, name, index);
- if (kcontrol == NULL)
+ if (kcontrol == NULL) {
+ up_read(&card->controls_rwsem);
return 0;
- snd_runtime_check((err = kcontrol->info(kcontrol, &info)) >= 0, return err);
- slot->kcontrol[item] = kcontrol;
+ }
+ if ((err = kcontrol->info(kcontrol, &info)) < 0) {
+ up_read(&card->controls_rwsem);
+ return err;
+ }
+ slot->numid[item] = kcontrol->id.numid;
+ up_read(&card->controls_rwsem);
if (info.count > slot->channels)
slot->channels = info.count;
slot->present |= 1 << item;
@@ -895,6 +921,7 @@
return 0;
memset(&slot, 0, sizeof(slot));
+ memset(slot.numid, 0xff, sizeof(slot.numid)); /* ID_UNKNOWN */
if (snd_mixer_oss_build_test(mixer, &slot, ptr->name, ptr->index,
SNDRV_MIXER_OSS_ITEM_GLOBAL))
return 0;
@@ -934,6 +961,7 @@
if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index,
SNDRV_MIXER_OSS_ITEM_CVOLUME))
return 0;
+ down_read(&mixer->card->controls_rwsem);
if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source",
0)) != NULL) {
snd_ctl_elem_info_t uinfo;
@@ -951,8 +979,10 @@
} else {
for (slot.capture_item = 1; slot.capture_item <
uinfo.value.enumerated.items; slot.capture_item++) {
uinfo.value.enumerated.item = slot.capture_item;
- if (kctl->info(kctl, &uinfo))
+ if (kctl->info(kctl, &uinfo)) {
+ up_read(&mixer->card->controls_rwsem);
return 0;
+ }
if (!strcmp(uinfo.value.enumerated.name, str)) {
slot.present |=
SNDRV_MIXER_OSS_PRESENT_CAPTURE;
break;
@@ -960,6 +990,7 @@
}
}
}
+ up_read(&mixer->card->controls_rwsem);
if (slot.present != 0) {
pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL);
snd_runtime_check(pslot != NULL, return -ENOMEM);
-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog