usb: gadget: uvc: Generalise helper functions for reuse
The __uvcg_*frm_intrv() helper functions can be helpful when adding support for similar attributes. Generalise the functions and move them higher in the file for better coverage. Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com> Link: https://lore.kernel.org/r/20230206161802.892954-3-dan.scally@ideasonboard.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b3c839bd8a
commit
0df28607c5
1 changed files with 67 additions and 53 deletions
|
@ -47,6 +47,71 @@ static int uvcg_config_compare_u32(const void *l, const void *r)
|
|||
return li < ri ? -1 : li == ri ? 0 : 1;
|
||||
}
|
||||
|
||||
static inline int __uvcg_count_item_entries(char *buf, void *priv, unsigned int size)
|
||||
{
|
||||
++*((int *)priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __uvcg_fill_item_entries(char *buf, void *priv, unsigned int size)
|
||||
{
|
||||
unsigned int num;
|
||||
u8 **values;
|
||||
int ret;
|
||||
|
||||
ret = kstrtouint(buf, 0, &num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (num != (num & GENMASK((size * 8) - 1, 0)))
|
||||
return -ERANGE;
|
||||
|
||||
values = priv;
|
||||
memcpy(*values, &num, size);
|
||||
*values += size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __uvcg_iter_item_entries(const char *page, size_t len,
|
||||
int (*fun)(char *, void *, unsigned int),
|
||||
void *priv, unsigned int size)
|
||||
{
|
||||
/* sign, base 2 representation, newline, terminator */
|
||||
unsigned int bufsize = 1 + size * 8 + 1 + 1;
|
||||
const char *pg = page;
|
||||
int i, ret = 0;
|
||||
char *buf;
|
||||
|
||||
if (!fun)
|
||||
return -EINVAL;
|
||||
|
||||
buf = kzalloc(bufsize, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
while (pg - page < len) {
|
||||
i = 0;
|
||||
while (i < sizeof(buf) && (pg - page < len) &&
|
||||
*pg != '\0' && *pg != '\n')
|
||||
buf[i++] = *pg++;
|
||||
if (i == sizeof(buf)) {
|
||||
ret = -EINVAL;
|
||||
goto out_free_buf;
|
||||
}
|
||||
while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
|
||||
++pg;
|
||||
buf[i] = '\0';
|
||||
ret = fun(buf, priv, size);
|
||||
if (ret)
|
||||
goto out_free_buf;
|
||||
}
|
||||
|
||||
out_free_buf:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uvcg_config_group_type {
|
||||
struct config_item_type type;
|
||||
const char *name;
|
||||
|
@ -1336,57 +1401,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)
|
||||
{
|
||||
|
@ -1410,7 +1424,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(page, len, __uvcg_count_item_entries, &n, sizeof(u32));
|
||||
if (ret)
|
||||
goto end;
|
||||
|
||||
|
@ -1420,7 +1434,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(page, len, __uvcg_fill_item_entries, &tmp, sizeof(u32));
|
||||
if (ret) {
|
||||
kfree(frm_intrv);
|
||||
goto end;
|
||||
|
|
Loading…
Add table
Reference in a new issue