[PATCH 4/9] USB:s3c-hsotg: Sending ZLP packet for IN EP0 transfers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux