usb: gadget: f_midi: allow resetting index option
authorJohn Keeping <john@metanate.com>
Fri, 29 Oct 2021 13:41:14 +0000 (14:41 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Nov 2021 13:40:43 +0000 (14:40 +0100)
Unlike the other integral options supported by the MIDI gadget, index is
a signed integer and defaults to -1, which means "choose any sound card
index".  The generic store routine parses input into a u32 which fails
to properly read -1 if an attempt is made to set the value to the
default.

Add a new macro block for signed values to fix this, and use the correct
format string for unsigned values.

Signed-off-by: John Keeping <john@metanate.com>
Link: https://lore.kernel.org/r/20211029134115.351008-1-john@metanate.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/function/f_midi.c

index 71a1a26e85c76b8a6f3979bc8293187d40a5f272..fddf539008a99a8f5c26a6f1ee237d5b46ace32b 100644 (file)
@@ -1097,7 +1097,7 @@ static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \
        int result;                                                     \
                                                                        \
        mutex_lock(&opts->lock);                                        \
-       result = sprintf(page, "%d\n", opts->name);                     \
+       result = sprintf(page, "%u\n", opts->name);                     \
        mutex_unlock(&opts->lock);                                      \
                                                                        \
        return result;                                                  \
@@ -1134,7 +1134,51 @@ end:                                                                     \
                                                                        \
 CONFIGFS_ATTR(f_midi_opts_, name);
 
-F_MIDI_OPT(index, true, SNDRV_CARDS);
+#define F_MIDI_OPT_SIGNED(name, test_limit, limit)                             \
+static ssize_t f_midi_opts_##name##_show(struct config_item *item, char *page) \
+{                                                                      \
+       struct f_midi_opts *opts = to_f_midi_opts(item);                \
+       int result;                                                     \
+                                                                       \
+       mutex_lock(&opts->lock);                                        \
+       result = sprintf(page, "%d\n", opts->name);                     \
+       mutex_unlock(&opts->lock);                                      \
+                                                                       \
+       return result;                                                  \
+}                                                                      \
+                                                                       \
+static ssize_t f_midi_opts_##name##_store(struct config_item *item,    \
+                                        const char *page, size_t len)  \
+{                                                                      \
+       struct f_midi_opts *opts = to_f_midi_opts(item);                \
+       int ret;                                                        \
+       s32 num;                                                        \
+                                                                       \
+       mutex_lock(&opts->lock);                                        \
+       if (opts->refcnt > 1) {                                         \
+               ret = -EBUSY;                                           \
+               goto end;                                               \
+       }                                                               \
+                                                                       \
+       ret = kstrtos32(page, 0, &num);                                 \
+       if (ret)                                                        \
+               goto end;                                               \
+                                                                       \
+       if (test_limit && num > limit) {                                \
+               ret = -EINVAL;                                          \
+               goto end;                                               \
+       }                                                               \
+       opts->name = num;                                               \
+       ret = len;                                                      \
+                                                                       \
+end:                                                                   \
+       mutex_unlock(&opts->lock);                                      \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+CONFIGFS_ATTR(f_midi_opts_, name);
+
+F_MIDI_OPT_SIGNED(index, true, SNDRV_CARDS);
 F_MIDI_OPT(buflen, false, 0);
 F_MIDI_OPT(qlen, false, 0);
 F_MIDI_OPT(in_ports, true, MAX_PORTS);