the __uvcg_*frm_intrv() helper functions can be helpful when adding support for similar attributes. Generalise the function names and move them higher in the file for better coverage. We also need copies of the functions for different sized targets, so refactor them to a macro with configurable bit size. Signed-off-by: Daniel Scally <dan.scally@xxxxxxxxxxxxxxxx> --- drivers/usb/gadget/function/uvc_configfs.c | 109 +++++++++++---------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 832565730d22..9bacd8573a46 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -596,6 +596,60 @@ static const struct uvcg_config_group_type uvcg_terminal_grp_type = { }, }; +static inline int __uvcg_count_item_entries(char *buf, void *priv) +{ + ++*((int *)priv); + return 0; +} + +#define UVCG_ITEM_ENTRY_FUNCS(bits) \ +static inline int __uvcg_fill_item_entries_u##bits(char *buf, void *priv)\ +{ \ + u##bits num, **interv; \ + int ret; \ + \ + ret = kstrtou##bits(buf, 0, &num); \ + if (ret) \ + return ret; \ + \ + interv = priv; \ + **interv = num; \ + ++*interv; \ + \ + return 0; \ +} \ + \ +static int __uvcg_iter_item_entries_u##bits(const char *page, size_t len,\ + int (*fun)(char *, void *), void *priv)\ +{ \ + /* sign, base 2 representation, newline, terminator */ \ + char buf[1 + sizeof(u##bits) * 8 + 1 + 1]; \ + const char *pg = page; \ + int i, ret; \ + \ + if (!fun) \ + return -EINVAL; \ + \ + while (pg - page < len) { \ + i = 0; \ + while (i < sizeof(buf) && (pg - page < len) && \ + *pg != '\0' && *pg != '\n') \ + buf[i++] = *pg++; \ + if (i == sizeof(buf)) \ + return -EINVAL; \ + while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))\ + ++pg; \ + buf[i] = '\0'; \ + ret = fun(buf, priv); \ + if (ret) \ + return ret; \ + } \ + \ + return 0; \ +} + +UVCG_ITEM_ENTRY_FUNCS(32) + /* ----------------------------------------------------------------------------- * control/class/{fs|ss} */ @@ -1188,57 +1242,6 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item, return result; } -static inline int __uvcg_count_frm_intrv(char *buf, void *priv) -{ - ++*((int *)priv); - return 0; -} - -static inline int __uvcg_fill_frm_intrv(char *buf, void *priv) -{ - u32 num, **interv; - int ret; - - ret = kstrtou32(buf, 0, &num); - if (ret) - return ret; - - interv = priv; - **interv = num; - ++*interv; - - return 0; -} - -static int __uvcg_iter_frm_intrv(const char *page, size_t len, - int (*fun)(char *, void *), void *priv) -{ - /* sign, base 2 representation, newline, terminator */ - char buf[1 + sizeof(u32) * 8 + 1 + 1]; - const char *pg = page; - int i, ret; - - if (!fun) - return -EINVAL; - - while (pg - page < len) { - i = 0; - while (i < sizeof(buf) && (pg - page < len) && - *pg != '\0' && *pg != '\n') - buf[i++] = *pg++; - if (i == sizeof(buf)) - return -EINVAL; - while ((pg - page < len) && (*pg == '\0' || *pg == '\n')) - ++pg; - buf[i] = '\0'; - ret = fun(buf, priv); - if (ret) - return ret; - } - - return 0; -} - static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item, const char *page, size_t len) { @@ -1262,7 +1265,7 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item, goto end; } - ret = __uvcg_iter_frm_intrv(page, len, __uvcg_count_frm_intrv, &n); + ret = __uvcg_iter_item_entries_u32(page, len, __uvcg_count_item_entries, &n); if (ret) goto end; @@ -1272,7 +1275,7 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item, goto end; } - ret = __uvcg_iter_frm_intrv(page, len, __uvcg_fill_frm_intrv, &tmp); + ret = __uvcg_iter_item_entries_u32(page, len, __uvcg_fill_item_entries_u32, &tmp); if (ret) { kfree(frm_intrv); goto end; -- 2.34.1