1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * u_ether_configfs.h
4 *
5 * Utility definitions for configfs support in USB Ethernet functions
6 *
7 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
8 * http://www.samsung.com
9 *
10 * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
11 */
12
13#ifndef __U_ETHER_CONFIGFS_H
14#define __U_ETHER_CONFIGFS_H
15
16#define USB_ETHERNET_CONFIGFS_ITEM(_f_) \
17 static void _f_##_attr_release(struct config_item *item) \
18 { \
19 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
20 \
21 usb_put_function_instance(&opts->func_inst); \
22 } \
23 \
24 static struct configfs_item_operations _f_##_item_ops = { \
25 .release = _f_##_attr_release, \
26 }
27
28#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_) \
29 static ssize_t _f_##_opts_dev_addr_show(struct config_item *item, \
30 char *page) \
31 { \
32 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
33 int result; \
34 \
35 mutex_lock(&opts->lock); \
36 result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \
37 mutex_unlock(&opts->lock); \
38 \
39 return result; \
40 } \
41 \
42 static ssize_t _f_##_opts_dev_addr_store(struct config_item *item, \
43 const char *page, size_t len)\
44 { \
45 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
46 int ret; \
47 \
48 mutex_lock(&opts->lock); \
49 if (opts->refcnt) { \
50 mutex_unlock(&opts->lock); \
51 return -EBUSY; \
52 } \
53 \
54 ret = gether_set_dev_addr(opts->net, page); \
55 mutex_unlock(&opts->lock); \
56 if (!ret) \
57 ret = len; \
58 return ret; \
59 } \
60 \
61 CONFIGFS_ATTR(_f_##_opts_, dev_addr)
62
63#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_) \
64 static ssize_t _f_##_opts_host_addr_show(struct config_item *item, \
65 char *page) \
66 { \
67 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
68 int result; \
69 \
70 mutex_lock(&opts->lock); \
71 result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \
72 mutex_unlock(&opts->lock); \
73 \
74 return result; \
75 } \
76 \
77 static ssize_t _f_##_opts_host_addr_store(struct config_item *item, \
78 const char *page, size_t len)\
79 { \
80 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
81 int ret; \
82 \
83 mutex_lock(&opts->lock); \
84 if (opts->refcnt) { \
85 mutex_unlock(&opts->lock); \
86 return -EBUSY; \
87 } \
88 \
89 ret = gether_set_host_addr(opts->net, page); \
90 mutex_unlock(&opts->lock); \
91 if (!ret) \
92 ret = len; \
93 return ret; \
94 } \
95 \
96 CONFIGFS_ATTR(_f_##_opts_, host_addr)
97
98#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_) \
99 static ssize_t _f_##_opts_qmult_show(struct config_item *item, \
100 char *page) \
101 { \
102 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
103 unsigned qmult; \
104 \
105 mutex_lock(&opts->lock); \
106 qmult = gether_get_qmult(opts->net); \
107 mutex_unlock(&opts->lock); \
108 return sprintf(page, "%d\n", qmult); \
109 } \
110 \
111 static ssize_t _f_##_opts_qmult_store(struct config_item *item, \
112 const char *page, size_t len)\
113 { \
114 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
115 u8 val; \
116 int ret; \
117 \
118 mutex_lock(&opts->lock); \
119 if (opts->refcnt) { \
120 ret = -EBUSY; \
121 goto out; \
122 } \
123 \
124 ret = kstrtou8(page, 0, &val); \
125 if (ret) \
126 goto out; \
127 \
128 gether_set_qmult(opts->net, val); \
129 ret = len; \
130out: \
131 mutex_unlock(&opts->lock); \
132 return ret; \
133 } \
134 \
135 CONFIGFS_ATTR(_f_##_opts_, qmult)
136
137#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_) \
138 static ssize_t _f_##_opts_ifname_show(struct config_item *item, \
139 char *page) \
140 { \
141 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
142 int ret; \
143 \
144 mutex_lock(&opts->lock); \
145 ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \
146 mutex_unlock(&opts->lock); \
147 \
148 return ret; \
149 } \
150 \
151 static ssize_t _f_##_opts_ifname_store(struct config_item *item, \
152 const char *page, size_t len)\
153 { \
154 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
155 int ret = -EBUSY; \
156 \
157 mutex_lock(&opts->lock); \
158 if (!opts->refcnt) \
159 ret = gether_set_ifname(opts->net, page, len); \
160 mutex_unlock(&opts->lock); \
161 return ret ?: len; \
162 } \
163 \
164 CONFIGFS_ATTR(_f_##_opts_, ifname)
165
166#define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \
167 static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\
168 char *page) \
169 { \
170 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
171 int ret; \
172 \
173 mutex_lock(&opts->lock); \
174 ret = sprintf(page, "%02x\n", opts->_n_); \
175 mutex_unlock(&opts->lock); \
176 \
177 return ret; \
178 } \
179 \
180 static ssize_t _f_##_opts_##_n_##_store(struct config_item *item,\
181 const char *page, \
182 size_t len) \
183 { \
184 struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
185 int ret = -EINVAL; \
186 u8 val; \
187 \
188 mutex_lock(&opts->lock); \
189 if (sscanf(page, "%02hhx", &val) > 0) { \
190 opts->_n_ = val; \
191 ret = len; \
192 } \
193 mutex_unlock(&opts->lock); \
194 \
195 return ret; \
196 } \
197 \
198 CONFIGFS_ATTR(_f_##_opts_, _n_)
199
200#endif /* __U_ETHER_CONFIGFS_H */
201

source code of linux/drivers/usb/gadget/function/u_ether_configfs.h