Beispiel #1
0
void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len)
{
	if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK))
		return;

	/*
	 * clear and disable transfer counter for IN/OUT pipe
	 */
	usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR);

	/*
	 * Only IN direction bulk pipe can use transfer count.
	 * Without using this function,
	 * received data will break if it was large data size.
	 * see PIPEnTRN/PIPEnTRE for detail
	 */
	if (usbhs_pipe_is_dir_in(pipe)) {
		int maxp = usbhs_pipe_get_maxpacket(pipe);

		usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp));
		usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */
	}
}
Beispiel #2
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;
}