diff options
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 267 | ||||
-rw-r--r-- | drivers/usb/gadget/mass_storage.c | 7 |
2 files changed, 178 insertions, 96 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 5fc01c04af05..e7c9f0ce86b6 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -253,51 +253,6 @@ static const char fsg_string_interface[] = "Mass Storage"; | |||
253 | /*-------------------------------------------------------------------------*/ | 253 | /*-------------------------------------------------------------------------*/ |
254 | 254 | ||
255 | 255 | ||
256 | /* Encapsulate the module parameter settings */ | ||
257 | |||
258 | static struct { | ||
259 | char *file[FSG_MAX_LUNS]; | ||
260 | int ro[FSG_MAX_LUNS]; | ||
261 | unsigned int num_filenames; | ||
262 | unsigned int num_ros; | ||
263 | unsigned int nluns; | ||
264 | |||
265 | int removable; | ||
266 | int can_stall; | ||
267 | int cdrom; | ||
268 | |||
269 | unsigned short release; | ||
270 | } mod_data = { // Default values | ||
271 | .removable = 0, | ||
272 | .can_stall = 1, | ||
273 | .cdrom = 0, | ||
274 | .release = 0xffff, | ||
275 | }; | ||
276 | |||
277 | |||
278 | module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames, | ||
279 | S_IRUGO); | ||
280 | MODULE_PARM_DESC(file, "names of backing files or devices"); | ||
281 | |||
282 | module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); | ||
283 | MODULE_PARM_DESC(ro, "true to force read-only"); | ||
284 | |||
285 | module_param_named(luns, mod_data.nluns, uint, S_IRUGO); | ||
286 | MODULE_PARM_DESC(luns, "number of LUNs"); | ||
287 | |||
288 | module_param_named(removable, mod_data.removable, bool, S_IRUGO); | ||
289 | MODULE_PARM_DESC(removable, "true to simulate removable media"); | ||
290 | |||
291 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | ||
292 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | ||
293 | |||
294 | module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); | ||
295 | MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); | ||
296 | |||
297 | |||
298 | /*-------------------------------------------------------------------------*/ | ||
299 | |||
300 | |||
301 | /* Data shared by all the FSG instances. */ | 256 | /* Data shared by all the FSG instances. */ |
302 | struct fsg_common { | 257 | struct fsg_common { |
303 | struct usb_gadget *gadget; | 258 | struct usb_gadget *gadget; |
@@ -317,12 +272,34 @@ struct fsg_common { | |||
317 | struct fsg_lun *luns; | 272 | struct fsg_lun *luns; |
318 | struct fsg_lun *curlun; | 273 | struct fsg_lun *curlun; |
319 | 274 | ||
275 | unsigned int can_stall:1; | ||
320 | unsigned int free_storage_on_release:1; | 276 | unsigned int free_storage_on_release:1; |
321 | 277 | ||
278 | /* Vendor (8 chars), product (16 chars), release (4 | ||
279 | * hexadecimal digits) and NUL byte */ | ||
280 | char inquiry_string[8 + 16 + 4 + 1]; | ||
281 | |||
322 | struct kref ref; | 282 | struct kref ref; |
323 | }; | 283 | }; |
324 | 284 | ||
325 | 285 | ||
286 | struct fsg_config { | ||
287 | unsigned nluns; | ||
288 | struct fsg_lun_config { | ||
289 | const char *filename; | ||
290 | char ro; | ||
291 | char removable; | ||
292 | char cdrom; | ||
293 | } luns[FSG_MAX_LUNS]; | ||
294 | |||
295 | const char *vendor_name; /* 8 characters or less */ | ||
296 | const char *product_name; /* 16 characters or less */ | ||
297 | u16 release; | ||
298 | |||
299 | char can_stall; | ||
300 | }; | ||
301 | |||
302 | |||
326 | struct fsg_dev { | 303 | struct fsg_dev { |
327 | struct usb_function function; | 304 | struct usb_function function; |
328 | struct usb_composite_dev*cdev; | 305 | struct usb_composite_dev*cdev; |
@@ -351,6 +328,7 @@ struct fsg_dev { | |||
351 | unsigned int phase_error : 1; | 328 | unsigned int phase_error : 1; |
352 | unsigned int short_packet_received : 1; | 329 | unsigned int short_packet_received : 1; |
353 | unsigned int bad_lun_okay : 1; | 330 | unsigned int bad_lun_okay : 1; |
331 | unsigned int can_stall : 1; | ||
354 | 332 | ||
355 | unsigned long atomic_bitflags; | 333 | unsigned long atomic_bitflags; |
356 | #define REGISTERED 0 | 334 | #define REGISTERED 0 |
@@ -1065,13 +1043,10 @@ static int do_verify(struct fsg_dev *fsg) | |||
1065 | 1043 | ||
1066 | static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) | 1044 | static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) |
1067 | { | 1045 | { |
1046 | struct fsg_lun *curlun = fsg->common->curlun; | ||
1068 | u8 *buf = (u8 *) bh->buf; | 1047 | u8 *buf = (u8 *) bh->buf; |
1069 | 1048 | ||
1070 | static char vendor_id[] = "Linux "; | 1049 | if (!curlun) { /* Unsupported LUNs are okay */ |
1071 | static char product_disk_id[] = "File-Stor Gadget"; | ||
1072 | static char product_cdrom_id[] = "File-CD Gadget "; | ||
1073 | |||
1074 | if (!fsg->common->curlun) { // Unsupported LUNs are okay | ||
1075 | fsg->bad_lun_okay = 1; | 1050 | fsg->bad_lun_okay = 1; |
1076 | memset(buf, 0, 36); | 1051 | memset(buf, 0, 36); |
1077 | buf[0] = 0x7f; // Unsupported, no device-type | 1052 | buf[0] = 0x7f; // Unsupported, no device-type |
@@ -1079,18 +1054,16 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
1079 | return 36; | 1054 | return 36; |
1080 | } | 1055 | } |
1081 | 1056 | ||
1082 | memset(buf, 0, 8); | 1057 | buf[0] = curlun->cdrom ? TYPE_CDROM : TYPE_DISK; |
1083 | buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK); | 1058 | buf[1] = curlun->removable ? 0x80 : 0; |
1084 | if (mod_data.removable) | ||
1085 | buf[1] = 0x80; | ||
1086 | buf[2] = 2; // ANSI SCSI level 2 | 1059 | buf[2] = 2; // ANSI SCSI level 2 |
1087 | buf[3] = 2; // SCSI-2 INQUIRY data format | 1060 | buf[3] = 2; // SCSI-2 INQUIRY data format |
1088 | buf[4] = 31; // Additional length | 1061 | buf[4] = 31; // Additional length |
1089 | // No special options | 1062 | buf[5] = 0; // No special options |
1090 | sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, | 1063 | buf[6] = 0; |
1091 | (mod_data.cdrom ? product_cdrom_id : | 1064 | buf[7] = 0; |
1092 | product_disk_id), | 1065 | memcpy(buf + 8, fsg->common->inquiry_string, |
1093 | mod_data.release); | 1066 | sizeof fsg->common->inquiry_string); |
1094 | return 36; | 1067 | return 36; |
1095 | } | 1068 | } |
1096 | 1069 | ||
@@ -1303,7 +1276,9 @@ static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
1303 | 1276 | ||
1304 | static int do_start_stop(struct fsg_dev *fsg) | 1277 | static int do_start_stop(struct fsg_dev *fsg) |
1305 | { | 1278 | { |
1306 | if (!mod_data.removable) { | 1279 | if (!fsg->common->curlun) { |
1280 | return -EINVAL; | ||
1281 | } else if (!fsg->common->curlun->removable) { | ||
1307 | fsg->common->curlun->sense_data = SS_INVALID_COMMAND; | 1282 | fsg->common->curlun->sense_data = SS_INVALID_COMMAND; |
1308 | return -EINVAL; | 1283 | return -EINVAL; |
1309 | } | 1284 | } |
@@ -1316,8 +1291,10 @@ static int do_prevent_allow(struct fsg_dev *fsg) | |||
1316 | struct fsg_lun *curlun = fsg->common->curlun; | 1291 | struct fsg_lun *curlun = fsg->common->curlun; |
1317 | int prevent; | 1292 | int prevent; |
1318 | 1293 | ||
1319 | if (!mod_data.removable) { | 1294 | if (!fsg->common->curlun) { |
1320 | curlun->sense_data = SS_INVALID_COMMAND; | 1295 | return -EINVAL; |
1296 | } else if (!fsg->common->curlun->removable) { | ||
1297 | fsg->common->curlun->sense_data = SS_INVALID_COMMAND; | ||
1321 | return -EINVAL; | 1298 | return -EINVAL; |
1322 | } | 1299 | } |
1323 | 1300 | ||
@@ -1505,7 +1482,7 @@ static int finish_reply(struct fsg_dev *fsg) | |||
1505 | * try to send or receive any data. So stall both bulk pipes | 1482 | * try to send or receive any data. So stall both bulk pipes |
1506 | * if we can and wait for a reset. */ | 1483 | * if we can and wait for a reset. */ |
1507 | case DATA_DIR_UNKNOWN: | 1484 | case DATA_DIR_UNKNOWN: |
1508 | if (mod_data.can_stall) { | 1485 | if (fsg->can_stall) { |
1509 | fsg_set_halt(fsg, fsg->bulk_out); | 1486 | fsg_set_halt(fsg, fsg->bulk_out); |
1510 | rc = halt_bulk_in_endpoint(fsg); | 1487 | rc = halt_bulk_in_endpoint(fsg); |
1511 | } | 1488 | } |
@@ -1526,7 +1503,7 @@ static int finish_reply(struct fsg_dev *fsg) | |||
1526 | /* For Bulk-only, if we're allowed to stall then send the | 1503 | /* For Bulk-only, if we're allowed to stall then send the |
1527 | * short packet and halt the bulk-in endpoint. If we can't | 1504 | * short packet and halt the bulk-in endpoint. If we can't |
1528 | * stall, pad out the remaining data with 0's. */ | 1505 | * stall, pad out the remaining data with 0's. */ |
1529 | } else if (mod_data.can_stall) { | 1506 | } else if (fsg->can_stall) { |
1530 | bh->inreq->zero = 1; | 1507 | bh->inreq->zero = 1; |
1531 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | 1508 | start_transfer(fsg, fsg->bulk_in, bh->inreq, |
1532 | &bh->inreq_busy, &bh->state); | 1509 | &bh->inreq_busy, &bh->state); |
@@ -1556,7 +1533,7 @@ static int finish_reply(struct fsg_dev *fsg) | |||
1556 | * STALL. Not realizing the endpoint was halted, it wouldn't | 1533 | * STALL. Not realizing the endpoint was halted, it wouldn't |
1557 | * clear the halt -- leading to problems later on. */ | 1534 | * clear the halt -- leading to problems later on. */ |
1558 | #if 0 | 1535 | #if 0 |
1559 | else if (mod_data.can_stall) { | 1536 | else if (fsg->can_stall) { |
1560 | fsg_set_halt(fsg, fsg->bulk_out); | 1537 | fsg_set_halt(fsg, fsg->bulk_out); |
1561 | raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); | 1538 | raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); |
1562 | rc = -EINTR; | 1539 | rc = -EINTR; |
@@ -1866,7 +1843,7 @@ static int do_scsi_command(struct fsg_dev *fsg) | |||
1866 | break; | 1843 | break; |
1867 | 1844 | ||
1868 | case SC_READ_HEADER: | 1845 | case SC_READ_HEADER: |
1869 | if (!mod_data.cdrom) | 1846 | if (!fsg->common->curlun || !fsg->common->curlun->cdrom) |
1870 | goto unknown_cmnd; | 1847 | goto unknown_cmnd; |
1871 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]); | 1848 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]); |
1872 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | 1849 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, |
@@ -1876,7 +1853,7 @@ static int do_scsi_command(struct fsg_dev *fsg) | |||
1876 | break; | 1853 | break; |
1877 | 1854 | ||
1878 | case SC_READ_TOC: | 1855 | case SC_READ_TOC: |
1879 | if (!mod_data.cdrom) | 1856 | if (!fsg->common->curlun || !fsg->common->curlun->cdrom) |
1880 | goto unknown_cmnd; | 1857 | goto unknown_cmnd; |
1881 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]); | 1858 | fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->common->cmnd[7]); |
1882 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | 1859 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, |
@@ -2043,7 +2020,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2043 | 2020 | ||
2044 | /* We can do anything we want here, so let's stall the | 2021 | /* We can do anything we want here, so let's stall the |
2045 | * bulk pipes if we are allowed to. */ | 2022 | * bulk pipes if we are allowed to. */ |
2046 | if (mod_data.can_stall) { | 2023 | if (fsg->can_stall) { |
2047 | fsg_set_halt(fsg, fsg->bulk_out); | 2024 | fsg_set_halt(fsg, fsg->bulk_out); |
2048 | halt_bulk_in_endpoint(fsg); | 2025 | halt_bulk_in_endpoint(fsg); |
2049 | } | 2026 | } |
@@ -2499,18 +2476,18 @@ static inline void fsg_common_put(struct fsg_common *common) | |||
2499 | 2476 | ||
2500 | 2477 | ||
2501 | static struct fsg_common *fsg_common_init(struct fsg_common *common, | 2478 | static struct fsg_common *fsg_common_init(struct fsg_common *common, |
2502 | struct usb_composite_dev *cdev) | 2479 | struct usb_composite_dev *cdev, |
2480 | struct fsg_config *cfg) | ||
2503 | { | 2481 | { |
2504 | struct usb_gadget *gadget = cdev->gadget; | 2482 | struct usb_gadget *gadget = cdev->gadget; |
2505 | struct fsg_buffhd *bh; | 2483 | struct fsg_buffhd *bh; |
2506 | struct fsg_lun *curlun; | 2484 | struct fsg_lun *curlun; |
2485 | struct fsg_lun_config *lcfg; | ||
2507 | int nluns, i, rc; | 2486 | int nluns, i, rc; |
2508 | char *pathbuf; | 2487 | char *pathbuf; |
2509 | 2488 | ||
2510 | /* Find out how many LUNs there should be */ | 2489 | /* Find out how many LUNs there should be */ |
2511 | nluns = mod_data.nluns; | 2490 | nluns = cfg->nluns; |
2512 | if (nluns == 0) | ||
2513 | nluns = max(mod_data.num_filenames, 1u); | ||
2514 | if (nluns < 1 || nluns > FSG_MAX_LUNS) { | 2491 | if (nluns < 1 || nluns > FSG_MAX_LUNS) { |
2515 | dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns); | 2492 | dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns); |
2516 | return ERR_PTR(-EINVAL); | 2493 | return ERR_PTR(-EINVAL); |
@@ -2539,10 +2516,10 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2539 | 2516 | ||
2540 | init_rwsem(&common->filesem); | 2517 | init_rwsem(&common->filesem); |
2541 | 2518 | ||
2542 | for (i = 0; i < nluns; ++i, ++curlun) { | 2519 | for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { |
2543 | curlun->cdrom = !!mod_data.cdrom; | 2520 | curlun->cdrom = !!lcfg->cdrom; |
2544 | curlun->ro = mod_data.cdrom || mod_data.ro[i]; | 2521 | curlun->ro = lcfg->cdrom || lcfg->ro; |
2545 | curlun->removable = mod_data.removable; | 2522 | curlun->removable = lcfg->removable; |
2546 | curlun->dev.release = fsg_lun_release; | 2523 | curlun->dev.release = fsg_lun_release; |
2547 | curlun->dev.parent = &gadget->dev; | 2524 | curlun->dev.parent = &gadget->dev; |
2548 | /* curlun->dev.driver = &fsg_driver.driver; XXX */ | 2525 | /* curlun->dev.driver = &fsg_driver.driver; XXX */ |
@@ -2564,11 +2541,11 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2564 | if (rc) | 2541 | if (rc) |
2565 | goto error_luns; | 2542 | goto error_luns; |
2566 | 2543 | ||
2567 | if (mod_data.file[i] && *mod_data.file[i]) { | 2544 | if (lcfg->filename) { |
2568 | rc = fsg_lun_open(curlun, mod_data.file[i]); | 2545 | rc = fsg_lun_open(curlun, lcfg->filename); |
2569 | if (rc) | 2546 | if (rc) |
2570 | goto error_luns; | 2547 | goto error_luns; |
2571 | } else if (!mod_data.removable) { | 2548 | } else if (!curlun->removable) { |
2572 | ERROR(common, "no file given for LUN%d\n", i); | 2549 | ERROR(common, "no file given for LUN%d\n", i); |
2573 | rc = -EINVAL; | 2550 | rc = -EINVAL; |
2574 | goto error_luns; | 2551 | goto error_luns; |
@@ -2588,33 +2565,40 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2588 | bh->next = common->buffhds; | 2565 | bh->next = common->buffhds; |
2589 | 2566 | ||
2590 | 2567 | ||
2591 | /* Release */ | 2568 | /* Prepare inquiryString */ |
2592 | if (mod_data.release == 0xffff) { // Parameter wasn't set | 2569 | if (cfg->release != 0xffff) { |
2593 | int gcnum; | 2570 | i = cfg->release; |
2594 | 2571 | } else { | |
2595 | /* The sa1100 controller is not supported */ | 2572 | /* The sa1100 controller is not supported */ |
2596 | if (gadget_is_sa1100(gadget)) | 2573 | i = gadget_is_sa1100(gadget) |
2597 | gcnum = -1; | 2574 | ? -1 |
2598 | else | 2575 | : usb_gadget_controller_number(gadget); |
2599 | gcnum = usb_gadget_controller_number(gadget); | 2576 | if (i >= 0) { |
2600 | if (gcnum >= 0) | 2577 | i = 0x0300 + i; |
2601 | mod_data.release = 0x0300 + gcnum; | 2578 | } else { |
2602 | else { | ||
2603 | WARNING(common, "controller '%s' not recognized\n", | ||
2604 | gadget->name); | ||
2605 | WARNING(common, "controller '%s' not recognized\n", | 2579 | WARNING(common, "controller '%s' not recognized\n", |
2606 | gadget->name); | 2580 | gadget->name); |
2607 | mod_data.release = 0x0399; | 2581 | i = 0x0399; |
2608 | } | 2582 | } |
2609 | } | 2583 | } |
2584 | #define OR(x, y) ((x) ? (x) : (y)) | ||
2585 | snprintf(common->inquiry_string, sizeof common->inquiry_string, | ||
2586 | "%-8s%-16s%04x", | ||
2587 | OR(cfg->vendor_name, "Linux "), | ||
2588 | /* Assume product name dependent on the first LUN */ | ||
2589 | OR(cfg->product_name, common->luns->cdrom | ||
2590 | ? "File-Stor Gadget" | ||
2591 | : "File-CD Gadget "), | ||
2592 | i); | ||
2593 | #undef OR | ||
2610 | 2594 | ||
2611 | 2595 | ||
2612 | /* Some peripheral controllers are known not to be able to | 2596 | /* Some peripheral controllers are known not to be able to |
2613 | * halt bulk endpoints correctly. If one of them is present, | 2597 | * halt bulk endpoints correctly. If one of them is present, |
2614 | * disable stalls. | 2598 | * disable stalls. |
2615 | */ | 2599 | */ |
2616 | if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget)) | 2600 | common->can_stall = cfg->can_stall && |
2617 | mod_data.can_stall = 0; | 2601 | !(gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget)); |
2618 | 2602 | ||
2619 | 2603 | ||
2620 | kref_init(&common->ref); | 2604 | kref_init(&common->ref); |
@@ -2820,6 +2804,7 @@ static int fsg_add(struct usb_composite_dev *cdev, | |||
2820 | * from this function. So instead of incrementing counter now | 2804 | * from this function. So instead of incrementing counter now |
2821 | * and decrement in error recovery we increment it only when | 2805 | * and decrement in error recovery we increment it only when |
2822 | * call to usb_add_function() was successful. */ | 2806 | * call to usb_add_function() was successful. */ |
2807 | fsg->can_stall = common->can_stall; | ||
2823 | 2808 | ||
2824 | rc = usb_add_function(c, &fsg->function); | 2809 | rc = usb_add_function(c, &fsg->function); |
2825 | 2810 | ||
@@ -2830,3 +2815,95 @@ static int fsg_add(struct usb_composite_dev *cdev, | |||
2830 | 2815 | ||
2831 | return rc; | 2816 | return rc; |
2832 | } | 2817 | } |
2818 | |||
2819 | |||
2820 | |||
2821 | /************************* Module parameters *************************/ | ||
2822 | |||
2823 | |||
2824 | struct fsg_module_parameters { | ||
2825 | char *file[FSG_MAX_LUNS]; | ||
2826 | int ro[FSG_MAX_LUNS]; | ||
2827 | int removable[FSG_MAX_LUNS]; | ||
2828 | int cdrom[FSG_MAX_LUNS]; | ||
2829 | |||
2830 | unsigned int file_count, ro_count, removable_count, cdrom_count; | ||
2831 | unsigned int luns; /* nluns */ | ||
2832 | int stall; /* can_stall */ | ||
2833 | }; | ||
2834 | |||
2835 | |||
2836 | #define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ | ||
2837 | module_param_array_named(prefix ## name, params.name, type, \ | ||
2838 | &prefix ## params.name ## _count, \ | ||
2839 | S_IRUGO); \ | ||
2840 | MODULE_PARM_DESC(prefix ## name, desc) | ||
2841 | |||
2842 | #define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ | ||
2843 | module_param_named(prefix ## name, params.name, type, \ | ||
2844 | S_IRUGO); \ | ||
2845 | MODULE_PARM_DESC(prefix ## name, desc) | ||
2846 | |||
2847 | #define FSG_MODULE_PARAMETERS(prefix, params) \ | ||
2848 | _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ | ||
2849 | "names of backing files or devices"); \ | ||
2850 | _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ | ||
2851 | "true to force read-only"); \ | ||
2852 | _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ | ||
2853 | "true to simulate removable media"); \ | ||
2854 | _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ | ||
2855 | "true to simulate CD-ROM instead of disk"); \ | ||
2856 | _FSG_MODULE_PARAM(prefix, params, luns, uint, \ | ||
2857 | "number of LUNs"); \ | ||
2858 | _FSG_MODULE_PARAM(prefix, params, stall, bool, \ | ||
2859 | "false to prevent bulk stalls") | ||
2860 | |||
2861 | |||
2862 | static void | ||
2863 | fsg_config_from_params(struct fsg_config *cfg, | ||
2864 | const struct fsg_module_parameters *params) | ||
2865 | { | ||
2866 | struct fsg_lun_config *lun; | ||
2867 | unsigned i, nluns; | ||
2868 | |||
2869 | /* Configure LUNs */ | ||
2870 | nluns = cfg->nluns = !params->luns | ||
2871 | ? params->file_count ? params->file_count : 1 | ||
2872 | : params->luns; | ||
2873 | for (i = 0, lun = cfg->luns; | ||
2874 | i < FSG_MAX_LUNS && i < nluns; | ||
2875 | ++i, ++lun) { | ||
2876 | lun->ro = !!params->ro[i]; | ||
2877 | lun->cdrom = !!params->cdrom[i]; | ||
2878 | lun->removable = | ||
2879 | params->removable_count <= i || params->removable[i]; | ||
2880 | lun->filename = | ||
2881 | params->file_count > i && params->file[i][0] | ||
2882 | ? params->file[i] | ||
2883 | : 0; | ||
2884 | } | ||
2885 | |||
2886 | /* Let FSG use defaults */ | ||
2887 | cfg->vendor_name = 0; | ||
2888 | cfg->product_name = 0; | ||
2889 | cfg->release = 0xffff; | ||
2890 | |||
2891 | /* Finalise */ | ||
2892 | cfg->can_stall = params->stall; | ||
2893 | } | ||
2894 | |||
2895 | static inline struct fsg_common * | ||
2896 | fsg_common_from_params(struct fsg_common *common, | ||
2897 | struct usb_composite_dev *cdev, | ||
2898 | const struct fsg_module_parameters *params) | ||
2899 | __attribute__((unused)); | ||
2900 | static inline struct fsg_common * | ||
2901 | fsg_common_from_params(struct fsg_common *common, | ||
2902 | struct usb_composite_dev *cdev, | ||
2903 | const struct fsg_module_parameters *params) | ||
2904 | { | ||
2905 | struct fsg_config cfg; | ||
2906 | fsg_config_from_params(&cfg, params); | ||
2907 | return fsg_common_init(common, cdev, &cfg); | ||
2908 | } | ||
2909 | |||
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 27339f04bc1b..00396a36d011 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c | |||
@@ -127,6 +127,11 @@ static struct usb_gadget_strings *dev_strings[] = { | |||
127 | 127 | ||
128 | /****************************** Configurations ******************************/ | 128 | /****************************** Configurations ******************************/ |
129 | 129 | ||
130 | static struct fsg_module_parameters mod_data = { | ||
131 | .stall = 1 | ||
132 | }; | ||
133 | FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); | ||
134 | |||
130 | static int __init msg_do_config(struct usb_configuration *c) | 135 | static int __init msg_do_config(struct usb_configuration *c) |
131 | { | 136 | { |
132 | struct fsg_common *common; | 137 | struct fsg_common *common; |
@@ -137,7 +142,7 @@ static int __init msg_do_config(struct usb_configuration *c) | |||
137 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 142 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
138 | } | 143 | } |
139 | 144 | ||
140 | common = fsg_common_init(0, c->cdev); | 145 | common = fsg_common_from_params(0, c->cdev, &mod_data); |
141 | if (IS_ERR(common)) | 146 | if (IS_ERR(common)) |
142 | return PTR_ERR(common); | 147 | return PTR_ERR(common); |
143 | 148 | ||