static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
			       struct usbhsh_ep *uep)
{
	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
	struct usbhs_pipe *pipe;
	struct device *dev = usbhs_priv_to_dev(priv);
	unsigned long flags;

	/********************  spin lock ********************/
	usbhs_lock(priv, flags);

	pipe = usbhsh_uep_to_pipe(uep);

	if (unlikely(!pipe)) {
		dev_err(dev, "uep doens't have pipe\n");
	} else {
		struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);
		struct usbhsh_device *udev = usbhsh_uep_to_udev(uep);

		/* detach pipe from uep */
		usbhsh_uep_to_pipe(uep)		= NULL;
		usbhsh_pipe_to_uep(pipe)	= NULL;

		dev_dbg(dev, "%s [%d-%d(%s)]\n", __func__,
			usbhsh_device_number(hpriv, udev),
			usb_endpoint_num(&ep->desc),
			usbhs_pipe_name(pipe));
	}

	usbhs_unlock(priv, flags);
	/********************  spin unlock ******************/
}
Exemple #2
0
static void usbhsh_endpoint_detach(struct usbhsh_hpriv *hpriv,
				   struct usb_host_endpoint *ep)
{
	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
	struct device *dev = usbhs_priv_to_dev(priv);
	struct usbhsh_ep *uep = usbhsh_ep_to_uep(ep);
	unsigned long flags;

	if (!uep)
		return;

	dev_dbg(dev, "%s [%d-%d]\n", __func__,
		usbhsh_device_number(hpriv, usbhsh_uep_to_udev(uep)),
		usb_endpoint_num(&ep->desc));

	if (usbhsh_uep_to_pipe(uep))
		usbhsh_pipe_detach(hpriv, uep);

	/********************  spin lock ********************/
	usbhs_lock(priv, flags);

	/* remove this endpoint from udev */
	list_del_init(&uep->ep_list);

	usbhsh_uep_to_udev(uep)	= NULL;
	usbhsh_uep_to_ep(uep)	= NULL;
	usbhsh_ep_to_uep(ep)	= NULL;

	usbhs_unlock(priv, flags);
	/********************  spin unlock ******************/

	kfree(uep);
}
Exemple #3
0
static int usbhsh_dcp_queue_push(struct usb_hcd *hcd,
				 struct urb *urb,
				 gfp_t mflags)
{
	struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd);
	struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep);
	struct usbhs_pipe *pipe = usbhsh_uep_to_pipe(uep);
	struct device *dev = usbhsh_hcd_to_dev(hcd);
	int ret;

	dev_dbg(dev, "%s\n", __func__);

	/*
	 * setup stage
	 *
	 * usbhsh_send_setup_stage_packet() wait SACK/SIGN
	 */
	usbhsh_setup_stage_packet_push(hpriv, urb, pipe);

	/*
	 * data stage
	 *
	 * It is pushed only when urb has buffer.
	 */
	if (urb->transfer_buffer_length) {
		ret = usbhsh_data_stage_packet_push(hpriv, urb, pipe, mflags);
		if (ret < 0) {
			dev_err(dev, "data stage failed\n");
			return ret;
		}
	}

	/*
	 * status stage
	 */
	ret = usbhsh_status_stage_packet_push(hpriv, urb, pipe, mflags);
	if (ret < 0) {
		dev_err(dev, "status stage failed\n");
		return ret;
	}

	/*
	 * start pushed packets
	 */
	usbhs_pkt_start(pipe);

	return 0;
}
Exemple #4
0
static int usbhsh_queue_push(struct usb_hcd *hcd,
			     struct urb *urb,
			     gfp_t mem_flags)
{
	struct usbhsh_hpriv *hpriv = usbhsh_hcd_to_hpriv(hcd);
	struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep);
	struct usbhs_pipe *pipe = usbhsh_uep_to_pipe(uep);
	struct device *dev = usbhsh_hcd_to_dev(hcd);
	struct usbhsh_request *ureq;
	void *buf;
	int len, sequence;

	if (usb_pipeisoc(urb->pipe)) {
		dev_err(dev, "pipe iso is not supported now\n");
		return -EIO;
	}

	/* this ureq will be freed on usbhsh_queue_done() */
	ureq = usbhsh_ureq_alloc(hpriv, urb, mem_flags);
	if (unlikely(!ureq)) {
		dev_err(dev, "ureq alloc fail\n");
		return -ENOMEM;
	}

	if (usb_pipein(urb->pipe))
		pipe->handler = &usbhs_fifo_dma_pop_handler;
	else
		pipe->handler = &usbhs_fifo_dma_push_handler;

	buf = (void *)(urb->transfer_buffer + urb->actual_length);
	len = urb->transfer_buffer_length - urb->actual_length;

	sequence = usb_gettoggle(urb->dev,
				 usb_pipeendpoint(urb->pipe),
				 usb_pipeout(urb->pipe));

	dev_dbg(dev, "%s\n", __func__);
	usbhs_pkt_push(pipe, &ureq->pkt, usbhsh_queue_done,
		       buf, len, (urb->transfer_flags & URB_ZERO_PACKET),
		       sequence);

	usbhs_pkt_start(pipe);

	return 0;
}
Exemple #5
0
static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
			      struct urb *urb)
{
	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
	struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep);
	struct usbhsh_device *udev = usbhsh_device_get(hpriv, urb);
	struct usbhs_pipe *pipe;
	struct usb_endpoint_descriptor *desc = &urb->ep->desc;
	struct device *dev = usbhs_priv_to_dev(priv);
	unsigned long flags;
	int dir_in_req = !!usb_pipein(urb->pipe);
	int is_dcp = usb_endpoint_xfer_control(desc);
	int i, dir_in;
	int ret = -EBUSY;

	/********************  spin lock ********************/
	usbhs_lock(priv, flags);

	/*
	 * if uep has been attached to pipe,
	 * reuse it
	 */
	if (usbhsh_uep_to_pipe(uep)) {
		ret = 0;
		goto usbhsh_pipe_attach_done;
	}

	usbhs_for_each_pipe_with_dcp(pipe, priv, i) {

		/* check pipe type */
		if (!usbhs_pipe_type_is(pipe, usb_endpoint_type(desc)))
			continue;

		/* check pipe direction if normal pipe */
		if (!is_dcp) {
			dir_in = !!usbhs_pipe_is_dir_in(pipe);
			if (0 != (dir_in - dir_in_req))
				continue;
		}

		/* check pipe is free */
		if (usbhsh_pipe_to_uep(pipe))
			continue;

		/*
		 * attach pipe to uep
		 *
		 * usbhs_pipe_config_update() should be called after
		 * usbhs_set_device_config()
		 * see
		 *  DCPMAXP/PIPEMAXP
		 */
		usbhsh_uep_to_pipe(uep)		= pipe;
		usbhsh_pipe_to_uep(pipe)	= uep;

		usbhs_pipe_config_update(pipe,
					 usbhsh_device_number(hpriv, udev),
					 usb_endpoint_num(desc),
					 usb_endpoint_maxp(desc));

		dev_dbg(dev, "%s [%d-%d(%s:%s)]\n", __func__,
			usbhsh_device_number(hpriv, udev),
			usb_endpoint_num(desc),
			usbhs_pipe_name(pipe),
			dir_in_req ? "in" : "out");

		ret = 0;
		break;
	}

usbhsh_pipe_attach_done:
	if (0 == ret)
		uep->counter++;

	usbhs_unlock(priv, flags);
	/********************  spin unlock ******************/

	return ret;
}