From: Chris Wulff <crwulff@xxxxxxxxx> Consolidate a bunch of common #defines used by both f_uac1 and f_uac2 to make it easier to maintain. Only the #defines moved and the same static functions get created in each module as before. Formatters are also #define which makes slightly smaller code. Signed-off-by: Chris Wulff <crwulff@xxxxxxxxx> --- drivers/usb/gadget/function/f_uac1.c | 148 +-------------- drivers/usb/gadget/function/f_uac2.c | 207 +-------------------- drivers/usb/gadget/function/u_uac_utils.h | 217 ++++++++++++++++++++++ 3 files changed, 235 insertions(+), 337 deletions(-) create mode 100644 drivers/usb/gadget/function/u_uac_utils.h diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index c87e74afc881..eeedcfa61fa1 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -19,6 +19,7 @@ #include "u_audio.h" #include "u_uac1.h" +#include "u_uac_utils.h" /* UAC1 spec: 3.7.2.3 Audio Channel Cluster Format */ #define UAC1_CHANNEL_MASK 0x0FFF @@ -1516,151 +1517,18 @@ static struct configfs_item_operations f_uac1_item_ops = { .release = f_uac1_attr_release, }; -#define uac1_kstrtou32 kstrtou32 -#define uac1_kstrtos16 kstrtos16 -#define uac1_kstrtobool(s, base, res) kstrtobool((s), (res)) - -static const char *u32_fmt = "%u\n"; -static const char *s16_fmt = "%hd\n"; -static const char *bool_fmt = "%u\n"; - +#define UAC1_ATTR_TO_OPTS struct f_uac1_opts *opts = to_f_uac1_opts(item) #define UAC1_ATTRIBUTE(type, name) \ -static ssize_t f_uac1_opts_##name##_show( \ - struct config_item *item, \ - char *page) \ -{ \ - struct f_uac1_opts *opts = to_f_uac1_opts(item); \ - int result; \ - \ - mutex_lock(&opts->lock); \ - result = sprintf(page, type##_fmt, opts->name); \ - mutex_unlock(&opts->lock); \ - \ - return result; \ -} \ - \ -static ssize_t f_uac1_opts_##name##_store( \ - struct config_item *item, \ - const char *page, size_t len) \ -{ \ - struct f_uac1_opts *opts = to_f_uac1_opts(item); \ - int ret; \ - type num; \ - \ - mutex_lock(&opts->lock); \ - if (opts->refcnt) { \ - ret = -EBUSY; \ - goto end; \ - } \ - \ - ret = uac1_kstrto##type(page, 0, &num); \ - if (ret) \ - goto end; \ - \ - opts->name = num; \ - ret = len; \ - \ -end: \ - mutex_unlock(&opts->lock); \ - return ret; \ -} \ - \ -CONFIGFS_ATTR(f_uac1_opts_, name) + UAC_ATTRIBUTE(f_uac1_opts, UAC1_ATTR_TO_OPTS, opts, \ + opts->lock, opts->refcnt, type, name) #define UAC1_RATE_ATTRIBUTE(name) \ -static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \ - char *page) \ -{ \ - struct f_uac1_opts *opts = to_f_uac1_opts(item); \ - int result = 0; \ - int i; \ - \ - mutex_lock(&opts->lock); \ - page[0] = '\0'; \ - for (i = 0; i < UAC_MAX_RATES; i++) { \ - if (opts->name##s[i] == 0) \ - break; \ - result += sprintf(page + strlen(page), "%u,", \ - opts->name##s[i]); \ - } \ - if (strlen(page) > 0) \ - page[strlen(page) - 1] = '\n'; \ - mutex_unlock(&opts->lock); \ - \ - return result; \ -} \ - \ -static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \ - const char *page, size_t len) \ -{ \ - struct f_uac1_opts *opts = to_f_uac1_opts(item); \ - char *split_page = NULL; \ - int ret = -EINVAL; \ - char *token; \ - u32 num; \ - int i; \ - \ - mutex_lock(&opts->lock); \ - if (opts->refcnt) { \ - ret = -EBUSY; \ - goto end; \ - } \ - \ - i = 0; \ - memset(opts->name##s, 0x00, sizeof(opts->name##s)); \ - split_page = kstrdup(page, GFP_KERNEL); \ - while ((token = strsep(&split_page, ",")) != NULL) { \ - ret = kstrtou32(token, 0, &num); \ - if (ret) \ - goto end; \ - \ - opts->name##s[i++] = num; \ - ret = len; \ - }; \ - \ -end: \ - kfree(split_page); \ - mutex_unlock(&opts->lock); \ - return ret; \ -} \ - \ -CONFIGFS_ATTR(f_uac1_opts_, name) + UAC_RATE_ATTRIBUTE(f_uac1_opts, UAC1_ATTR_TO_OPTS, opts, \ + opts->lock, opts->refcnt, name) #define UAC1_ATTRIBUTE_STRING(name) \ -static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \ - char *page) \ -{ \ - struct f_uac1_opts *opts = to_f_uac1_opts(item); \ - int result; \ - \ - mutex_lock(&opts->lock); \ - result = scnprintf(page, sizeof(opts->name), "%s", opts->name); \ - mutex_unlock(&opts->lock); \ - \ - return result; \ -} \ - \ -static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \ - const char *page, size_t len) \ -{ \ - struct f_uac1_opts *opts = to_f_uac1_opts(item); \ - int ret = 0; \ - \ - mutex_lock(&opts->lock); \ - if (opts->refcnt) { \ - ret = -EBUSY; \ - goto end; \ - } \ - \ - ret = scnprintf(opts->name, min(sizeof(opts->name), len), \ - "%s", page); \ - \ -end: \ - mutex_unlock(&opts->lock); \ - return ret; \ -} \ - \ -CONFIGFS_ATTR(f_uac1_opts_, name) + UAC_ATTRIBUTE_STRING(f_uac1_opts, UAC1_ATTR_TO_OPTS, opts, \ + opts->lock, opts->refcnt, name) UAC1_ATTRIBUTE(u32, c_chmask); UAC1_RATE_ATTRIBUTE(c_srate); diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 1cdda44455b3..2142a0951f71 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -17,6 +17,7 @@ #include "u_audio.h" #include "u_uac2.h" +#include "u_uac_utils.h" /* UAC2 spec: 4.1 Audio Channel Cluster Descriptor */ #define UAC2_CHANNEL_MASK 0x07FFFFFF @@ -1877,210 +1878,22 @@ static struct configfs_item_operations f_uac2_item_ops = { .release = f_uac2_attr_release, }; -#define uac2_kstrtou8 kstrtou8 -#define uac2_kstrtou32 kstrtou32 -#define uac2_kstrtos16 kstrtos16 -#define uac2_kstrtobool(s, base, res) kstrtobool((s), (res)) - -static const char *u8_fmt = "%u\n"; -static const char *u32_fmt = "%u\n"; -static const char *s16_fmt = "%hd\n"; -static const char *bool_fmt = "%u\n"; - +#define UAC2_ATTR_TO_OPTS struct f_uac2_opts *opts = to_f_uac2_opts(item) #define UAC2_ATTRIBUTE(type, name) \ -static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ - char *page) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - int result; \ - \ - mutex_lock(&opts->lock); \ - result = sprintf(page, type##_fmt, opts->name); \ - mutex_unlock(&opts->lock); \ - \ - return result; \ -} \ - \ -static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ - const char *page, size_t len) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - int ret; \ - type num; \ - \ - mutex_lock(&opts->lock); \ - if (opts->refcnt) { \ - ret = -EBUSY; \ - goto end; \ - } \ - \ - ret = uac2_kstrto##type(page, 0, &num); \ - if (ret) \ - goto end; \ - \ - opts->name = num; \ - ret = len; \ - \ -end: \ - mutex_unlock(&opts->lock); \ - return ret; \ -} \ - \ -CONFIGFS_ATTR(f_uac2_opts_, name) + UAC_ATTRIBUTE(f_uac2_opts, UAC2_ATTR_TO_OPTS, opts, \ + opts->lock, opts->refcnt, type, name) #define UAC2_ATTRIBUTE_SYNC(name) \ -static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ - char *page) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - int result; \ - char *str; \ - \ - mutex_lock(&opts->lock); \ - switch (opts->name) { \ - case USB_ENDPOINT_SYNC_ASYNC: \ - str = "async"; \ - break; \ - case USB_ENDPOINT_SYNC_ADAPTIVE: \ - str = "adaptive"; \ - break; \ - default: \ - str = "unknown"; \ - break; \ - } \ - result = sprintf(page, "%s\n", str); \ - mutex_unlock(&opts->lock); \ - \ - return result; \ -} \ - \ -static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ - const char *page, size_t len) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - int ret = 0; \ - \ - mutex_lock(&opts->lock); \ - if (opts->refcnt) { \ - ret = -EBUSY; \ - goto end; \ - } \ - \ - if (!strncmp(page, "async", 5)) \ - opts->name = USB_ENDPOINT_SYNC_ASYNC; \ - else if (!strncmp(page, "adaptive", 8)) \ - opts->name = USB_ENDPOINT_SYNC_ADAPTIVE; \ - else { \ - ret = -EINVAL; \ - goto end; \ - } \ - \ - ret = len; \ - \ -end: \ - mutex_unlock(&opts->lock); \ - return ret; \ -} \ - \ -CONFIGFS_ATTR(f_uac2_opts_, name) + UAC_ATTRIBUTE_SYNC(f_uac2_opts, UAC2_ATTR_TO_OPTS, opts, \ + opts->lock, opts->refcnt, name) #define UAC2_RATE_ATTRIBUTE(name) \ -static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ - char *page) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - int result = 0; \ - int i; \ - \ - mutex_lock(&opts->lock); \ - page[0] = '\0'; \ - for (i = 0; i < UAC_MAX_RATES; i++) { \ - if (opts->name##s[i] == 0) \ - break; \ - result += sprintf(page + strlen(page), "%u,", \ - opts->name##s[i]); \ - } \ - if (strlen(page) > 0) \ - page[strlen(page) - 1] = '\n'; \ - mutex_unlock(&opts->lock); \ - \ - return result; \ -} \ - \ -static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ - const char *page, size_t len) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - char *split_page = NULL; \ - int ret = -EINVAL; \ - char *token; \ - u32 num; \ - int i; \ - \ - mutex_lock(&opts->lock); \ - if (opts->refcnt) { \ - ret = -EBUSY; \ - goto end; \ - } \ - \ - i = 0; \ - memset(opts->name##s, 0x00, sizeof(opts->name##s)); \ - split_page = kstrdup(page, GFP_KERNEL); \ - while ((token = strsep(&split_page, ",")) != NULL) { \ - ret = kstrtou32(token, 0, &num); \ - if (ret) \ - goto end; \ - \ - opts->name##s[i++] = num; \ - ret = len; \ - }; \ - \ -end: \ - kfree(split_page); \ - mutex_unlock(&opts->lock); \ - return ret; \ -} \ - \ -CONFIGFS_ATTR(f_uac2_opts_, name) + UAC_RATE_ATTRIBUTE(f_uac2_opts, UAC2_ATTR_TO_OPTS, opts, \ + opts->lock, opts->refcnt, name) #define UAC2_ATTRIBUTE_STRING(name) \ -static ssize_t f_uac2_opts_##name##_show(struct config_item *item, \ - char *page) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - int result; \ - \ - mutex_lock(&opts->lock); \ - result = scnprintf(page, sizeof(opts->name), "%s", opts->name); \ - mutex_unlock(&opts->lock); \ - \ - return result; \ -} \ - \ -static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \ - const char *page, size_t len) \ -{ \ - struct f_uac2_opts *opts = to_f_uac2_opts(item); \ - int ret = 0; \ - \ - mutex_lock(&opts->lock); \ - if (opts->refcnt) { \ - ret = -EBUSY; \ - goto end; \ - } \ - \ - if (len && page[len - 1] == '\n') \ - len--; \ - \ - ret = scnprintf(opts->name, min(sizeof(opts->name), len + 1), \ - "%s", page); \ - \ -end: \ - mutex_unlock(&opts->lock); \ - return ret; \ -} \ - \ -CONFIGFS_ATTR(f_uac2_opts_, name) + UAC_ATTRIBUTE_STRING(f_uac2_opts, UAC2_ATTR_TO_OPTS, opts, \ + opts->lock, opts->refcnt, name) UAC2_ATTRIBUTE(u32, p_chmask); UAC2_RATE_ATTRIBUTE(p_srate); diff --git a/drivers/usb/gadget/function/u_uac_utils.h b/drivers/usb/gadget/function/u_uac_utils.h new file mode 100644 index 000000000000..5f88e31103dd --- /dev/null +++ b/drivers/usb/gadget/function/u_uac_utils.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * u_uac_utils.h -- Utilities for UAC1/2 function driver + * + * Copyright (C) 2024 + * Author: Chris Wulff <crwulff@xxxxxxxxx> + */ + +#ifndef __U_UAC_UTILS_H +#define __U_UAC_UTILS_H + +#define uac_kstrtou8 kstrtou8 +#define uac_kstrtos16 kstrtos16 +#define uac_kstrtou32 kstrtou32 +#define uac_kstrtobool(s, base, res) kstrtobool((s), (res)) + +#define u8_FMT "%u\n" +#define u32_FMT "%u\n" +#define s16_FMT "%hd\n" +#define bool_FMT "%u\n" + +#define UAC_ATTRIBUTE(prefix, to_struct, var, lock, refcnt, type, name) \ +static ssize_t prefix##_##name##_show(struct config_item *item, \ + char *page) \ +{ \ + to_struct; \ + int result; \ + \ + mutex_lock(&lock); \ + result = sprintf(page, type##_FMT, var->name); \ + mutex_unlock(&lock); \ + \ + return result; \ +} \ + \ +static ssize_t prefix##_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + to_struct; \ + int ret; \ + type num; \ + \ + mutex_lock(&lock); \ + if (refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + ret = uac_kstrto##type(page, 0, &num); \ + if (ret) \ + goto end; \ + \ + var->name = num; \ + ret = len; \ + \ +end: \ + mutex_unlock(&lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(prefix##_, name) + +#define UAC_RATE_ATTRIBUTE(prefix, to_struct, var, lock, refcnt, name) \ +static ssize_t prefix##_##name##_show(struct config_item *item, \ + char *page) \ +{ \ + to_struct; \ + int result = 0; \ + int i; \ + \ + mutex_lock(&lock); \ + page[0] = '\0'; \ + for (i = 0; i < UAC_MAX_RATES; i++) { \ + if (var->name##s[i] == 0) \ + break; \ + result += sprintf(page + strlen(page), "%u,", \ + var->name##s[i]); \ + } \ + if (strlen(page) > 0) \ + page[strlen(page) - 1] = '\n'; \ + mutex_unlock(&lock); \ + \ + return result; \ +} \ + \ +static ssize_t prefix##_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + to_struct; \ + char *split_page = NULL; \ + int ret = -EINVAL; \ + char *token; \ + u32 num; \ + int i; \ + \ + mutex_lock(&lock); \ + if (refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + i = 0; \ + memset(var->name##s, 0x00, sizeof(var->name##s)); \ + split_page = kstrdup(page, GFP_KERNEL); \ + while ((token = strsep(&split_page, ",")) != NULL) { \ + ret = kstrtou32(token, 0, &num); \ + if (ret) \ + goto end; \ + \ + var->name##s[i++] = num; \ + ret = len; \ + }; \ + \ +end: \ + kfree(split_page); \ + mutex_unlock(&lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(prefix##_, name) + +#define UAC_ATTRIBUTE_STRING(prefix, to_struct, var, lock, refcnt, name) \ +static ssize_t prefix##_##name##_show(struct config_item *item, \ + char *page) \ +{ \ + to_struct; \ + int result; \ + \ + mutex_lock(&lock); \ + result = scnprintf(page, sizeof(var->name), "%s", var->name); \ + mutex_unlock(&lock); \ + \ + return result; \ +} \ + \ +static ssize_t prefix##_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + to_struct; \ + int ret = 0; \ + \ + mutex_lock(&lock); \ + if (refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + if (len && page[len - 1] == '\n') \ + len--; \ + \ + ret = scnprintf(var->name, min(sizeof(var->name), len + 1), \ + "%s", page); \ + \ +end: \ + mutex_unlock(&lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(prefix##_, name) + +#define UAC_ATTRIBUTE_SYNC(prefix, to_struct, var, lock, refcnt, name) \ +static ssize_t prefix##_##name##_show(struct config_item *item, \ + char *page) \ +{ \ + to_struct; \ + int result; \ + char *str; \ + \ + mutex_lock(&lock); \ + switch (var->name) { \ + case USB_ENDPOINT_SYNC_ASYNC: \ + str = "async"; \ + break; \ + case USB_ENDPOINT_SYNC_ADAPTIVE: \ + str = "adaptive"; \ + break; \ + default: \ + str = "unknown"; \ + break; \ + } \ + result = sprintf(page, "%s\n", str); \ + mutex_unlock(&lock); \ + \ + return result; \ +} \ + \ +static ssize_t prefix##_##name##_store(struct config_item *item, \ + const char *page, size_t len) \ +{ \ + to_struct; \ + int ret = 0; \ + \ + mutex_lock(&lock); \ + if (refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + if (!strncmp(page, "async", 5)) \ + var->name = USB_ENDPOINT_SYNC_ASYNC; \ + else if (!strncmp(page, "adaptive", 8)) \ + var->name = USB_ENDPOINT_SYNC_ADAPTIVE; \ + else { \ + ret = -EINVAL; \ + goto end; \ + } \ + \ + ret = len; \ + \ +end: \ + mutex_unlock(&lock); \ + return ret; \ +} \ + \ +CONFIGFS_ATTR(prefix##_, name) + +#endif /* __U_UAC_UTILS_H */ -- 2.43.0