When sent data lenght is equal to maximum packet size (MPS = 64B for EP0), then a ZLP packet shall be sent to indicate end of the transfer to a USB host. Tested with: - DFU gadget (various size of the sent data - also packet = MPS) - Ethernet gadget (CDC and RNDIS) - Multi Function Gadget (g_multi) HW: - Samsung's C210 Universal rev.0 Signed-off-by: Lukasz Majewski <l.majewski@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- drivers/usb/gadget/s3c-hsotg.c | 25 +++++++++++++++++++++++-- 1 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 80f39c8..146636e 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1586,8 +1586,11 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, } if (epnum == 0) { + /* Condition req->complete != s3c_hsotg_complete_setup says: */ + /* send ZLP when we have an asynchronous request from gadget */ if (!was_setup && req->complete != s3c_hsotg_complete_setup) s3c_hsotg_send_zlp(hsotg, hs_req); + } s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, result); @@ -1838,6 +1841,13 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, return; } + /* Finish ZLP handling for IN EP0 transactions */ + if (hsotg->eps[0].sent_zlp) { + dev_dbg(hsotg->dev, "zlp packet received\n"); + s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); + return; + } + /* Calculate the size of the transfer by checking how much is left * in the endpoint size register and then working it out from * the amount we loaded for the transfer. @@ -1857,9 +1867,20 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, __func__, hs_req->req.actual, size_done); hs_req->req.actual = size_done; + dev_dbg(hsotg->dev, "req->length:%d req->actual:%d\n", + hs_req->req.length, hs_req->req.actual); - /* if we did all of the transfer, and there is more data left - * around, then try restarting the rest of the request */ + /* Check if dealing with Maximum Packet Size IN transfer (EP0) */ + /* When req.lenght == ep.maxpacket then send IN ZLP packet */ + /* to inform host that no more data is available */ + if (hs_req->req.length == hs_req->req.actual && hs_ep->index == 0 + && hs_req->req.length == hs_ep->ep.maxpacket) { + + dev_dbg(hsotg->dev, "ep0 zlp IN packet sent\n"); + s3c_hsotg_send_zlp(hsotg, hs_req); + + return; + } if (!size_left && hs_req->req.actual < hs_req->req.length) { dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html