All USB Ethernet functions will have very similar attributes in configfs. This patch provides helper definitions to ease writing the functions and reduce source code duplication. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/f_ncm.c | 139 ++------------------------- drivers/usb/gadget/u_ether_configfs.h | 164 +++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 128 deletions(-) create mode 100644 drivers/usb/gadget/u_ether_configfs.h diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index 795d702..eabf43d 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -24,6 +24,7 @@ #include <linux/usb/cdc.h> #include "u_ether.h" +#include "u_ether_configfs.h" #include "u_ncm.h" /* @@ -1288,138 +1289,20 @@ static inline struct f_ncm_opts *to_f_ncm_opts(struct config_item *item) func_inst.group); } -CONFIGFS_ATTR_STRUCT(f_ncm_opts); -CONFIGFS_ATTR_OPS(f_ncm_opts); +/* f_ncm_item_ops */ +USB_ETHERNET_CONFIGFS_ITEM(ncm); -static void ncm_attr_release(struct config_item *item) -{ - struct f_ncm_opts *opts = to_f_ncm_opts(item); - - usb_put_function_instance(&opts->func_inst); -} - -static struct configfs_item_operations ncm_item_ops = { - .release = ncm_attr_release, - .show_attribute = f_ncm_opts_attr_show, - .store_attribute = f_ncm_opts_attr_store, -}; - -static ssize_t ncm_opts_dev_addr_show(struct f_ncm_opts *opts, char *page) -{ - int result; - - mutex_lock(&opts->lock); - result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); - mutex_unlock(&opts->lock); - - return result; -} - -static ssize_t ncm_opts_dev_addr_store(struct f_ncm_opts *opts, - const char *page, size_t len) -{ - int ret; - - mutex_lock(&opts->lock); - if (opts->refcnt) { - mutex_unlock(&opts->lock); - return -EBUSY; - } - - ret = gether_set_dev_addr(opts->net, page); - mutex_unlock(&opts->lock); - if (!ret) - ret = len; - return ret; -} - -static struct f_ncm_opts_attribute f_ncm_opts_dev_addr = - __CONFIGFS_ATTR(dev_addr, S_IRUGO | S_IWUSR, ncm_opts_dev_addr_show, - ncm_opts_dev_addr_store); - -static ssize_t ncm_opts_host_addr_show(struct f_ncm_opts *opts, char *page) -{ - int result; - - mutex_lock(&opts->lock); - result = gether_get_host_addr(opts->net, page, PAGE_SIZE); - mutex_unlock(&opts->lock); - - return result; -} - -static ssize_t ncm_opts_host_addr_store(struct f_ncm_opts *opts, - const char *page, size_t len) -{ - int ret; +/* f_ncm_opts_dev_addr */ +USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ncm); - mutex_lock(&opts->lock); - if (opts->refcnt) { - mutex_unlock(&opts->lock); - return -EBUSY; - } - - ret = gether_set_host_addr(opts->net, page); - mutex_unlock(&opts->lock); - if (!ret) - ret = len; - return ret; -} - -static struct f_ncm_opts_attribute f_ncm_opts_host_addr = - __CONFIGFS_ATTR(host_addr, S_IRUGO | S_IWUSR, ncm_opts_host_addr_show, - ncm_opts_host_addr_store); - -static ssize_t ncm_opts_qmult_show(struct f_ncm_opts *opts, char *page) -{ - unsigned qmult; - - mutex_lock(&opts->lock); - qmult = gether_get_qmult(opts->net); - mutex_unlock(&opts->lock); - return sprintf(page, "%d", qmult); -} - -static ssize_t ncm_opts_qmult_store(struct f_ncm_opts *opts, - const char *page, size_t len) -{ - u8 val; - int ret; +/* f_ncm_opts_host_addr */ +USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ncm); - mutex_lock(&opts->lock); - if (opts->refcnt) { - ret = -EBUSY; - goto out; - } - - ret = kstrtou8(page, 0, &val); - if (ret) - goto out; - - gether_set_qmult(opts->net, val); - ret = len; -out: - mutex_unlock(&opts->lock); - return ret; -} - -static struct f_ncm_opts_attribute f_ncm_opts_qmult = - __CONFIGFS_ATTR(qmult, S_IRUGO | S_IWUSR, ncm_opts_qmult_show, - ncm_opts_qmult_store); - -static ssize_t ncm_opts_ifname_show(struct f_ncm_opts *opts, char *page) -{ - int ret; - - mutex_lock(&opts->lock); - ret = gether_get_ifname(opts->net, page, PAGE_SIZE); - mutex_unlock(&opts->lock); - - return ret; -} +/* f_ncm_opts_qmult */ +USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ncm); -static struct f_ncm_opts_attribute f_ncm_opts_ifname = - __CONFIGFS_ATTR_RO(ifname, ncm_opts_ifname_show); +/* f_ncm_opts_ifname */ +USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ncm); static struct configfs_attribute *ncm_attrs[] = { &f_ncm_opts_dev_addr.attr, diff --git a/drivers/usb/gadget/u_ether_configfs.h b/drivers/usb/gadget/u_ether_configfs.h new file mode 100644 index 0000000..bcbd301 --- /dev/null +++ b/drivers/usb/gadget/u_ether_configfs.h @@ -0,0 +1,164 @@ +/* + * u_ether_configfs.h + * + * Utility definitions for configfs support in USB Ethernet functions + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __U_ETHER_CONFIGFS_H +#define __U_ETHER_CONFIGFS_H + +#define USB_ETHERNET_CONFIGFS_ITEM(_f_) \ + CONFIGFS_ATTR_STRUCT(f_##_f_##_opts); \ + CONFIGFS_ATTR_OPS(f_##_f_##_opts); \ + \ + static void _f_##_attr_release(struct config_item *item) \ + { \ + struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ + \ + usb_put_function_instance(&opts->func_inst); \ + } \ + \ + static struct configfs_item_operations _f_##_item_ops = { \ + .release = _f_##_attr_release, \ + .show_attribute = f_##_f_##_opts_attr_show, \ + .store_attribute = f_##_f_##_opts_attr_store, \ + } + +#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_) \ + static ssize_t _f_##_opts_dev_addr_show(struct f_##_f_##_opts *opts, \ + char *page) \ + { \ + int result; \ + \ + mutex_lock(&opts->lock); \ + result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \ + mutex_unlock(&opts->lock); \ + \ + return result; \ + } \ + \ + static ssize_t _f_##_opts_dev_addr_store(struct f_##_f_##_opts *opts, \ + const char *page, size_t len)\ + { \ + int ret; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + mutex_unlock(&opts->lock); \ + return -EBUSY; \ + } \ + \ + ret = gether_set_dev_addr(opts->net, page); \ + mutex_unlock(&opts->lock); \ + if (!ret) \ + ret = len; \ + return ret; \ + } \ + \ + static struct f_##_f_##_opts_attribute f_##_f_##_opts_dev_addr = \ + __CONFIGFS_ATTR(dev_addr, S_IRUGO | S_IWUSR, \ + _f_##_opts_dev_addr_show, \ + _f_##_opts_dev_addr_store) + +#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_) \ + static ssize_t _f_##_opts_host_addr_show(struct f_##_f_##_opts *opts, \ + char *page) \ + { \ + int result; \ + \ + mutex_lock(&opts->lock); \ + result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \ + mutex_unlock(&opts->lock); \ + \ + return result; \ + } \ + \ + static ssize_t _f_##_opts_host_addr_store(struct f_##_f_##_opts *opts, \ + const char *page, size_t len)\ + { \ + int ret; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + mutex_unlock(&opts->lock); \ + return -EBUSY; \ + } \ + \ + ret = gether_set_host_addr(opts->net, page); \ + mutex_unlock(&opts->lock); \ + if (!ret) \ + ret = len; \ + return ret; \ + } \ + \ + static struct f_##_f_##_opts_attribute f_##_f_##_opts_host_addr = \ + __CONFIGFS_ATTR(host_addr, S_IRUGO | S_IWUSR, \ + _f_##_opts_host_addr_show, \ + _f_##_opts_host_addr_store) + +#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_) \ + static ssize_t _f_##_opts_qmult_show(struct f_##_f_##_opts *opts, \ + char *page) \ + { \ + unsigned qmult; \ + \ + mutex_lock(&opts->lock); \ + qmult = gether_get_qmult(opts->net); \ + mutex_unlock(&opts->lock); \ + return sprintf(page, "%d", qmult); \ + } \ + \ + static ssize_t _f_##_opts_qmult_store(struct f_##_f_##_opts *opts, \ + const char *page, size_t len)\ + { \ + u8 val; \ + int ret; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + ret = -EBUSY; \ + goto out; \ + } \ + \ + ret = kstrtou8(page, 0, &val); \ + if (ret) \ + goto out; \ + \ + gether_set_qmult(opts->net, val); \ + ret = len; \ +out: \ + mutex_unlock(&opts->lock); \ + return ret; \ + } \ + \ + static struct f_##_f_##_opts_attribute f_##_f_##_opts_qmult = \ + __CONFIGFS_ATTR(qmult, S_IRUGO | S_IWUSR, \ + _f_##_opts_qmult_show, \ + _f_##_opts_qmult_store) + +#define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_) \ + static ssize_t _f_##_opts_ifname_show(struct f_##_f_##_opts *opts, \ + char *page) \ + { \ + int ret; \ + \ + mutex_lock(&opts->lock); \ + ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \ + mutex_unlock(&opts->lock); \ + \ + return ret; \ + } \ + \ + static struct f_##_f_##_opts_attribute f_##_f_##_opts_ifname = \ + __CONFIGFS_ATTR_RO(ifname, _f_##_opts_ifname_show) + +#endif /* __U_ETHER_CONFIGFS_H */ -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html