Linux-kernel mailing list archive 1997-49,: Persistent mixer volumes with sound modules in Linux.

# Persistent mixer volumes with sound modules in Linux.

David Woodhouse (dwmw2@cam.ac.uk)
Sun, 07 Dec 1997 21:04:51 +0000

- Messages sorted by: [ date ][ thread ][ subject ][ author ]
- Next message: Krzysztof G. Baranowski: "rmmod ipv6 - opps (it's still there)"
- Previous message: Ildar Khabibrakhmanov: "Re: 2.1.70: stange NFS modes"

This is a multipart MIME message.

--==_Exmh_8481573880
Content-Type: text/plain; charset=us-ascii

Using the patch that comes with kerneld for persistent module storage, I've
put together a patch which makes the sound driver store mixer levels across
load/unloading of the module. This means that it won't reset all the levels
every time you access it.

At the moment, all devices should have mixer levels loaded this way, but only
Sound Blasters will store them upon module unloading. If the patch is approved
of, then I'll go through and perform the same for all other devices.

This includes a version of the kerneld-persist-patch that comes with
modutils-2.1.55, modified to accommodate the 2.1.71 kernel by increasing the
message numbers by one to avoid KERNELD_PNP.

(You need to recompile kerneld to use this, and note that you may have to
compile it without optimisation.)

--==_Exmh_8481573880
Content-Type: text/plain ; name="sound-persistlevels-71"; charset=us-ascii
Content-Description: sound-persistlevels-71
Content-Disposition: attachment; filename="sound-persistlevels-71"

--- linux/include/linux/kerneld.h.prepersist Sat Nov 29 18:33:21 1997
+++ linux/include/linux/kerneld.h Sun Dec 7 19:05:49 1997
@@ -9,6 +9,8 @@
#define KERNELD_REQUEST_ROUTE 6 /* from net/ipv4/route.c */
#define KERNELD_BLANKER 7 /* from drivers/char/console.c */
#define KERNELD_PNP 8 /* from drivers/pnp/kerneld.c */
+#define KERNELD_GET_PERSIST 9 /* persistent module storage */
+#define KERNELD_SET_PERSIST 10 /* persistent module storage */
#define KERNELD_ARP 256 /* from net/ipv4/arp.c */
/*
@@ -47,7 +49,16 @@
#endif /* __KERNEL__ */
};
+struct __persist {
+ int keylen;
+ int arglen;
+ char arr[0];
+};
+
#ifdef __KERNEL__
+#include <sys/types.h>
+#include <linux/malloc.h>
+
extern int kerneld_send(int msgtype, int ret_size, int msgsz,
const char *text, const char *ret_val);
@@ -128,5 +139,47 @@
strlen(on_off?"on":"off"), on_off?"on":"off", NULL);
}
+/*
+ * Persistent storage for modules
+ *
+ * Usage:
+ * int get_persist("a key", &value, sizeof(value));
+ * Returns > 0 on success (return value == returned size)
+ *
+ * int set_persist("a key", &value, sizeof(value));
+ * Returns < 0 on failure
+ *
+ * To remove an entry, use: "set_persist("a key", NULL, 0);"
+ */
+
+static inline int set_persist(char *key, void *value, size_t length)
+{
+ struct __persist *p;
+ int keylen = strlen(key) + 1;
+ int structsize = keylen + length + sizeof(struct __persist);
+ int status;
+
+ if ((p = (struct __persist *)kmalloc(structsize, GFP_ATOMIC)) == NULL)
+ return -ENOMEM;
+ strcpy(p->arr, key);
+ p->keylen = keylen;
+ p->arglen = length;
+ if (length)
+ memcpy(p->arr + keylen, value, length);
+
+ status = kerneld_send(KERNELD_SET_PERSIST,
+ 0 | KERNELD_NOWAIT,
+ structsize, (char *)p, NULL);
+
+ kfree(p);
+ return status;
+}
+
+static inline int get_persist(char *key, void *value, size_t length)
+{
+ return kerneld_send(KERNELD_GET_PERSIST,
+ length | KERNELD_WAIT,
+ strlen(key), key, value);
+}
#endif /* __KERNEL__ */
#endif
--- linux/drivers/sound/sb_mixer.c.prepersist Sun Dec 7 19:08:20 1997
+++ linux/drivers/sound/sb_mixer.c Sun Dec 7 19:35:45 1997
@@ -12,7 +12,8 @@
* for more info.
*/
#include <linux/config.h>
-
+#include <linux/string.h>
+#include <linux/kerneld.h>
#include "sound_config.h"
--- linux/drivers/sound/sb_common.c.prepersist Sun Dec 7 19:53:48 1997
+++ linux/drivers/sound/sb_common.c Sun Dec 7 20:47:29 1997
@@ -11,7 +11,10 @@
* for more info.
*/
#include <linux/config.h>
-
+#ifdef CONFIG_KERNELD
+#include <linux/string.h>
+#include <linux/kerneld.h>
+#endif
#include "sound_config.h"
#include "sound_firmware.h"
@@ -967,6 +970,12 @@
if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) &&
devc->irq > 0)
{
+#ifdef CONFIG_KERNELD
+ char buf[32];
+ sprintf(buf,"mixer_SB_%d",devc->sbmixnum);
+ set_persist(buf,devc->levels,sizeof(int) * 32);
+ printk("set levels for %s\n",buf);
+#endif
snd_release_irq(devc->irq);
irq2devc[devc->irq] = NULL;
sound_unload_mixerdev(devc->my_mixerdev);
--- linux/drivers/sound/sound_switch.c.prepersist Sun Dec 7 19:07:21 1997
+++ linux/drivers/sound/sound_switch.c Sun Dec 7 20:44:01 1997
@@ -39,6 +39,7 @@
load_mixer_volumes(char *name, int *levels, int present)
{
int i, n;
+ char buf[32];
for (i = 0; i < num_mixer_volumes; i++)
if (strcmp(name, mixer_vols[i].name) == 0)
@@ -63,6 +64,18 @@
for (i = 0; i < 32; i++)
mixer_vols[n].levels[i] = levels[i];
+
+ /* Ask kerneld for the mixer levels for this one.
+ * We do this _after_ copying in the defaults, so that we
+ * don't need to do any error handling. DW.
+ */
+#ifdef CONFIG_KERNELD
+ sprintf(buf,"mixer_%s",name);
+ printk("Asking kerneld for sound levels for %s\n",buf);
+
+ printk("get_persist returns %d\n",get_persist(buf, (void *)&mixer_vols[n].levels, sizeof(mixer_vols[n].levels)));
+
+#endif
return mixer_vols[n].levels;
}

--==_Exmh_8481573880
Content-Type: text/plain; charset=us-ascii

---- ---- ----
David Woodhouse, Robinson College, CB3 9AN, England. (+44) 0976 658355
dwmw2@cam.ac.uk http://dwmw2.robinson.cam.ac.uk
finger pgp@dwmw2.robinson.cam.ac.uk for PGP key.

--==_Exmh_8481573880--

- Next message: Krzysztof G. Baranowski: "rmmod ipv6 - opps (it's still there)"
- Previous message: Ildar Khabibrakhmanov: "Re: 2.1.70: stange NFS modes"