static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	spinlock_t *lock;
	unsigned long flags;

	/*
	 * see
	 *   CAUTION [*queue handler*]
	 *   CAUTION [*endpoint queue*]
	 *   CAUTION [*request complete*]
	 */

	/********************  spin lock ********************/
	lock = usbhsg_trylock(gpriv, &flags);

	usbhsg_queue_pop(uep, ureq, -ECONNRESET);

	usbhsg_unlock(lock, &flags);
	/********************  spin unlock ******************/

	return 0;
}
static int usbhsg_pipe_disable(struct usbhsg_uep *uep)
{
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct usbhsg_request *ureq;
	int disable = 0;

	/*
	 *********  assume under spin lock  *********
	 */

	usbhs_fifo_disable(pipe);

	/*
	 * disable pipe irq
	 */
	usbhsg_irq_empty_ctrl(uep, disable);
	usbhsg_irq_ready_ctrl(uep, disable);

	while (1) {
		ureq = usbhsg_queue_get(uep);
		if (!ureq)
			break;

		usbhsg_queue_pop(uep, ureq, -ECONNRESET);
	}

	return 0;
}
Beispiel #3
0
static void usbhsg_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
{
	struct usbhs_pipe *pipe = pkt->pipe;
	struct usbhsg_uep *uep = usbhsg_pipe_to_uep(pipe);
	struct usbhsg_request *ureq = usbhsg_pkt_to_ureq(pkt);

	ureq->req.actual = pkt->actual;

	usbhsg_queue_pop(uep, ureq, 0);
}
Beispiel #4
0
static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);

	usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
	usbhsg_queue_pop(uep, ureq, -ECONNRESET);

	return 0;
}
static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep,
					 struct usbhsg_request *ureq)
{
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct usb_request *req = &ureq->req;
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	void *buf;
	int maxp;
	int remainder, recv;
	int is_done = 0;

	/*
	 *********  assume under spin lock  *********
	 */

	maxp		= usbhs_pipe_get_maxpacket(pipe);
	buf		= req->buf    + req->actual;
	remainder	= req->length - req->actual;

	recv = usbhs_fifo_read(pipe, buf, remainder);
	/*
	 * recv < 0  : pipe busy
	 * recv >= 0 : receive data
	 *
	 * recv <= max_packet
	 */
	if (recv < 0)
		return -EBUSY;

	/* update parameters */
	req->actual += recv;

	if ((recv == remainder) ||	/* receive all data */
	    (recv < maxp))		/* short packet */
		is_done = 1;

	dev_dbg(dev, "  recv %d (%d/ %d/ %d/ %d)\n",
		usbhs_pipe_number(pipe),
		remainder, recv, is_done, req->zero);

	/* read all data ? */
	if (is_done) {
		int disable = 0;

		uep->handler->irq_mask(uep, disable);
		usbhs_fifo_disable(pipe);
		usbhsg_queue_pop(uep, ureq, 0);
	}

	return 0;
}
/*
 *		handler function
 */
static int usbhsg_try_run_ctrl_stage_end(struct usbhsg_uep *uep,
					 struct usbhsg_request *ureq)
{
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);

	/*
	 *********  assume under spin lock  *********
	 */

	usbhs_dcp_control_transfer_done(pipe);
	usbhsg_queue_pop(uep, ureq, 0);

	return 0;
}
Beispiel #7
0
/*
 *
 *		usb_dcp_ops
 *
 */
static int usbhsg_pipe_disable(struct usbhsg_uep *uep)
{
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct usbhs_pkt *pkt;

	while (1) {
		pkt = usbhs_pkt_pop(pipe, NULL);
		if (!pkt)
			break;

		usbhsg_queue_pop(uep, usbhsg_pkt_to_ureq(pkt), -ECONNRESET);
	}

	usbhs_pipe_disable(pipe);

	return 0;
}
Beispiel #8
0
static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);

	if (pipe)
		usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));

	/*
	 * To dequeue a request, this driver should call the usbhsg_queue_pop()
	 * even if the pipe is NULL.
	 */
	usbhsg_queue_pop(uep, ureq, -ECONNRESET);

	return 0;
}
Beispiel #9
0
static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
	struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
	struct usbhs_pipe *pipe;
	unsigned long flags;

	spin_lock_irqsave(&uep->lock, flags);
	pipe = usbhsg_uep_to_pipe(uep);
	if (pipe)
		usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));

	/*
	 * To dequeue a request, this driver should call the usbhsg_queue_pop()
	 * even if the pipe is NULL.
	 */
	usbhsg_queue_pop(uep, ureq, -ECONNRESET);
	spin_unlock_irqrestore(&uep->lock, flags);

	return 0;
}
static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep,
				      struct usbhsg_request *ureq)
{
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct usb_request *req = &ureq->req;
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	void *buf;
	int remainder, send;
	int is_done = 0;
	int enable;
	int maxp;

	/*
	 *********  assume under spin lock  *********
	 */

	maxp		= usbhs_pipe_get_maxpacket(pipe);
	buf		= req->buf    + req->actual;
	remainder	= req->length - req->actual;

	send = usbhs_fifo_write(pipe, buf, remainder);

	/*
	 * send < 0 : pipe busy
	 * send = 0 : send zero packet
	 * send > 0 : send data
	 *
	 * send <= max_packet
	 */
	if (send > 0)
		req->actual += send;

	/* send all packet ? */
	if (send < remainder)
		is_done = 0;		/* there are remainder data */
	else if (send < maxp)
		is_done = 1;		/* short packet */
	else
		is_done = !req->zero;	/* send zero packet ? */

	dev_dbg(dev, "  send %d (%d/ %d/ %d/ %d)\n",
		usbhs_pipe_number(pipe),
		remainder, send, is_done, req->zero);

	/*
	 * enable interrupt and send again in irq handler
	 * if it still have remainder data which should be sent.
	 */
	enable = !is_done;
	uep->handler->irq_mask(uep, enable);

	/*
	 * usbhs_fifo_enable execute
	 *  - after callback_update,
	 *  - before queue_pop / stage_end
	 */
	usbhs_fifo_enable(pipe);

	/*
	 * all data were sent ?
	 */
	if (is_done) {
		/* it care below call in
		   "function mode" */
		if (usbhsg_is_dcp(uep))
			usbhs_dcp_control_transfer_done(pipe);

		usbhsg_queue_pop(uep, ureq, 0);
	}

	return 0;
}