When sent data length 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 | 26 ++++++++++++++++++++++++-- 1 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 0492c20..89e49ce 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1558,8 +1558,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); @@ -1810,6 +1813,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. @@ -1829,9 +1839,21 @@ 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(MPS) 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