From: Rong Zhang Date: Thu, 5 Mar 2026 17:46:39 +0000 (+0800) Subject: ALSA: usb-audio: Refine string-descriptor-based quirk matching X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9558a2cbec2eb034ae7d570ff56ad74f9a918177;p=thirdparty%2Fkernel%2Flinux.git ALSA: usb-audio: Refine string-descriptor-based quirk matching Remove snd_usb_get_string() and use the manufacturer and product strings stored in struct usb_device directly to match quirk table entries. Their NULLity can be checked to determine if the device has no these strings. This simplifies the code a lot. Meanwhile, allow quirk table entries to match "no string" explicitly, and add appropriate comments to show the expected usages of DEVICE_STRING_FLG() and VENDOR_STRING_FLG(). These changes are tiny and doesn't form another separate patch, so that back-and-forth changes can be avoided. Suggested-by: Terry Junge Link: https://lore.kernel.org/r/b59da54a-9c80-4212-a337-c5ea98da52d1@cosmicgizmosystems.com Signed-off-by: Rong Zhang Link: https://patch.msgid.link/20260305174711.1106324-1-i@rong.moe Signed-off-by: Takashi Iwai --- diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 17f6be4d2350e..ab67f7826e9b5 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2153,7 +2153,28 @@ struct usb_audio_quirk_flags_table { { .id = USB_ID(vid, pid), .flags = (_flags) } #define VENDOR_FLG(vid, _flags) DEVICE_FLG(vid, 0, _flags) -/* Use as a last resort if using DEVICE_FLG() is prone to VID/PID conflicts. */ +/* + * Use as a last resort if using DEVICE_FLG() is prone to VID/PID conflicts. + * + * Usage: + * // match vid, pid, "manufacturer", and "product" + * DEVICE_STRING_FLG(vid, pid, "manufacturer", "product", flags) + * + * // match vid, pid, "manufacturer", and any product string + * DEVICE_STRING_FLG(vid, pid, "manufacturer", NULL, flags) + * + * // match vid, pid, "manufacturer", and device must have no product string + * DEVICE_STRING_FLG(vid, pid, "manufacturer", "", flags) + * + * // match vid, pid, any manufacturer string, and "product" + * DEVICE_STRING_FLG(vid, pid, NULL, "product", flags) + * + * // match vid, pid, no manufacturer string, and "product" + * DEVICE_STRING_FLG(vid, pid, "", "product", flags) + * + * // match vid, pid, no manufacturer string, and no product string + * DEVICE_STRING_FLG(vid, pid, "", "", flags) + */ #define DEVICE_STRING_FLG(vid, pid, _manufacturer, _product, _flags) \ { \ .id = USB_ID(vid, pid), \ @@ -2164,7 +2185,16 @@ struct usb_audio_quirk_flags_table { .flags = (_flags), \ } -/* Use as a last resort if using VENDOR_FLG() is prone to VID conflicts. */ +/* + * Use as a last resort if using VENDOR_FLG() is prone to VID conflicts. + * + * Usage: + * // match vid, and "manufacturer" + * VENDOR_STRING_FLG(vid, "manufacturer", flags) + * + * // match vid, and device must have no manufacturer string + * VENDOR_STRING_FLG(vid, "", flags) + */ #define VENDOR_STRING_FLG(vid, _manufacturer, _flags) \ DEVICE_STRING_FLG(vid, 0, _manufacturer, NULL, _flags) @@ -2595,63 +2625,23 @@ void snd_usb_apply_flag_dbg(const char *reason, } } -#define USB_STRING_SIZE 128 - -static char *snd_usb_get_string(struct snd_usb_audio *chip, int id) -{ - char *buf; - int ret; - - /* - * Devices without the corresponding string descriptor. - * This is non-fatal as *_STRING_FLG have nothing to do in this case. - */ - if (id == 0) - return ERR_PTR(-ENODATA); - - buf = kmalloc(USB_STRING_SIZE, GFP_KERNEL); - if (buf == NULL) - return ERR_PTR(-ENOMEM); - - ret = usb_string(chip->dev, id, buf, USB_STRING_SIZE); - if (ret < 0) { - usb_audio_warn(chip, "failed to get string for id%d: %d\n", id, ret); - kfree(buf); - return ERR_PTR(ret); - } - - return buf; -} - void snd_usb_init_quirk_flags_table(struct snd_usb_audio *chip) { const struct usb_audio_quirk_flags_table *p; - char *manufacturer __free(kfree) = NULL; - char *product __free(kfree) = NULL; for (p = quirk_flags_table; p->id; p++) { if (chip->usb_id == p->id || (!USB_ID_PRODUCT(p->id) && USB_ID_VENDOR(chip->usb_id) == USB_ID_VENDOR(p->id))) { /* Handle DEVICE_STRING_FLG/VENDOR_STRING_FLG. */ - if (p->usb_string_match && p->usb_string_match->manufacturer) { - if (!manufacturer) { - manufacturer = snd_usb_get_string(chip, - chip->dev->descriptor.iManufacturer); - } - if (IS_ERR_OR_NULL(manufacturer) || - strcmp(p->usb_string_match->manufacturer, manufacturer)) - continue; - } - if (p->usb_string_match && p->usb_string_match->product) { - if (!product) { - product = snd_usb_get_string(chip, - chip->dev->descriptor.iProduct); - } - if (IS_ERR_OR_NULL(product) || - strcmp(p->usb_string_match->product, product)) - continue; - } + if (p->usb_string_match && p->usb_string_match->manufacturer && + strcmp(p->usb_string_match->manufacturer, + chip->dev->manufacturer ? chip->dev->manufacturer : "")) + continue; + if (p->usb_string_match && p->usb_string_match->product && + strcmp(p->usb_string_match->product, + chip->dev->product ? chip->dev->product : "")) + continue; snd_usb_apply_flag_dbg("builtin table", chip, p->flags); chip->quirk_flags |= p->flags;