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) \ | |
45b6a73f | 10 | static ssize_t __struct##_##__name##_store(struct config_item *item, \ |
88af8bbe SAS |
11 | const char *page, size_t len) \ |
12 | { \ | |
45b6a73f | 13 | struct __struct *gs = to_##__struct(item); \ |
88af8bbe SAS |
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) \ | |
45b6a73f | 23 | static ssize_t __struct##_##__name##_show(struct config_item *item, char *page) \ |
88af8bbe | 24 | { \ |
45b6a73f | 25 | struct __struct *gs = to_##__struct(item); \ |
88af8bbe SAS |
26 | return sprintf(page, "%s\n", gs->__name ?: ""); \ |
27 | } | |
28 | ||
88af8bbe SAS |
29 | #define GS_STRINGS_RW(struct_name, _name) \ |
30 | GS_STRINGS_R(struct_name, _name) \ | |
31 | GS_STRINGS_W(struct_name, _name) \ | |
45b6a73f | 32 | CONFIGFS_ATTR(struct_name##_, _name) |
88af8bbe SAS |
33 | |
34 | #define USB_CONFIG_STRING_RW_OPS(struct_in) \ | |
88af8bbe SAS |
35 | static struct configfs_item_operations struct_in##_langid_item_ops = { \ |
36 | .release = struct_in##_attr_release, \ | |
88af8bbe SAS |
37 | }; \ |
38 | \ | |
39 | static 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; \ | |
79 | err: \ | |
80 | kfree(new); \ | |
81 | return ERR_PTR(ret); \ | |
82 | } \ | |
83 | \ | |
84 | static void struct_in##_strings_drop( \ | |
85 | struct config_group *group, \ | |
86 | struct config_item *item) \ | |
87 | { \ | |
88 | config_item_put(item); \ | |
89 | } \ | |
90 | \ | |
91 | static struct configfs_group_operations struct_in##_strings_ops = { \ | |
92 | .make_group = &struct_in##_strings_make, \ | |
93 | .drop_item = &struct_in##_strings_drop, \ | |
94 | }; \ | |
95 | \ | |
96 | static 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 |