All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] UAC2 jack detection and clock validity
@ 2018-03-24  2:25 Andrew Chant
  2018-03-24  2:25 ` [PATCH v3 1/2] ALSA: usb-audio: UAC2 jack detection Andrew Chant
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Andrew Chant @ 2018-03-24  2:25 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Andrew Chant, Ruslan Bilovol, Benson Leung

These patches implement UAC2 jack detection.

This allows USB-to-3.5mm adapters and similar USB devices
to report jack state via alsa control, using the reporting
provided by the UAC2 connector control.

The second patch updates the clock validity control so
it doesn't show up in mixer UIs.

I declined to mark the controls as VOLATILE since clients
should always be notified of changes, since UAC devices
are expected to generate interrupt messages when a control
value changes.

v3 changes:
 - move channel count correction to first patch.
 - fix incorrect comment formatting and spacing.

v2 changes:
 - use SNDRV_CTL_ELEM_IFACE_CARD instead of _MIXER
 - correct channel count to 1, cmask to 0.
 - add validity patch.

Andrew Chant (2):
  ALSA: usb-audio: UAC2 jack detection
  ALSA: usb-audio: update clock valid control

 sound/usb/mixer.c | 117 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 109 insertions(+), 8 deletions(-)

-- 
2.17.0.rc0.231.g781580f067-goog

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v3 1/2] ALSA: usb-audio: UAC2 jack detection
  2018-03-24  2:25 [PATCH v3 0/2] UAC2 jack detection and clock validity Andrew Chant
@ 2018-03-24  2:25 ` Andrew Chant
  2018-03-24  8:51   ` Takashi Iwai
  2018-03-24  2:25 ` [PATCH v3 2/2] ALSA: usb-audio: update clock valid control Andrew Chant
  2018-03-24  8:51 ` [PATCH v3 0/2] UAC2 jack detection and clock validity Takashi Iwai
  2 siblings, 1 reply; 6+ messages in thread
From: Andrew Chant @ 2018-03-24  2:25 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Andrew Chant, Ruslan Bilovol, Benson Leung

This implements UAC2 jack detection support, presenting
jack status as a boolean read-only mono mixer.

The presence of any channel in the UAC2_TE_CONNECTOR
control for a terminal will result in the mixer saying
the jack is connected.

Mixer naming follows the convention in sound/core/ctljack.c,
terminating the mixer with " Jack".
For additional clues as to which jack is being presented,
the name is prefixed with " - Input Jack" or " - Output Jack"
depending on if it's an input or output terminal.

This is required because terminal names are ambiguous
between inputs and outputs and often duplicated -
Bidirectional terminal types (0x400 -> 0x4FF)
"... may be used separately for input only or output only.
These types require two Terminal descriptors. Both have the same type."
(quote from "USB Device Class Definition for Terminal Types")

Since bidirectional terminal types are common for headphone adapters,
this distinguishes between two otherwise identically-named
jack controls.

Tested with a UAC2 audio device with connector control capability.

Signed-off-by: Andrew Chant <achant@google.com>
---
 sound/usb/mixer.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 3075ac50a391..97ed2155205d 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1235,6 +1235,21 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
 	return changed;
 }
 
+/* get the current value from a mixer element */
+static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_elem_info *cval = kcontrol->private_data;
+	int val, err;
+
+	err = snd_usb_get_cur_mix_value(cval, 0, 0, &val);
+	if (err < 0)
+		return filter_error(cval, err);
+	val = (val != 0);
+	ucontrol->value.integer.value[0] = val;
+	return 0;
+}
+
 static struct snd_kcontrol_new usb_feature_unit_ctl = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "", /* will be filled later manually */
@@ -1252,6 +1267,16 @@ static const struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
 	.put = NULL,
 };
 
+/* A UAC connector mixer control */
+static struct snd_kcontrol_new usb_connector_ctl_ro = {
+	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
+	.name = "", /* will be filled later manually */
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.info = snd_ctl_boolean_mono_info,
+	.get = mixer_ctl_connector_get,
+	.put = NULL,
+};
+
 /*
  * This symbol is exported in order to allow the mixer quirks to
  * hook up to the standard feature unit control mechanism
@@ -1464,6 +1489,54 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 	snd_usb_mixer_add_control(&cval->head, kctl);
 }
 
+static void get_connector_control_name(struct mixer_build *state,
+				       struct usb_audio_term *term,
+				       bool is_input, char *name, int name_size)
+{
+	int name_len = get_term_name(state, term, name, name_size, 0);
+
+	if (name_len == 0)
+		strlcpy(name, "Unknown", name_size);
+
+	/*
+	 *  sound/core/ctljack.c has a convention of naming jack controls
+	 * by ending in " Jack".  Make it slightly more useful by
+	 * indicating Input or Output after the terminal name.
+	 */
+	if (is_input)
+		strlcat(name, " - Input Jack", name_size);
+	else
+		strlcat(name, " - Output Jack", name_size);
+}
+
+/* Build a mixer control for a UAC connector control (jack-detect) */
+static void build_connector_control(struct mixer_build *state,
+				    struct usb_audio_term *term, bool is_input)
+{
+	struct snd_kcontrol *kctl;
+	struct usb_mixer_elem_info *cval;
+
+	cval = kzalloc(sizeof(*cval), GFP_KERNEL);
+	if (!cval)
+		return;
+	snd_usb_mixer_elem_init_std(&cval->head, state->mixer, term->id);
+	cval->control = UAC2_TE_CONNECTOR;
+	cval->val_type = USB_MIXER_BOOLEAN;
+	cval->channels = 1; /* report true if any channel is connected */
+	cval->min = 0;
+	cval->max = 1;
+	kctl = snd_ctl_new1(&usb_connector_ctl_ro, cval);
+	if (!kctl) {
+		usb_audio_err(state->chip, "cannot malloc kcontrol\n");
+		kfree(cval);
+		return;
+	}
+	get_connector_control_name(state, term, is_input, kctl->id.name,
+				   sizeof(kctl->id.name));
+	kctl->private_free = snd_usb_mixer_elem_free;
+	snd_usb_mixer_add_control(&cval->head, kctl);
+}
+
 static int parse_clock_source_unit(struct mixer_build *state, int unitid,
 				   void *_ftr)
 {
@@ -1770,6 +1843,23 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
 	snd_usb_mixer_add_control(&cval->head, kctl);
 }
 
+static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
+				      void *raw_desc)
+{
+	struct usb_audio_term iterm;
+	struct uac2_input_terminal_descriptor *d = raw_desc;
+
+	check_input_term(state, d->bTerminalID, &iterm);
+	if (state->mixer->protocol == UAC_VERSION_2) {
+		/* Check for jack detection. */
+		if (uac_v2v3_control_is_readable(d->bmControls,
+						 UAC2_TE_CONNECTOR)) {
+			build_connector_control(state, &iterm, true);
+		}
+	}
+	return 0;
+}
+
 /*
  * parse a mixer unit
  */
@@ -2320,7 +2410,7 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
 	if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
 		switch (p1[2]) {
 		case UAC_INPUT_TERMINAL:
-			return 0; /* NOP */
+			return parse_audio_input_terminal(state, unitid, p1);
 		case UAC_MIXER_UNIT:
 			return parse_audio_mixer_unit(state, unitid, p1);
 		case UAC2_CLOCK_SOURCE:
@@ -2463,6 +2553,12 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
 			err = parse_audio_unit(&state, desc->bCSourceID);
 			if (err < 0 && err != -EINVAL)
 				return err;
+
+			if (uac_v2v3_control_is_readable(desc->bmControls,
+							 UAC2_TE_CONNECTOR)) {
+				build_connector_control(&state, &state.oterm,
+							false);
+			}
 		} else {  /* UAC_VERSION_3 */
 			struct uac3_output_terminal_descriptor *desc = p;
 
-- 
2.17.0.rc0.231.g781580f067-goog

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 2/2] ALSA: usb-audio: update clock valid control
  2018-03-24  2:25 [PATCH v3 0/2] UAC2 jack detection and clock validity Andrew Chant
  2018-03-24  2:25 ` [PATCH v3 1/2] ALSA: usb-audio: UAC2 jack detection Andrew Chant
@ 2018-03-24  2:25 ` Andrew Chant
  2018-03-24  8:51   ` Takashi Iwai
  2018-03-24  8:51 ` [PATCH v3 0/2] UAC2 jack detection and clock validity Takashi Iwai
  2 siblings, 1 reply; 6+ messages in thread
From: Andrew Chant @ 2018-03-24  2:25 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Andrew Chant, Ruslan Bilovol, Benson Leung

Make the "clock valid" control a global control instead of a mixer
so that it doesn't appear in mixer applications.

Additionally, remove the check for writeability prohibited by spec, and
Use common code to read the control value.

Tested with a UAC2 Audio device that presents a clock validity
control.  The control still shows up in /proc usbmixer but not
in alsamixer.

Signed-off-by: Andrew Chant <achant@google.com>
---
 sound/usb/mixer.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 97ed2155205d..04dab6f65535 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1235,9 +1235,9 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
 	return changed;
 }
 
-/* get the current value from a mixer element */
-static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
+/* get the boolean value from the master channel of a UAC control */
+static int mixer_ctl_master_bool_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct usb_mixer_elem_info *cval = kcontrol->private_data;
 	int val, err;
@@ -1267,13 +1267,16 @@ static const struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
 	.put = NULL,
 };
 
-/* A UAC connector mixer control */
-static struct snd_kcontrol_new usb_connector_ctl_ro = {
+/*
+ * A control which shows the boolean value from reading a UAC control on
+ * the master channel.
+ */
+static struct snd_kcontrol_new usb_bool_master_control_ctl_ro = {
 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
 	.name = "", /* will be filled later manually */
 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
 	.info = snd_ctl_boolean_mono_info,
-	.get = mixer_ctl_connector_get,
+	.get = mixer_ctl_master_bool_get,
 	.put = NULL,
 };
 
@@ -1520,12 +1523,18 @@ static void build_connector_control(struct mixer_build *state,
 	if (!cval)
 		return;
 	snd_usb_mixer_elem_init_std(&cval->head, state->mixer, term->id);
+	/*
+	 * The first byte from reading the UAC2_TE_CONNECTOR control returns the
+	 * number of channels connected.  This boolean ctl will simply report
+	 * if any channels are connected or not.
+	 * (Audio20_final.pdf Table 5-10: Connector Control CUR Parameter Block)
+	 */
 	cval->control = UAC2_TE_CONNECTOR;
 	cval->val_type = USB_MIXER_BOOLEAN;
 	cval->channels = 1; /* report true if any channel is connected */
 	cval->min = 0;
 	cval->max = 1;
-	kctl = snd_ctl_new1(&usb_connector_ctl_ro, cval);
+	kctl = snd_ctl_new1(&usb_bool_master_control_ctl_ro, cval);
 	if (!kctl) {
 		usb_audio_err(state->chip, "cannot malloc kcontrol\n");
 		kfree(cval);
@@ -1576,13 +1585,9 @@ static int parse_clock_source_unit(struct mixer_build *state, int unitid,
 	cval->val_type = USB_MIXER_BOOLEAN;
 	cval->control = UAC2_CS_CONTROL_CLOCK_VALID;
 
-	if (uac_v2v3_control_is_writeable(hdr->bmControls,
-				      UAC2_CS_CONTROL_CLOCK_VALID))
-		kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
-	else {
-		cval->master_readonly = 1;
-		kctl = snd_ctl_new1(&usb_feature_unit_ctl_ro, cval);
-	}
+	cval->master_readonly = 1;
+	/* From UAC2 5.2.5.1.2 "Only the get request is supported." */
+	kctl = snd_ctl_new1(&usb_bool_master_control_ctl_ro, cval);
 
 	if (!kctl) {
 		kfree(cval);
-- 
2.17.0.rc0.231.g781580f067-goog

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 0/2] UAC2 jack detection and clock validity
  2018-03-24  2:25 [PATCH v3 0/2] UAC2 jack detection and clock validity Andrew Chant
  2018-03-24  2:25 ` [PATCH v3 1/2] ALSA: usb-audio: UAC2 jack detection Andrew Chant
  2018-03-24  2:25 ` [PATCH v3 2/2] ALSA: usb-audio: update clock valid control Andrew Chant
@ 2018-03-24  8:51 ` Takashi Iwai
  2 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2018-03-24  8:51 UTC (permalink / raw)
  To: Andrew Chant; +Cc: alsa-devel, Ruslan Bilovol, Benson Leung

On Sat, 24 Mar 2018 03:25:22 +0100,
Andrew Chant wrote:
> 
> These patches implement UAC2 jack detection.
> 
> This allows USB-to-3.5mm adapters and similar USB devices
> to report jack state via alsa control, using the reporting
> provided by the UAC2 connector control.
> 
> The second patch updates the clock validity control so
> it doesn't show up in mixer UIs.
> 
> I declined to mark the controls as VOLATILE since clients
> should always be notified of changes, since UAC devices
> are expected to generate interrupt messages when a control
> value changes.

Right, after consideration, I concluded that, too.
Sorry for confusion.


Takashi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 1/2] ALSA: usb-audio: UAC2 jack detection
  2018-03-24  2:25 ` [PATCH v3 1/2] ALSA: usb-audio: UAC2 jack detection Andrew Chant
@ 2018-03-24  8:51   ` Takashi Iwai
  0 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2018-03-24  8:51 UTC (permalink / raw)
  To: Andrew Chant; +Cc: alsa-devel, Ruslan Bilovol, Benson Leung

On Sat, 24 Mar 2018 03:25:23 +0100,
Andrew Chant wrote:
> 
> This implements UAC2 jack detection support, presenting
> jack status as a boolean read-only mono mixer.
> 
> The presence of any channel in the UAC2_TE_CONNECTOR
> control for a terminal will result in the mixer saying
> the jack is connected.
> 
> Mixer naming follows the convention in sound/core/ctljack.c,
> terminating the mixer with " Jack".
> For additional clues as to which jack is being presented,
> the name is prefixed with " - Input Jack" or " - Output Jack"
> depending on if it's an input or output terminal.
> 
> This is required because terminal names are ambiguous
> between inputs and outputs and often duplicated -
> Bidirectional terminal types (0x400 -> 0x4FF)
> "... may be used separately for input only or output only.
> These types require two Terminal descriptors. Both have the same type."
> (quote from "USB Device Class Definition for Terminal Types")
> 
> Since bidirectional terminal types are common for headphone adapters,
> this distinguishes between two otherwise identically-named
> jack controls.
> 
> Tested with a UAC2 audio device with connector control capability.
> 
> Signed-off-by: Andrew Chant <achant@google.com>

Applied now, thanks.


Takashi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 2/2] ALSA: usb-audio: update clock valid control
  2018-03-24  2:25 ` [PATCH v3 2/2] ALSA: usb-audio: update clock valid control Andrew Chant
@ 2018-03-24  8:51   ` Takashi Iwai
  0 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2018-03-24  8:51 UTC (permalink / raw)
  To: Andrew Chant; +Cc: alsa-devel, Ruslan Bilovol, Benson Leung

On Sat, 24 Mar 2018 03:25:24 +0100,
Andrew Chant wrote:
> 
> Make the "clock valid" control a global control instead of a mixer
> so that it doesn't appear in mixer applications.
> 
> Additionally, remove the check for writeability prohibited by spec, and
> Use common code to read the control value.
> 
> Tested with a UAC2 Audio device that presents a clock validity
> control.  The control still shows up in /proc usbmixer but not
> in alsamixer.
> 
> Signed-off-by: Andrew Chant <achant@google.com>

Applied now, thanks.


Takashi

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-03-24  8:51 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-24  2:25 [PATCH v3 0/2] UAC2 jack detection and clock validity Andrew Chant
2018-03-24  2:25 ` [PATCH v3 1/2] ALSA: usb-audio: UAC2 jack detection Andrew Chant
2018-03-24  8:51   ` Takashi Iwai
2018-03-24  2:25 ` [PATCH v3 2/2] ALSA: usb-audio: update clock valid control Andrew Chant
2018-03-24  8:51   ` Takashi Iwai
2018-03-24  8:51 ` [PATCH v3 0/2] UAC2 jack detection and clock validity Takashi Iwai

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.