Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/storage_common.c | 122 +++++++++++++++++++++++++++------- 1 files changed, 97 insertions(+), 25 deletions(-) diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index b5da774..8f3e731 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -153,6 +153,63 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun) return curlun->filp != NULL; } +CONFIGFS_ATTR_STRUCT(fsg_lun); + +#define FSG_LUN_ATTR_RW(_name) \ +static struct fsg_lun_attribute fsg_lun_##_name = \ + __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, fsg_lun_show_##_name, \ + fsg_lun_store_##_name) + +static ssize_t fsg_lun_show_ro(struct fsg_lun *curlun, char *buf); +static ssize_t fsg_lun_show_nofua(struct fsg_lun *curlun, char *buf); +static ssize_t fsg_lun_show_file(struct fsg_lun *curlun, char *buf); +static ssize_t fsg_lun_store_ro(struct fsg_lun *curlun, const char *buf, + size_t count); +static ssize_t fsg_lun_store_nofua(struct fsg_lun *curlun, const char *buf, + size_t count); +static ssize_t fsg_lun_store_file(struct fsg_lun *curlun, const char *buf, + size_t count); +static ssize_t fsg_lun_show_removable(struct fsg_lun *curlun, char *buf); +static ssize_t fsg_lun_store_removable(struct fsg_lun *curlun, const char *buf, + size_t count); + +FSG_LUN_ATTR_RW(ro); +FSG_LUN_ATTR_RW(nofua); +FSG_LUN_ATTR_RW(file); +FSG_LUN_ATTR_RW(removable); + +static struct configfs_attribute *fsg_lun_attrs[] = { + &fsg_lun_ro.attr, + &fsg_lun_nofua.attr, + &fsg_lun_file.attr, + &fsg_lun_removable.attr, + NULL, +}; + +static struct fsg_lun *to_fsg_lun(struct config_item *item) +{ + return item ? container_of(item, struct fsg_lun, item) : NULL; +} + +CONFIGFS_ATTR_OPS(fsg_lun); + +static void fsg_lun_item_release(struct config_item *item) +{ + kfree(to_fsg_lun(item)); +} + +static struct configfs_item_operations fsg_lun_ops = { + .show_attribute = fsg_lun_attr_show, + .store_attribute = fsg_lun_attr_store, + .release = fsg_lun_item_release, +}; + +static struct config_item_type fsg_lun_item_type = { + .ct_attrs = fsg_lun_attrs, + .ct_item_ops = &fsg_lun_ops, + .ct_owner = THIS_MODULE, +}; + /* Big enough to hold our biggest descriptor */ #define EP0_BUFSIZE 256 #define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ @@ -430,6 +487,7 @@ static void fsg_lun_close(struct fsg_lun *curlun) fput(curlun->filp); curlun->filp = NULL; } + configfs_undepend_item(curlun->item.ci_group->cg_subsys, &curlun->item); } @@ -445,6 +503,8 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) unsigned int blkbits; unsigned int blksize; + configfs_depend_item(curlun->item.ci_group->cg_subsys, &curlun->item); + /* R/W if we can, R/O if we must */ ro = curlun->initially_ro; if (!ro) { @@ -528,6 +588,9 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) out: fput(filp); + if (rc) + configfs_undepend_item(curlun->item.ci_group->cg_subsys, + &curlun->item); return rc; } @@ -569,29 +632,21 @@ static void store_cdrom_address(u8 *dest, int msf, u32 addr) /*-------------------------------------------------------------------------*/ -static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fsg_lun_show_ro(struct fsg_lun *curlun, char *buf) { - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) ? curlun->ro : curlun->initially_ro); } -static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fsg_lun_show_nofua(struct fsg_lun *curlun, char *buf) { - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - return sprintf(buf, "%u\n", curlun->nofua); } -static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fsg_lun_show_file(struct fsg_lun *curlun, char *buf) { - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); + struct rw_semaphore *filesem = curlun->filesem; char *p; ssize_t rc; @@ -614,13 +669,11 @@ static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, return rc; } - -static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fsg_lun_store_ro(struct fsg_lun *curlun, const char *buf, + size_t count) { ssize_t rc; - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); + struct rw_semaphore *filesem = curlun->filesem; unsigned ro; rc = kstrtouint(buf, 2, &ro); @@ -645,11 +698,9 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, return rc; } -static ssize_t fsg_store_nofua(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fsg_lun_store_nofua(struct fsg_lun *curlun, const char *buf, + size_t count) { - struct fsg_lun *curlun = fsg_lun_from_dev(dev); unsigned nofua; int ret; @@ -666,11 +717,10 @@ static ssize_t fsg_store_nofua(struct device *dev, return count; } -static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fsg_lun_store_file(struct fsg_lun *curlun, const char *buf, + size_t count) { - struct fsg_lun *curlun = fsg_lun_from_dev(dev); - struct rw_semaphore *filesem = dev_get_drvdata(dev); + struct rw_semaphore *filesem = curlun->filesem; int rc = 0; if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { @@ -697,3 +747,25 @@ static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, up_write(filesem); return (rc < 0 ? rc : count); } + +static ssize_t fsg_lun_show_removable(struct fsg_lun *curlun, char *buf) +{ + return sprintf(buf, "%d\n", curlun->removable); +} + +static ssize_t fsg_lun_store_removable(struct fsg_lun *curlun, const char *buf, + size_t count) +{ + if (fsg_lun_is_open(curlun)) { + LDBG(curlun, "media type change prevented\n"); + return -EBUSY; + } + + if (buf[0] != '0' && buf[0] != '1') + return -EINVAL; + + curlun->removable = buf[0] == '1'; + + return count; +} + -- 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