Ejemplo n.º 1
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	u32			transferred;
	u32			status;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;

	r = next_request(&ep0->request_list);
	ur = &r->request;

	trb = 	(struct dwc3_trb*)dwc->ep0_trb;

	status = trb->trbsts;
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dev_dbg(dwc->dev, "Setup Pending received\n");

		if (r)
			dwc3_gadget_giveback(ep0, r, -ECONNRESET);

		return;
	}

	length = trb->length;

	if (dwc->ep0_bounced) {
		unsigned transfer_size = ur->length;
		unsigned maxp = ep0->endpoint.maxpacket;

		transfer_size += (maxp - (transfer_size % maxp));
		transferred = min_t(u32, ur->length,
				transfer_size - length);
		memcpy(ur->buf, dwc->ep0_bounce, transferred);
	} else {
		transferred = ur->length - length;
	}

	ur->actual += transferred;

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */
		dwc3_ep0_stall_and_restart(dwc);
	} else {
		/*
		 * handle the case where we have to send a zero packet. This
		 * seems to be case when req.length > maxpacket. Could it be?
		 */
		if (r)
			dwc3_gadget_giveback(ep0, r, 0);
	}
}
Ejemplo n.º 2
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	unsigned		maxp;
	unsigned		remaining_ur_length;
	void			*buf;
	u32			transferred = 0;
	u32			status;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
	trb = dwc->ep0_trb;
	trace_dwc3_complete_trb(ep0, trb);

	r = next_request(&ep0->pending_list);
	if (!r)
		return;

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dwc->setup_packet_pending = true;
		if (r)
			dwc3_gadget_giveback(ep0, r, -ECONNRESET);

		return;
	}

	ur = &r->request;
	buf = ur->buf;
	remaining_ur_length = ur->length;

	length = trb->size & DWC3_TRB_SIZE_MASK;
	maxp = ep0->endpoint.maxpacket;
	transferred = ur->length - length;
	ur->actual += transferred;

	if ((IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
	     ur->length && ur->zero) || dwc->ep0_bounced) {
		trb++;
		trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
		trace_dwc3_complete_trb(ep0, trb);
		ep0->trb_enqueue = 0;
		dwc->ep0_bounced = false;
	}

	if ((epnum & 1) && ur->actual < ur->length)
		dwc3_ep0_stall_and_restart(dwc);
	else
		dwc3_gadget_giveback(ep0, r, 0);
}
Ejemplo n.º 3
0
Archivo: ep0.c Proyecto: AllenWeb/linux
static void dwc3_ep0_complete_req(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r;
	struct dwc3_ep		*dep;

	dep = dwc->eps[0];

	if (!list_empty(&dep->request_list)) {
		r = next_request(&dep->request_list);

		dwc3_gadget_giveback(dep, r, 0);
	}

	if (dwc->test_mode) {
		int ret;

		ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
		if (ret < 0) {
			dev_dbg(dwc->dev, "Invalid Test #%d\n",
					dwc->test_mode_nr);
			dwc3_ep0_stall_and_restart(dwc);
		}
	}

	dwc->ep0state = EP0_SETUP_PHASE;
	dwc3_ep0_out_start(dwc);
}
Ejemplo n.º 4
0
static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
{
	struct dwc3_ep		*dep;

	/* reinitialize physical ep1 */
	dep = dwc->eps[1];
	dep->flags = DWC3_EP_ENABLED;

	/* stall is always issued on EP0 */
	dep = dwc->eps[0];
	__dwc3_gadget_ep_set_halt(dep, 1);

	dep->flags = DWC3_EP_ENABLED;
	dwc->delayed_status = false;

	if (!list_empty(&dep->request_list)) {
		struct dwc3_request	*req;

		req = next_request(&dep->request_list);
		dwc3_gadget_giveback(dep, req, -ECONNRESET);
	}

	dwc->ep0state = EP0_SETUP_PHASE;
	dwc3_ep0_out_start(dwc);
}
Ejemplo n.º 5
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		trb;
	struct dwc3_ep		*dep;
	u32			transfered;
	u8			epnum;

	epnum = event->endpoint_number;
	dep = dwc->eps[epnum];

	if (!dwc->ep0_status_pending) {
		r = next_request(&dep->request_list);
		ur = &r->request;
	} else {
		ur = &dwc->ep0_usb_req;
		dwc->ep0_status_pending = 0;
	}

	dwc3_trb_to_nat(dwc->ep0_trb, &trb);

	transfered = ur->length - trb.length;
	ur->actual += transfered;

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */

		dwc3_ep0_stall_and_restart(dwc);
		dwc3_gadget_giveback(dep, r, -ECONNRESET);
	} else {
		/*
		 * handle the case where we have to send a zero packet. This
		 * seems to be case when req.length > maxpacket. Could it be?
		 */
		/* The transfer is complete, wait for HOST */
		if (epnum & 1)
			dwc->ep0state = EP0_IN_WAIT_NRDY;
		else
			dwc->ep0state = EP0_OUT_WAIT_NRDY;

		if (r)
			dwc3_gadget_giveback(dep, r, 0);
	}
}
Ejemplo n.º 6
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		trb;
	struct dwc3_ep		*dep;
	u32			transferred;
	u8			epnum;

	epnum = event->endpoint_number;
	dep = dwc->eps[epnum];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;

	if (!dwc->ep0_status_pending) {
		r = next_request(&dwc->eps[0]->request_list);
		ur = &r->request;
	} else {
		ur = &dwc->ep0_usb_req;
		dwc->ep0_status_pending = 0;
	}

	dwc3_trb_to_nat(dwc->ep0_trb, &trb);

	if (dwc->ep0_bounced) {
		struct dwc3_ep	*ep0 = dwc->eps[0];

		transferred = min_t(u32, ur->length,
				ep0->endpoint.maxpacket - trb.length);
		memcpy(ur->buf, dwc->ep0_bounce, transferred);
		dwc->ep0_bounced = false;
	} else {
		transferred = ur->length - trb.length;
	}

	ur->actual += transferred;

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */

		dwc3_ep0_stall_and_restart(dwc);
	} else {
		/*
		 * handle the case where we have to send a zero packet. This
		 * seems to be case when req.length > maxpacket. Could it be?
		 */
		if (r)
			dwc3_gadget_giveback(dep, r, 0);
	}
}
Ejemplo n.º 7
0
static void dwc3_ep0_complete_req(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r;
	struct dwc3_ep		*dep;

	dep = dwc->eps[0];

	if (!list_empty(&dep->request_list)) {
		r = next_request(&dep->request_list);

		dwc3_gadget_giveback(dep, r, 0);
	}

	dwc->ep0state = EP0_SETUP_PHASE;
	dwc3_ep0_out_start(dwc);
}
Ejemplo n.º 8
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	u32			transferred;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;

	r = next_request(&ep0->request_list);
	ur = &r->request;

	trb = dwc->ep0_trb;
	length = trb->size & DWC3_TRB_SIZE_MASK;

	if (dwc->ep0_bounced) {
		transferred = min_t(u32, ur->length,
				ep0->endpoint.maxpacket - length);
		memcpy(ur->buf, dwc->ep0_bounce, transferred);
		dwc->ep0_bounced = false;
	} else {
		transferred = ur->length - length;
		ur->actual += transferred;
	}

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */

		dwc3_ep0_stall_and_restart(dwc);
	} else {
		/*
		 * handle the case where we have to send a zero packet. This
		 * seems to be case when req.length > maxpacket. Could it be?
		 */
		if (r)
			dwc3_gadget_giveback(ep0, r, 0);
	}
}
Ejemplo n.º 9
0
static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
{
	struct dwc3_ep		*dep = dwc->eps[0];

	/* stall is always issued on EP0 */
	__dwc3_gadget_ep_set_halt(dwc->eps[0], 1);
	dwc->eps[0]->flags = DWC3_EP_ENABLED;

	if (!list_empty(&dep->request_list)) {
		struct dwc3_request	*req;

		req = next_request(&dep->request_list);
		dwc3_gadget_giveback(dep, req, -ECONNRESET);
	}

	dwc->ep0state = EP0_SETUP_PHASE;
	dwc3_ep0_out_start(dwc);
}
Ejemplo n.º 10
0
static void dwc3_ep0_complete_req(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r;
	struct dwc3_ep		*dep;
	u8			epnum;

	epnum = event->endpoint_number;
	dep = dwc->eps[epnum];

	if (!list_empty(&dep->request_list)) {
		r = next_request(&dep->request_list);

		dwc3_gadget_giveback(dep, r, 0);
	}

	dwc->ep0state = EP0_IDLE;
	dwc3_ep0_out_start(dwc);
}
Ejemplo n.º 11
0
Archivo: ep0.c Proyecto: 020gzh/linux
static void dwc3_ep0_complete_status(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r;
	struct dwc3_ep		*dep;
	struct dwc3_trb		*trb;
	u32			status;

	dep = dwc->eps[0];
	trb = dwc->ep0_trb;

	trace_dwc3_complete_trb(dep, trb);

	if (!list_empty(&dep->request_list)) {
		r = next_request(&dep->request_list);

		dwc3_gadget_giveback(dep, r, 0);
	}

	if (dwc->test_mode) {
		int ret;

		ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
		if (ret < 0) {
			dwc3_trace(trace_dwc3_ep0, "Invalid Test #%d",
					dwc->test_mode_nr);
			dwc3_ep0_stall_and_restart(dwc);
			return;
		}
	}

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dwc->setup_packet_pending = true;
		dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
	}

	dwc->ep0state = EP0_SETUP_PHASE;
	dwc3_ep0_out_start(dwc);
}
Ejemplo n.º 12
0
static void dwc3_ep0_complete_status(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r;
	struct dwc3_ep		*dep;
	struct dwc3_trb		*trb;
	u32			status;

	dep = dwc->eps[0];
	trb = dwc->ep0_trb;

	if (!list_empty(&dep->request_list)) {
		r = next_request(&dep->request_list);

		dwc3_gadget_giveback(dep, r, 0);
	}

	if (dwc->test_mode) {
		int ret;

		ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
		if (ret < 0) {
			dev_dbg(dwc->dev, "Invalid Test #%d\n",
					dwc->test_mode_nr);
			dbg_event(0x00, "INVALTEST", ret);
			dwc3_ep0_stall_and_restart(dwc);
			return;
		}
	}

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING)
		dev_dbg(dwc->dev, "Setup Pending received\n");

	dbg_print(dep->number, "DONE", status, "STATUS");
	dwc->ep0state = EP0_SETUP_PHASE;
	dwc3_ep0_out_start(dwc);
}
Ejemplo n.º 13
0
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	u32			transferred;
	u32			status;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;

	trb = dwc->ep0_trb;

	r = next_request(&ep0->request_list);
	if (!r)
		return;

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dev_dbg(dwc->dev, "Setup Pending received\n");

		if (r)
			dwc3_gadget_giveback(ep0, r, -ECONNRESET);

		return;
	}

	if (dwc->ep0_zlp_sent)
		goto finish_zlp;

	ur = &r->request;

	length = trb->size & DWC3_TRB_SIZE_MASK;

	if (dwc->ep0_bounced) {
		unsigned transfer_size = ur->length;
		unsigned maxp = ep0->endpoint.maxpacket;

		transfer_size += (maxp - (transfer_size % maxp));
		transferred = min_t(u32, ur->length,
				transfer_size - length);
		memcpy(ur->buf, dwc->ep0_bounce, transferred);
	} else {
		transferred = ur->length - length;
	}

	ur->actual += transferred;

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */

		dwc3_ep0_stall_and_restart(dwc);
		return;
	}

	/* handle the case where we have to send a zero packet */
	if ((epnum & 1) && ur->zero &&
	    (ur->length % ep0->endpoint.maxpacket == 0)) {
		int ret;

		ret = dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, 0,
				DWC3_TRBCTL_CONTROL_DATA);
		WARN_ON(ret < 0);
		dwc->ep0_zlp_sent = 1;
		return;
	}

finish_zlp:
	dwc3_gadget_giveback(ep0, r, 0);
}
Ejemplo n.º 14
0
Archivo: ep0.c Proyecto: 020gzh/linux
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
		const struct dwc3_event_depevt *event)
{
	struct dwc3_request	*r = NULL;
	struct usb_request	*ur;
	struct dwc3_trb		*trb;
	struct dwc3_ep		*ep0;
	unsigned		transfer_size = 0;
	unsigned		maxp;
	unsigned		remaining_ur_length;
	void			*buf;
	u32			transferred = 0;
	u32			status;
	u32			length;
	u8			epnum;

	epnum = event->endpoint_number;
	ep0 = dwc->eps[0];

	dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;

	trb = dwc->ep0_trb;

	trace_dwc3_complete_trb(ep0, trb);

	r = next_request(&ep0->request_list);
	if (!r)
		return;

	status = DWC3_TRB_SIZE_TRBSTS(trb->size);
	if (status == DWC3_TRBSTS_SETUP_PENDING) {
		dwc->setup_packet_pending = true;

		dwc3_trace(trace_dwc3_ep0, "Setup Pending received");

		if (r)
			dwc3_gadget_giveback(ep0, r, -ECONNRESET);

		return;
	}

	ur = &r->request;
	buf = ur->buf;
	remaining_ur_length = ur->length;

	length = trb->size & DWC3_TRB_SIZE_MASK;

	maxp = ep0->endpoint.maxpacket;

	if (dwc->ep0_bounced) {
		/*
		 * Handle the first TRB before handling the bounce buffer if
		 * the request length is greater than the bounce buffer size
		 */
		if (ur->length > DWC3_EP0_BOUNCE_SIZE) {
			transfer_size = ALIGN(ur->length - maxp, maxp);
			transferred = transfer_size - length;
			buf = (u8 *)buf + transferred;
			ur->actual += transferred;
			remaining_ur_length -= transferred;

			trb++;
			length = trb->size & DWC3_TRB_SIZE_MASK;

			ep0->free_slot = 0;
		}

		transfer_size = roundup((ur->length - transfer_size),
					maxp);

		transferred = min_t(u32, remaining_ur_length,
				    transfer_size - length);
		memcpy(buf, dwc->ep0_bounce, transferred);
	} else {
		transferred = ur->length - length;
	}

	ur->actual += transferred;

	if ((epnum & 1) && ur->actual < ur->length) {
		/* for some reason we did not get everything out */

		dwc3_ep0_stall_and_restart(dwc);
	} else {
		dwc3_gadget_giveback(ep0, r, 0);

		if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
				ur->length && ur->zero) {
			int ret;

			dwc->ep0_next_event = DWC3_EP0_COMPLETE;

			ret = dwc3_ep0_start_trans(dwc, epnum,
					dwc->ctrl_req_addr, 0,
					DWC3_TRBCTL_CONTROL_DATA, false);
			WARN_ON(ret < 0);
		}
	}
}