Commit | Line | Data |
---|---|---|
88af8bbe SAS |
1 | #ifndef __GADGET_CONFIGFS__ |
2 | #define __GADGET_CONFIGFS__ | |
3 | ||
4 | #include <linux/configfs.h> | |
5 | ||
6 | int 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 | \ | |
42 | static 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 | \ | |
48 | static 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; \ | |
88 | err: \ | |
89 | kfree(new); \ | |
90 | return ERR_PTR(ret); \ | |
91 | } \ | |
92 | \ | |
93 | static void struct_in##_strings_drop( \ | |
94 | struct config_group *group, \ | |
95 | struct config_item *item) \ | |
96 | { \ | |
97 | config_item_put(item); \ | |
98 | } \ | |
99 | \ | |
100 | static struct configfs_group_operations struct_in##_strings_ops = { \ | |
101 | .make_group = &struct_in##_strings_make, \ | |
102 | .drop_item = &struct_in##_strings_drop, \ | |
103 | }; \ | |
104 | \ | |
105 | static 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 |