struct usb_composite_dev *cdev,
struct fsg_config *cfg)
{
- int i, rc;
+ struct usb_gadget *gadget = cdev->gadget;
+ struct fsg_lun **curlun_it;
+ struct fsg_lun_config *lcfg;
+ int nluns, i, rc;
+ char *pathbuf;
+
common = fsg_common_setup(common, !!common);
if (IS_ERR(common))
rc = fsg_common_set_nluns(common, cfg->nluns);
if (rc)
goto error_release;
+ curlun_it = common->luns;
+ nluns = cfg->nluns;
+ for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun_it, ++lcfg) {
+ struct fsg_lun *curlun;
+
+ curlun = kzalloc(sizeof(*curlun), GFP_KERNEL);
+ if (!curlun) {
+ rc = -ENOMEM;
+ common->nluns = i;
+ goto error_release;
+ }
+ *curlun_it = curlun;
+
+ curlun->name = kzalloc(MAX_LUN_NAME_LEN, GFP_KERNEL);
+ if (!curlun->name) {
+ rc = -ENOMEM;
+ common->nluns = i;
+ goto error_release;
+ }
+ curlun->cdrom = !!lcfg->cdrom;
+ curlun->ro = lcfg->cdrom || lcfg->ro;
+ curlun->initially_ro = curlun->ro;
+ curlun->removable = lcfg->removable;
+ curlun->dev.release = fsg_lun_release;
+ curlun->dev.parent = &gadget->dev;
+ /* curlun->dev.driver = &fsg_driver.driver; XXX */
+ dev_set_drvdata(&curlun->dev, &common->filesem);
+ dev_set_name(&curlun->dev, "lun%d", i);
+ strlcpy(curlun->name, dev_name(&curlun->dev), MAX_LUN_NAME_LEN);
+
+ rc = device_register(&curlun->dev);
+ if (rc) {
+ INFO(common, "failed to register LUN%d: %d\n", i, rc);
+ common->nluns = i;
+ put_device(&curlun->dev);
+ kfree(curlun);
+ goto error_release;
+ }
+
+ rc = device_create_file(&curlun->dev,
+ curlun->cdrom
+ ? &dev_attr_ro_cdrom
+ : &dev_attr_ro);
+ if (rc)
+ goto error_luns;
+ rc = device_create_file(&curlun->dev,
+ curlun->removable
+ ? &dev_attr_file
+ : &dev_attr_file_nonremovable);
+ if (rc)
+ goto error_luns;
+ rc = device_create_file(&curlun->dev, &dev_attr_nofua);
+ if (rc)
+ goto error_luns;
+
+ if (lcfg->filename) {
+ rc = fsg_lun_open(curlun, lcfg->filename);
+ if (rc)
+ goto error_luns;
+ } else if (!curlun->removable) {
+ ERROR(common, "no file given for LUN%d\n", i);
+ rc = -EINVAL;
+ goto error_luns;
+ }
+ }
- rc = fsg_common_create_luns(common, cfg);
- if (rc)
- goto error_release;
/* Prepare inquiryString */
i = get_default_bcdDevice();
: "File-Stor Gadget"),
i);
+
/* Tell the thread to start working */
common->thread_task =
kthread_create(fsg_main_thread, common, "file-storage");
INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
INFO(common, "Number of LUNs=%d\n", common->nluns);
+ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
+ for (i = 0, nluns = common->nluns, curlun_it = common->luns;
+ i < nluns;
+ ++curlun_it, ++i) {
+ struct fsg_lun *curlun = *curlun_it;
+ char *p = "(no medium)";
+ if (fsg_lun_is_open(curlun)) {
+ p = "(error)";
+ if (pathbuf) {
+ p = d_path(&curlun->filp->f_path,
+ pathbuf, PATH_MAX);
+ if (IS_ERR(p))
+ p = "(error)";
+ }
+ }
+ LINFO(curlun, "LUN: %s%s%sfile: %s\n",
+ curlun->removable ? "removable " : "",
+ curlun->ro ? "read only " : "",
+ curlun->cdrom ? "CD-ROM " : "",
+ p);
+ }
+ kfree(pathbuf);
+
DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task));
wake_up_process(common->thread_task);
return common;
+error_luns:
+ common->nluns = i + 1;
error_release:
common->state = FSG_STATE_TERMINATED; /* The thread is dead */
/* Call fsg_common_release() directly, ref might be not initialised. */