Signed-off-by: Andrzej Pietrasiewicz <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html