blob: c36e95730de14d577e2a84962dc1c9fa2694f27a [file] [log] [blame]
Kyle Swenson8d8f6542021-03-15 11:02:55 -06001#ifndef __GADGET_CONFIGFS__
2#define __GADGET_CONFIGFS__
3
4#include <linux/configfs.h>
5
6int check_user_usb_string(const char *name,
7 struct usb_gadget_strings *stringtab_dev);
8
9#define GS_STRINGS_W(__struct, __name) \
10static ssize_t __struct##_##__name##_store(struct config_item *item, \
11 const char *page, size_t len) \
12{ \
13 struct __struct *gs = to_##__struct(item); \
14 int ret; \
15 \
16 ret = usb_string_copy(page, &gs->__name); \
17 if (ret) \
18 return ret; \
19 return len; \
20}
21
22#define GS_STRINGS_R(__struct, __name) \
23static ssize_t __struct##_##__name##_show(struct config_item *item, char *page) \
24{ \
25 struct __struct *gs = to_##__struct(item); \
26 return sprintf(page, "%s\n", gs->__name ?: ""); \
27}
28
29#define GS_STRINGS_RW(struct_name, _name) \
30 GS_STRINGS_R(struct_name, _name) \
31 GS_STRINGS_W(struct_name, _name) \
32 CONFIGFS_ATTR(struct_name##_, _name)
33
34#define USB_CONFIG_STRING_RW_OPS(struct_in) \
35static struct configfs_item_operations struct_in##_langid_item_ops = { \
36 .release = struct_in##_attr_release, \
37}; \
38 \
39static struct config_item_type struct_in##_langid_type = { \
40 .ct_item_ops = &struct_in##_langid_item_ops, \
41 .ct_attrs = struct_in##_langid_attrs, \
42 .ct_owner = THIS_MODULE, \
43}
44
45#define USB_CONFIG_STRINGS_LANG(struct_in, struct_member) \
46 static struct config_group *struct_in##_strings_make( \
47 struct config_group *group, \
48 const char *name) \
49 { \
50 struct struct_member *gi; \
51 struct struct_in *gs; \
52 struct struct_in *new; \
53 int langs = 0; \
54 int ret; \
55 \
56 new = kzalloc(sizeof(*new), GFP_KERNEL); \
57 if (!new) \
58 return ERR_PTR(-ENOMEM); \
59 \
60 ret = check_user_usb_string(name, &new->stringtab_dev); \
61 if (ret) \
62 goto err; \
63 config_group_init_type_name(&new->group, name, \
64 &struct_in##_langid_type); \
65 \
66 gi = container_of(group, struct struct_member, strings_group); \
67 ret = -EEXIST; \
68 list_for_each_entry(gs, &gi->string_list, list) { \
69 if (gs->stringtab_dev.language == new->stringtab_dev.language) \
70 goto err; \
71 langs++; \
72 } \
73 ret = -EOVERFLOW; \
74 if (langs >= MAX_USB_STRING_LANGS) \
75 goto err; \
76 \
77 list_add_tail(&new->list, &gi->string_list); \
78 return &new->group; \
79err: \
80 kfree(new); \
81 return ERR_PTR(ret); \
82} \
83 \
84static void struct_in##_strings_drop( \
85 struct config_group *group, \
86 struct config_item *item) \
87{ \
88 config_item_put(item); \
89} \
90 \
91static struct configfs_group_operations struct_in##_strings_ops = { \
92 .make_group = &struct_in##_strings_make, \
93 .drop_item = &struct_in##_strings_drop, \
94}; \
95 \
96static struct config_item_type struct_in##_strings_type = { \
97 .ct_group_ops = &struct_in##_strings_ops, \
98 .ct_owner = THIS_MODULE, \
99}
100
101#endif