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