diff options
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 68 |
1 files changed, 23 insertions, 45 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6d8e533949eb..efb58f9f5aa9 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -347,6 +347,7 @@ struct fsg_operations { | |||
347 | /* Data shared by all the FSG instances. */ | 347 | /* Data shared by all the FSG instances. */ |
348 | struct fsg_common { | 348 | struct fsg_common { |
349 | struct usb_gadget *gadget; | 349 | struct usb_gadget *gadget; |
350 | struct usb_composite_dev *cdev; | ||
350 | struct fsg_dev *fsg, *new_fsg; | 351 | struct fsg_dev *fsg, *new_fsg; |
351 | wait_queue_head_t fsg_wait; | 352 | wait_queue_head_t fsg_wait; |
352 | 353 | ||
@@ -613,6 +614,11 @@ static int fsg_setup(struct usb_function *f, | |||
613 | if (!fsg_is_set(fsg->common)) | 614 | if (!fsg_is_set(fsg->common)) |
614 | return -EOPNOTSUPP; | 615 | return -EOPNOTSUPP; |
615 | 616 | ||
617 | ++fsg->common->ep0_req_tag; /* Record arrival of a new request */ | ||
618 | req->context = NULL; | ||
619 | req->length = 0; | ||
620 | dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); | ||
621 | |||
616 | switch (ctrl->bRequest) { | 622 | switch (ctrl->bRequest) { |
617 | 623 | ||
618 | case USB_BULK_RESET_REQUEST: | 624 | case USB_BULK_RESET_REQUEST: |
@@ -1584,37 +1590,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) | |||
1584 | return rc; | 1590 | return rc; |
1585 | } | 1591 | } |
1586 | 1592 | ||
1587 | static int pad_with_zeros(struct fsg_dev *fsg) | ||
1588 | { | ||
1589 | struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; | ||
1590 | u32 nkeep = bh->inreq->length; | ||
1591 | u32 nsend; | ||
1592 | int rc; | ||
1593 | |||
1594 | bh->state = BUF_STATE_EMPTY; /* For the first iteration */ | ||
1595 | fsg->common->usb_amount_left = nkeep + fsg->common->residue; | ||
1596 | while (fsg->common->usb_amount_left > 0) { | ||
1597 | |||
1598 | /* Wait for the next buffer to be free */ | ||
1599 | while (bh->state != BUF_STATE_EMPTY) { | ||
1600 | rc = sleep_thread(fsg->common); | ||
1601 | if (rc) | ||
1602 | return rc; | ||
1603 | } | ||
1604 | |||
1605 | nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); | ||
1606 | memset(bh->buf + nkeep, 0, nsend - nkeep); | ||
1607 | bh->inreq->length = nsend; | ||
1608 | bh->inreq->zero = 0; | ||
1609 | start_transfer(fsg, fsg->bulk_in, bh->inreq, | ||
1610 | &bh->inreq_busy, &bh->state); | ||
1611 | bh = fsg->common->next_buffhd_to_fill = bh->next; | ||
1612 | fsg->common->usb_amount_left -= nsend; | ||
1613 | nkeep = 0; | ||
1614 | } | ||
1615 | return 0; | ||
1616 | } | ||
1617 | |||
1618 | static int throw_away_data(struct fsg_common *common) | 1593 | static int throw_away_data(struct fsg_common *common) |
1619 | { | 1594 | { |
1620 | struct fsg_buffhd *bh; | 1595 | struct fsg_buffhd *bh; |
@@ -1702,6 +1677,10 @@ static int finish_reply(struct fsg_common *common) | |||
1702 | if (common->data_size == 0) { | 1677 | if (common->data_size == 0) { |
1703 | /* Nothing to send */ | 1678 | /* Nothing to send */ |
1704 | 1679 | ||
1680 | /* Don't know what to do if common->fsg is NULL */ | ||
1681 | } else if (!fsg_is_set(common)) { | ||
1682 | rc = -EIO; | ||
1683 | |||
1705 | /* If there's no residue, simply send the last buffer */ | 1684 | /* If there's no residue, simply send the last buffer */ |
1706 | } else if (common->residue == 0) { | 1685 | } else if (common->residue == 0) { |
1707 | bh->inreq->zero = 0; | 1686 | bh->inreq->zero = 0; |
@@ -1710,24 +1689,19 @@ static int finish_reply(struct fsg_common *common) | |||
1710 | common->next_buffhd_to_fill = bh->next; | 1689 | common->next_buffhd_to_fill = bh->next; |
1711 | 1690 | ||
1712 | /* | 1691 | /* |
1713 | * For Bulk-only, if we're allowed to stall then send the | 1692 | * For Bulk-only, mark the end of the data with a short |
1714 | * short packet and halt the bulk-in endpoint. If we can't | 1693 | * packet. If we are allowed to stall, halt the bulk-in |
1715 | * stall, pad out the remaining data with 0's. | 1694 | * endpoint. (Note: This violates the Bulk-Only Transport |
1695 | * specification, which requires us to pad the data if we | ||
1696 | * don't halt the endpoint. Presumably nobody will mind.) | ||
1716 | */ | 1697 | */ |
1717 | } else if (common->can_stall) { | 1698 | } else { |
1718 | bh->inreq->zero = 1; | 1699 | bh->inreq->zero = 1; |
1719 | if (!start_in_transfer(common, bh)) | 1700 | if (!start_in_transfer(common, bh)) |
1720 | /* Don't know what to do if | ||
1721 | * common->fsg is NULL */ | ||
1722 | rc = -EIO; | 1701 | rc = -EIO; |
1723 | common->next_buffhd_to_fill = bh->next; | 1702 | common->next_buffhd_to_fill = bh->next; |
1724 | if (common->fsg) | 1703 | if (common->can_stall) |
1725 | rc = halt_bulk_in_endpoint(common->fsg); | 1704 | rc = halt_bulk_in_endpoint(common->fsg); |
1726 | } else if (fsg_is_set(common)) { | ||
1727 | rc = pad_with_zeros(common->fsg); | ||
1728 | } else { | ||
1729 | /* Don't know what to do if common->fsg is NULL */ | ||
1730 | rc = -EIO; | ||
1731 | } | 1705 | } |
1732 | break; | 1706 | break; |
1733 | 1707 | ||
@@ -1910,7 +1884,7 @@ static int check_command(struct fsg_common *common, int cmnd_size, | |||
1910 | common->lun, lun); | 1884 | common->lun, lun); |
1911 | 1885 | ||
1912 | /* Check the LUN */ | 1886 | /* Check the LUN */ |
1913 | if (common->lun >= 0 && common->lun < common->nluns) { | 1887 | if (common->lun < common->nluns) { |
1914 | curlun = &common->luns[common->lun]; | 1888 | curlun = &common->luns[common->lun]; |
1915 | common->curlun = curlun; | 1889 | common->curlun = curlun; |
1916 | if (common->cmnd[0] != REQUEST_SENSE) { | 1890 | if (common->cmnd[0] != REQUEST_SENSE) { |
@@ -2468,7 +2442,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
2468 | struct fsg_dev *fsg = fsg_from_func(f); | 2442 | struct fsg_dev *fsg = fsg_from_func(f); |
2469 | fsg->common->new_fsg = fsg; | 2443 | fsg->common->new_fsg = fsg; |
2470 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); | 2444 | raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); |
2471 | return 0; | 2445 | return USB_GADGET_DELAYED_STATUS; |
2472 | } | 2446 | } |
2473 | 2447 | ||
2474 | static void fsg_disable(struct usb_function *f) | 2448 | static void fsg_disable(struct usb_function *f) |
@@ -2604,6 +2578,8 @@ static void handle_exception(struct fsg_common *common) | |||
2604 | 2578 | ||
2605 | case FSG_STATE_CONFIG_CHANGE: | 2579 | case FSG_STATE_CONFIG_CHANGE: |
2606 | do_set_interface(common, common->new_fsg); | 2580 | do_set_interface(common, common->new_fsg); |
2581 | if (common->new_fsg) | ||
2582 | usb_composite_setup_continue(common->cdev); | ||
2607 | break; | 2583 | break; |
2608 | 2584 | ||
2609 | case FSG_STATE_EXIT: | 2585 | case FSG_STATE_EXIT: |
@@ -2774,6 +2750,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2774 | common->gadget = gadget; | 2750 | common->gadget = gadget; |
2775 | common->ep0 = gadget->ep0; | 2751 | common->ep0 = gadget->ep0; |
2776 | common->ep0req = cdev->req; | 2752 | common->ep0req = cdev->req; |
2753 | common->cdev = cdev; | ||
2777 | 2754 | ||
2778 | /* Maybe allocate device-global string IDs, and patch descriptors */ | 2755 | /* Maybe allocate device-global string IDs, and patch descriptors */ |
2779 | if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { | 2756 | if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { |
@@ -2800,6 +2777,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, | |||
2800 | for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { | 2777 | for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { |
2801 | curlun->cdrom = !!lcfg->cdrom; | 2778 | curlun->cdrom = !!lcfg->cdrom; |
2802 | curlun->ro = lcfg->cdrom || lcfg->ro; | 2779 | curlun->ro = lcfg->cdrom || lcfg->ro; |
2780 | curlun->initially_ro = curlun->ro; | ||
2803 | curlun->removable = lcfg->removable; | 2781 | curlun->removable = lcfg->removable; |
2804 | curlun->dev.release = fsg_lun_release; | 2782 | curlun->dev.release = fsg_lun_release; |
2805 | curlun->dev.parent = &gadget->dev; | 2783 | curlun->dev.parent = &gadget->dev; |