All of lore.kernel.org
 help / color / mirror / Atom feed
From: LCID Fire <lcid-fire@gmx.net>
To: Takashi Iwai <tiwai@suse.de>
Cc: alsa-devel@alsa-project.org
Subject: Re: [Fwd: Scratch Live amplifier switch]
Date: Fri, 16 Oct 2009 21:52:48 +0200	[thread overview]
Message-ID: <4AD8CF10.9050707@gmx.net> (raw)
In-Reply-To: <s5hy6p4l5hc.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 710 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Takashi Iwai wrote:
> I'd recommend not to use put callback.  snd_kcontrol_value is a big
> struct, so it should be avoided to be used on the stack as much as
> possible.  Better to take the accessor part from the put callback and
> call it from here.
> 
> 
> Could you fix and repost?
I reworked the patch and it should be better now (with regards to
multiple issues).
As always - apply or complain :)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkrYzw0ACgkQWo5Cf7DM0R8/JQCdFVUojGczhdtqizcm809LSov+
ndMAoIkW0mL7Hq0bhj0N/FZxBunL2VO8
=2KbY
-----END PGP SIGNATURE-----

[-- Attachment #2: slpreamp.patch --]
[-- Type: text/x-diff, Size: 8260 bytes --]

Signed-off-by: Andreas Bergmeier <andreas.bergmeier@gmx.net>

diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 00397c8..532d02d 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -2013,6 +2013,281 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 	}
 }
 
+static void snd_usb_cleanup_interrupt_urb(struct urb *pUrb)
+{
+	if (pUrb->transfer_buffer_length > 0)
+		kfree(pUrb->transfer_buffer);
+
+	kfree(pUrb->context);
+
+	usb_free_urb(pUrb);
+}
+
+/* Wrapper for setting and submitting the interrupt urb().*/
+static int snd_usb_interrupt_trans(struct usb_device *dev,
+	unsigned int pipe, void *data, __u16 size, usb_complete_t callback)
+{
+	int err = 0;
+	void *buf = NULL;
+	struct urb *pUrb = NULL;
+
+	buf = kmemdup(data, size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pUrb = usb_alloc_urb(1/*int iso packets*/, GFP_KERNEL);
+
+	if (!pUrb) {
+		/* cleanup */
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	/*TODO: Remove hardcoded 4*/
+	usb_fill_int_urb(pUrb, dev, pipe, buf, size, callback, NULL, 4);
+
+	err = usb_submit_urb(pUrb, GFP_KERNEL);
+
+	if (err < 0)
+		snd_usb_cleanup_interrupt_urb(pUrb);
+
+	return err;
+}
+
+#define snd_sl_phono_info snd_ctl_boolean_mono_info
+
+#define snd_sl_phono_receive snd_usb_cleanup_interrupt_urb
+
+#define snd_sl_phono_changed snd_sl_phono_receive
+
+static int snd_sl_phono_get(struct snd_kcontrol *kcontrol,
+	 struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = kcontrol->private_value;
+
+	/* the following code gets the value of the device
+	 * we just trust that the remembered state is correct
+	 * and don't use it :)
+
+	snd_usb_interrupt_trans(mixer->chip->dev,
+				usb_rcvbulkpipe(mixer->chip->dev, 0x83),
+				buffer, bufferSize, snd_sl_phono_receive);
+
+	unsigned char statusMessage[] = {7};
+
+	snd_usb_interrupt_trans(mixer->chip->dev,
+				usb_sndintpipe(mixer->chip->dev, 0x03),
+				statusMessage, 1, snd_sl_phono_receive);
+*/
+
+	return 0;
+}
+
+/* One example USB message on startup
+ * Unknown command
+	IN  03 Length: 0x40 ...
+	OUT 83 Length: 0x01 "00"
+	IN  03 Length: 0x40 "00 00 03 00 FF FF 02 00 01 00 03 00 01 00 FB FF
+		01 00 FF FF 06 00 02 00 FF FF 03 00 05 00 00 00
+		06 00 FC FF FD FF 03 00 FD FF 04 00 FB FF F8 FF
+		FC FF FD FF 06 00 01 00 01 00 FF FF 04 00 02 00"
+
+ * Sets line mode
+	IN  03 Length: 0x40 ...
+	OUT 83 Length: 0x02 "07 01"
+	IN  03 Length: 0x40 "07 FF 03 00 FF FF 02 00 01 00 03 00 01 00 FB FF
+		01 00 FF FF 06 00 02 00 FF FF 03 00 05 00 00 00
+		06 00 FC FF FD FF 03 00 FD FF 04 00 FB FF F8 FF
+		FC FF FD FF 06 00 01 00 01 00 FF FF 04 00 02 00"
+
+ * Unknown "termination" message?
+	IN  03 Length: 0x40 ...
+	OUT 83 Length: 0x01 "06"
+	OUT 83 Length: 0x01 "00"
+	IN  03 Length: 0x40 "00 FF FE FF FD FF 01 00 03 00 07 00 FE FF 08 00
+		03 00 00 00 FC FF 03 00 FF FF 00 00 01 00 03 00
+		FB FF F9 FF 01 00 FF FF FD FF 00 00 FE FF FA FF
+		FF FF FD FF 01 00 04 00 00 00 03 00 FB FF 01 00"
+
+ * Unknown commmand
+	IN  03 Length: 0x40 ...
+	OUT 83 Length: 0x01 "01"
+	IN  03 Length: 0x40 "01 42 FC 54 03 FF 01 00 03 00 07 00 FE FF 08 00
+		03 00 00 00 FC FF 03 00 FF FF 00 00 01 00 03 00
+		FB FF F9 FF 01 00 FF FF FD FF 00 00 FE FF FA FF
+		FF FF FD FF 01 00 04 00 00
+*/
+
+/* Following the messages that are sent prior and after setting the device
+ * no clue what they are good for - but they don't seem necessary
+static int snd_sl_phono_start(struct snd_kcontrol *kcontrol)
+{
+	unsigned char buffer[] = {0};
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	return snd_usb_interrupt_trans(mixer->chip->dev,
+				usb_sndintpipe(mixer->chip->dev, 0x03),
+				buffer, 1, snd_sl_phono_receive);
+}
+
+static int snd_sl_phono_end(struct snd_kcontrol *kcontrol)
+{
+	unsigned char buffer[] = {6};
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	return snd_usb_interrupt_trans(mixer->chip->dev,
+				usb_sndintpipe(mixer->chip->dev, 0x03),
+				buffer, 1, snd_sl_phono_receive);
+}
+*/
+
+static int snd_sl_phono_set(struct snd_kcontrol *kcontrol,
+	int value)
+{
+	int err;
+	const unsigned int bufferSize = 64;
+	unsigned char buffer[bufferSize];
+	unsigned char instructions[] = {7, 0};
+
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+
+/* One example of USB traffic by serato driver
+ * switching line to phono:
+
+	OUT 03 Length: 0x01 "00"
+
+	IN  83 Length: 0x40 ...
+	OUT 03 Length: 0x02 "07 00"
+	IN  83 Length: 0x40 "07 00 01 00 04 00 02 00 02 00 05 00 04 00 02 00
+		05 00 06 00 02 00 01 00 03 00 0E 00 05 00 0E 00
+		09 00 FF FF 02 00 02 00 05 00 03 00 FA FF 04 00
+		05 00 07 00 08 00 01 00 02 00 01 00 02 00 01 00"
+
+	IN  83 Length: 0x40 ...
+	OUT 03 Length: 0x01 "06"
+	IN  83 Length: 0x40 No answer!?
+
+ * switching phono to line:
+	OUT 03 Length: 0x01 "00"
+
+	IN  83 Length: 0x40 ...
+	OUT 03 Length: 0x02 "07 01"
+	IN  83 Length: 0x40 "07 FF F9 FF FB FF 01 00 FF FF FE FF F6 FF EF FF
+		F8 FF FD FF FB FF FC FF FA FF 00 00 FA FF F7 FF
+		F5 FF FB FF 01 00 F7 FF F7 FF FC FF F9 FF F9 FF
+		F7 FF F7 FF 00 00 F4 FF FB FF F6 FF F9 FF FA FF"
+
+	IN  83 Length: 0x40 ...
+	OUT 03 Length: 0x01 "06"
+	IN  83 Length: 0x40 No answer!?
+*/
+
+	if (value > 1)
+		return -EINVAL;
+
+	/* outcommented for now since it works without
+	 * and don't have a clue what it's good for
+	err = snd_sl_phono_start(kcontrol);
+	*/
+
+	err = snd_usb_interrupt_trans(mixer->chip->dev,
+				usb_rcvbulkpipe(mixer->chip->dev, 0x83),
+				buffer, bufferSize, snd_sl_phono_receive);
+
+	if (err < 0)
+		return err;
+
+	/* 07 00 = phone
+	   07 01 = line */
+	instructions[1] = !value;
+
+	err =  snd_usb_interrupt_trans(mixer->chip->dev,
+				usb_sndintpipe(mixer->chip->dev, 0x03),
+				instructions, 2, snd_sl_phono_receive);
+
+	if (err < 0)
+		return err;
+
+	err = snd_usb_interrupt_trans(mixer->chip->dev,
+				usb_rcvbulkpipe(mixer->chip->dev, 0x83),
+				buffer, bufferSize, snd_sl_phono_changed);
+
+	/* outcommented for now since it works without
+	 * and don't have a clue what it's good for
+	err = snd_sl_phono_end(kcontrol);
+	*/
+
+	if (err < 0)
+		return err;
+
+	kcontrol->private_value = value;
+	return 0;
+}
+
+static int snd_sl_phono_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	int err = 0;
+	int value = ucontrol->value.integer.value[0];
+
+	if (value == kcontrol->private_value)
+		return 0;
+
+	err = snd_sl_phono_set(kcontrol, value);
+
+	if (err < 0)
+		return err;
+
+	return 1;
+}
+
+static struct snd_kcontrol_new snd_sl_controls[] =
+{
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Phono Switch",
+		.info = snd_sl_phono_info,
+		.get = snd_sl_phono_get,
+		.put = snd_sl_phono_put,
+		.private_value = 1, /*switch is activated*/
+	}
+};
+
+/* gets called multiple times! */
+static int snd_sl_controls_create(struct usb_mixer_interface *mixer)
+{
+	int i, err;
+
+	for (i = 0; i < ARRAY_SIZE(snd_sl_controls); ++i) {
+		struct snd_kcontrol *kcontrol =
+			snd_ctl_new1(&snd_sl_controls[i], mixer);
+
+		/* Since we only need one control and the routine
+		 * is called multiple times we have to ignore all
+		 * attempts to attach controls multiple times*/
+		if (snd_ctl_find_id(mixer->chip->card, &kcontrol->id)) {
+			/* we found the control - it is already present
+			 * so just continue*/
+			snd_ctl_free_one(kcontrol);
+			continue;
+		}
+
+		/* add frees the control if on err < 0! */
+		err = snd_ctl_add(mixer->chip->card,
+			  kcontrol);
+		if (err < 0)
+			return err;
+
+		/* Make sure device is set to default */
+		err = snd_sl_phono_set(kcontrol, kcontrol->private_value);
+
+		if (err < 0) {
+			snd_ctl_free_one(kcontrol);
+			return err; /* the device screwed up */
+		}
+	}
+
+	return 0;
+}
+
 int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
 			 int ignore_error)
 {
@@ -2043,6 +2318,12 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
 	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
 		goto _error;
 
+	if (mixer->chip->usb_id == USB_ID(0x13e5, 0x001)) {
+		err = snd_sl_controls_create(mixer);
+		if (err < 0)
+			goto _error;
+	}
+
 	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
 	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040)) {
 		struct snd_info_entry *entry;

[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

  reply	other threads:[~2009-10-16 19:52 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-28  7:52 [Fwd: Scratch Live amplifier switch] LCID Fire
2009-08-28  8:14 ` Takashi Iwai
2009-10-16 19:52   ` LCID Fire [this message]
2009-11-02 13:03     ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4AD8CF10.9050707@gmx.net \
    --to=lcid-fire@gmx.net \
    --cc=alsa-devel@alsa-project.org \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.