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

Reply via email to