diff options
| -rw-r--r-- | drivers/usb/gadget/file_storage.c | 129 | ||||
| -rw-r--r-- | drivers/usb/gadget/storage_common.c | 116 |
2 files changed, 128 insertions, 117 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index ee712a5715e7..7998402b1840 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
| @@ -278,18 +278,14 @@ static char fsg_string_serial[13]; | |||
| 278 | static const char fsg_string_config[] = "Self-powered"; | 278 | static const char fsg_string_config[] = "Self-powered"; |
| 279 | static const char fsg_string_interface[] = "Mass Storage"; | 279 | static const char fsg_string_interface[] = "Mass Storage"; |
| 280 | 280 | ||
| 281 | |||
| 282 | #include "storage_common.c" | ||
| 283 | |||
| 284 | |||
| 281 | MODULE_DESCRIPTION(DRIVER_DESC); | 285 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 282 | MODULE_AUTHOR("Alan Stern"); | 286 | MODULE_AUTHOR("Alan Stern"); |
| 283 | MODULE_LICENSE("Dual BSD/GPL"); | 287 | MODULE_LICENSE("Dual BSD/GPL"); |
| 284 | 288 | ||
| 285 | /* Thanks to NetChip Technologies for donating this product ID. | ||
| 286 | * | ||
| 287 | * DO NOT REUSE THESE IDs with any other driver!! Ever!! | ||
| 288 | * Instead: allocate your own, using normal USB-IF procedures. */ | ||
| 289 | #define FSG_VENDOR_ID 0x0525 // NetChip | ||
| 290 | #define FSG_PRODUCT_ID 0xa4a5 // Linux-USB File-backed Storage Gadget | ||
| 291 | |||
| 292 | |||
| 293 | /* | 289 | /* |
| 294 | * This driver assumes self-powered hardware and has no way for users to | 290 | * This driver assumes self-powered hardware and has no way for users to |
| 295 | * trigger remote wakeup. It uses autoconfiguration to select endpoints | 291 | * trigger remote wakeup. It uses autoconfiguration to select endpoints |
| @@ -302,8 +298,6 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
| 302 | 298 | ||
| 303 | /* Encapsulate the module parameter settings */ | 299 | /* Encapsulate the module parameter settings */ |
| 304 | 300 | ||
| 305 | #define FSG_MAX_LUNS 8 | ||
| 306 | |||
| 307 | static struct { | 301 | static struct { |
| 308 | char *file[FSG_MAX_LUNS]; | 302 | char *file[FSG_MAX_LUNS]; |
| 309 | int ro[FSG_MAX_LUNS]; | 303 | int ro[FSG_MAX_LUNS]; |
| @@ -410,10 +404,6 @@ MODULE_PARM_DESC(buflen, "I/O buffer size"); | |||
| 410 | 404 | ||
| 411 | /*-------------------------------------------------------------------------*/ | 405 | /*-------------------------------------------------------------------------*/ |
| 412 | 406 | ||
| 413 | #include "storage_common.c" | ||
| 414 | |||
| 415 | /*-------------------------------------------------------------------------*/ | ||
| 416 | |||
| 417 | 407 | ||
| 418 | struct fsg_dev { | 408 | struct fsg_dev { |
| 419 | /* lock protects: state, all the req_busy's, and cbbuf_cmnd */ | 409 | /* lock protects: state, all the req_busy's, and cbbuf_cmnd */ |
| @@ -3134,107 +3124,10 @@ static int fsg_main_thread(void *fsg_) | |||
| 3134 | 3124 | ||
| 3135 | /*-------------------------------------------------------------------------*/ | 3125 | /*-------------------------------------------------------------------------*/ |
| 3136 | 3126 | ||
| 3137 | static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 3138 | { | ||
| 3139 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
| 3140 | |||
| 3141 | return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) | ||
| 3142 | ? curlun->ro | ||
| 3143 | : curlun->initially_ro); | ||
| 3144 | } | ||
| 3145 | |||
| 3146 | static ssize_t show_file(struct device *dev, struct device_attribute *attr, | ||
| 3147 | char *buf) | ||
| 3148 | { | ||
| 3149 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
| 3150 | struct fsg_dev *fsg = dev_get_drvdata(dev); | ||
| 3151 | char *p; | ||
| 3152 | ssize_t rc; | ||
| 3153 | |||
| 3154 | down_read(&fsg->filesem); | ||
| 3155 | if (fsg_lun_is_open(curlun)) { // Get the complete pathname | ||
| 3156 | p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1); | ||
| 3157 | if (IS_ERR(p)) | ||
| 3158 | rc = PTR_ERR(p); | ||
| 3159 | else { | ||
| 3160 | rc = strlen(p); | ||
| 3161 | memmove(buf, p, rc); | ||
| 3162 | buf[rc] = '\n'; // Add a newline | ||
| 3163 | buf[++rc] = 0; | ||
| 3164 | } | ||
| 3165 | } else { // No file, return 0 bytes | ||
| 3166 | *buf = 0; | ||
| 3167 | rc = 0; | ||
| 3168 | } | ||
| 3169 | up_read(&fsg->filesem); | ||
| 3170 | return rc; | ||
| 3171 | } | ||
| 3172 | |||
| 3173 | |||
| 3174 | static ssize_t store_ro(struct device *dev, struct device_attribute *attr, | ||
| 3175 | const char *buf, size_t count) | ||
| 3176 | { | ||
| 3177 | ssize_t rc = count; | ||
| 3178 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
| 3179 | struct fsg_dev *fsg = dev_get_drvdata(dev); | ||
| 3180 | int i; | ||
| 3181 | |||
| 3182 | if (sscanf(buf, "%d", &i) != 1) | ||
| 3183 | return -EINVAL; | ||
| 3184 | |||
| 3185 | /* Allow the write-enable status to change only while the backing file | ||
| 3186 | * is closed. */ | ||
| 3187 | down_read(&fsg->filesem); | ||
| 3188 | if (fsg_lun_is_open(curlun)) { | ||
| 3189 | LDBG(curlun, "read-only status change prevented\n"); | ||
| 3190 | rc = -EBUSY; | ||
| 3191 | } else { | ||
| 3192 | curlun->ro = !!i; | ||
| 3193 | curlun->initially_ro = !!i; | ||
| 3194 | LDBG(curlun, "read-only status set to %d\n", curlun->ro); | ||
| 3195 | } | ||
| 3196 | up_read(&fsg->filesem); | ||
| 3197 | return rc; | ||
| 3198 | } | ||
| 3199 | |||
| 3200 | static ssize_t store_file(struct device *dev, struct device_attribute *attr, | ||
| 3201 | const char *buf, size_t count) | ||
| 3202 | { | ||
| 3203 | struct fsg_lun *curlun = fsg_lun_from_dev(dev); | ||
| 3204 | struct fsg_dev *fsg = dev_get_drvdata(dev); | ||
| 3205 | int rc = 0; | ||
| 3206 | |||
| 3207 | if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { | ||
| 3208 | LDBG(curlun, "eject attempt prevented\n"); | ||
| 3209 | return -EBUSY; // "Door is locked" | ||
| 3210 | } | ||
| 3211 | |||
| 3212 | /* Remove a trailing newline */ | ||
| 3213 | if (count > 0 && buf[count-1] == '\n') | ||
| 3214 | ((char *) buf)[count-1] = 0; // Ugh! | ||
| 3215 | |||
| 3216 | /* Eject current medium */ | ||
| 3217 | down_write(&fsg->filesem); | ||
| 3218 | if (fsg_lun_is_open(curlun)) { | ||
| 3219 | fsg_lun_close(curlun); | ||
| 3220 | curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | /* Load new medium */ | ||
| 3224 | if (count > 0 && buf[0]) { | ||
| 3225 | rc = fsg_lun_open(curlun, buf); | ||
| 3226 | if (rc == 0) | ||
| 3227 | curlun->unit_attention_data = | ||
| 3228 | SS_NOT_READY_TO_READY_TRANSITION; | ||
| 3229 | } | ||
| 3230 | up_write(&fsg->filesem); | ||
| 3231 | return (rc < 0 ? rc : count); | ||
| 3232 | } | ||
| 3233 | |||
| 3234 | 3127 | ||
| 3235 | /* The write permissions and store_xxx pointers are set in fsg_bind() */ | 3128 | /* The write permissions and store_xxx pointers are set in fsg_bind() */ |
| 3236 | static DEVICE_ATTR(ro, 0444, show_ro, NULL); | 3129 | static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); |
| 3237 | static DEVICE_ATTR(file, 0444, show_file, NULL); | 3130 | static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); |
| 3238 | 3131 | ||
| 3239 | 3132 | ||
| 3240 | /*-------------------------------------------------------------------------*/ | 3133 | /*-------------------------------------------------------------------------*/ |
| @@ -3249,7 +3142,9 @@ static void fsg_release(struct kref *ref) | |||
| 3249 | 3142 | ||
| 3250 | static void lun_release(struct device *dev) | 3143 | static void lun_release(struct device *dev) |
| 3251 | { | 3144 | { |
| 3252 | struct fsg_dev *fsg = dev_get_drvdata(dev); | 3145 | struct rw_semaphore *filesem = dev_get_drvdata(dev); |
| 3146 | struct fsg_dev *fsg = | ||
| 3147 | container_of(filesem, struct fsg_dev, filesem); | ||
| 3253 | 3148 | ||
| 3254 | kref_put(&fsg->ref, fsg_release); | 3149 | kref_put(&fsg->ref, fsg_release); |
| 3255 | } | 3150 | } |
| @@ -3408,10 +3303,10 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
| 3408 | 3303 | ||
| 3409 | if (mod_data.removable) { // Enable the store_xxx attributes | 3304 | if (mod_data.removable) { // Enable the store_xxx attributes |
| 3410 | dev_attr_file.attr.mode = 0644; | 3305 | dev_attr_file.attr.mode = 0644; |
| 3411 | dev_attr_file.store = store_file; | 3306 | dev_attr_file.store = fsg_store_file; |
| 3412 | if (!mod_data.cdrom) { | 3307 | if (!mod_data.cdrom) { |
| 3413 | dev_attr_ro.attr.mode = 0644; | 3308 | dev_attr_ro.attr.mode = 0644; |
| 3414 | dev_attr_ro.store = store_ro; | 3309 | dev_attr_ro.store = fsg_store_ro; |
| 3415 | } | 3310 | } |
