From aa83c6adf753cc46e7898605ceb33dfa98eb63fa Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 23 May 2013 10:32:02 +0200 Subject: [PATCH] usb: gadget: add helpers for configfs support for USB Ethernet 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 Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- 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 697262e2a575..47a5724211cd 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -24,6 +24,7 @@ #include #include "u_ether.h" +#include "u_ether_configfs.h" #include "u_ncm.h" /* @@ -1298,138 +1299,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 000000000000..bcbd30146cfd --- /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 + * + * 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 */ -- GitLab