usb: gadget: midi2: Add "Operation Mode" control
authorTakashi Iwai <tiwai@suse.de>
Tue, 25 Jul 2023 06:22:05 +0000 (08:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Jul 2023 04:38:14 +0000 (06:38 +0200)
Add a new ALSA control element to watch the current operation mode
(MIDI 1.0 or MIDI 2.0).  It's a read-only control that reflects the
current value of altsetting, and 0 means unused, 1 for MIDI 1.0
(altset 0) and 2 for MIDI 2.0 (altset 1).

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20230725062206.9674-7-tiwai@suse.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/usb/gadget-testing.rst
drivers/usb/gadget/function/f_midi2.c

index 0f3708a..1fb181d 100644 (file)
@@ -1106,3 +1106,14 @@ On the host::
 The access to MIDI 1.0 on altset 0 on the host is supported, and it's
 translated from/to UMP packets on the gadget. It's bound to only
 Function Block 0.
+
+The current operation mode can be observed in ALSA control element
+"Operation Mode" for SND_CTL_IFACE_RAWMIDI.  For example::
+
+  $ amixer -c1 contents
+  numid=1,iface=RAWMIDI,name='Operation Mode'
+    ; type=INTEGER,access=r--v----,values=1,min=0,max=2,step=0
+    : values=2
+
+where 0 = unused, 1 = MIDI 1.0 (altset 0), 2 = MIDI 2.0 (altset 1).
+The example above shows it's running in 2, i.e. MIDI 2.0.
index a368ac5..ec9ef15 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 
 #include <sound/core.h>
+#include <sound/control.h>
 #include <sound/ump.h>
 #include <sound/ump_msg.h>
 #include <sound/ump_convert.h>
@@ -1451,6 +1452,36 @@ static const struct snd_ump_ops f_midi2_ump_ops = {
 };
 
 /*
+ * "Operation Mode" control element
+ */
+static int f_midi2_operation_mode_info(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = MIDI_OP_MODE_UNSET;
+       uinfo->value.integer.max = MIDI_OP_MODE_MIDI2;
+       return 0;
+}
+
+static int f_midi2_operation_mode_get(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_value *ucontrol)
+{
+       struct f_midi2 *midi2 = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = midi2->operation_mode;
+       return 0;
+}
+
+static const struct snd_kcontrol_new operation_mode_ctl = {
+       .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
+       .name = "Operation Mode",
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+       .info = f_midi2_operation_mode_info,
+       .get = f_midi2_operation_mode_get,
+};
+
+/*
  * ALSA UMP instance creation / deletion
  */
 static void f_midi2_free_card(struct f_midi2 *midi2)
@@ -1547,6 +1578,10 @@ static int f_midi2_create_card(struct f_midi2 *midi2)
                id++;
        }
 
+       err = snd_ctl_add(card, snd_ctl_new1(&operation_mode_ctl, midi2));
+       if (err < 0)
+               goto error;
+
        err = snd_card_register(card);
        if (err < 0)
                goto error;