Exemplo n.º 1
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);
}
Exemplo n.º 2
0
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 ******************/
}
Exemplo n.º 3
0
static void usbhsh_device_detach(struct usbhsh_hpriv *hpriv,
			       struct usbhsh_device *udev)
{
	struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv);
	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
	struct device *dev = usbhsh_hcd_to_dev(hcd);
	struct usb_device *usbv = usbhsh_udev_to_usbv(udev);
	unsigned long flags;

	dev_dbg(dev, "%s [%d](%p)\n", __func__,
		usbhsh_device_number(hpriv, udev), udev);

	if (usbhsh_device_has_endpoint(udev)) {
		dev_warn(dev, "udev still have endpoint\n");
		usbhsh_endpoint_detach_all(hpriv, udev);
	}

	/*
	 * There is nothing to do if it is device0.
	 * see
	 *  usbhsh_device_attach()
	 *  usbhsh_device_get()
	 */
	if (0 == usbhsh_device_number(hpriv, udev))
		return;

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

	/*
	 * usbhsh_usbv_to_udev()
	 * usbhsh_udev_to_usbv()
	 * will be disable
	 */
	dev_set_drvdata(&usbv->dev, NULL);
	udev->usbv = NULL;

	usbhs_unlock(priv, flags);
	/********************  spin unlock ******************/
}
Exemplo n.º 4
0
static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv,
					   struct urb *urb,
					   struct usbhs_pipe *pipe)
{
	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
	struct usb_ctrlrequest req;
	struct device *dev = usbhs_priv_to_dev(priv);

	/*
	 * wait setup packet ACK
	 * see
	 *	usbhsh_irq_setup_ack()
	 *	usbhsh_irq_setup_err()
	 */
	init_completion(&hpriv->setup_ack_done);

	/* copy original request */
	memcpy(&req, urb->setup_packet, sizeof(struct usb_ctrlrequest));

	/*
	 * renesas_usbhs can not use original usb address.
	 * see HARDWARE LIMITATION.
	 * modify usb address here to use attached device.
	 * see usbhsh_device_attach()
	 */
	if (usbhsh_is_request_address(urb)) {
		struct usb_device *usbv = usbhsh_urb_to_usbv(urb);
		struct usbhsh_device *udev = usbhsh_usbv_to_udev(usbv);

		/* udev is a attached device */
		req.wValue = usbhsh_device_number(hpriv, udev);
		dev_dbg(dev, "create new address - %d\n", req.wValue);
	}

	/* set request */
	usbhs_usbreq_set_val(priv, &req);

	/*
	 * wait setup packet ACK
	 */
	wait_for_completion(&hpriv->setup_ack_done);

	dev_dbg(dev, "%s done\n", __func__);
}
Exemplo n.º 5
0
/*
 *		endpoint control
 */
static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,
				  struct urb *urb,
				  gfp_t mem_flags)
{
	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
	struct usbhsh_device *udev = usbhsh_device_get(hpriv, urb);
	struct usb_host_endpoint *ep = urb->ep;
	struct usbhsh_ep *uep;
	struct device *dev = usbhs_priv_to_dev(priv);
	struct usb_endpoint_descriptor *desc = &ep->desc;
	unsigned long flags;

	uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags);
	if (!uep) {
		dev_err(dev, "usbhsh_ep alloc fail\n");
		return -ENOMEM;
	}

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

	/*
	 * init endpoint
	 */
	uep->counter = 0;
	INIT_LIST_HEAD(&uep->ep_list);
	list_add_tail(&uep->ep_list, &udev->ep_list_head);

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

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

	dev_dbg(dev, "%s [%d-%d]\n", __func__,
		usbhsh_device_number(hpriv, udev),
		usb_endpoint_num(desc));

	return 0;
}
Exemplo n.º 6
0
static struct usbhsh_device *usbhsh_device_attach(struct usbhsh_hpriv *hpriv,
						 struct urb *urb)
{
	struct usbhsh_device *udev = NULL;
	struct usbhsh_device *udev0 = usbhsh_device0(hpriv);
	struct usbhsh_device *pos;
	struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv);
	struct device *dev = usbhsh_hcd_to_dev(hcd);
	struct usb_device *usbv = usbhsh_urb_to_usbv(urb);
	struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
	unsigned long flags;
	u16 upphub, hubport;
	int i;

	/*
	 * This function should be called only while urb is pointing to device0.
	 * It will attach unused usbhsh_device to urb (usbv),
	 * and initialize device0.
	 * You can use usbhsh_device_get() to get "current" udev,
	 * and usbhsh_usbv_to_udev() is for "attached" udev.
	 */
	if (0 != usb_pipedevice(urb->pipe)) {
		dev_err(dev, "%s fail: urb isn't pointing device0\n", __func__);
		return NULL;
	}

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

	/*
	 * find unused device
	 */
	usbhsh_for_each_udev(pos, hpriv, i) {
		if (usbhsh_udev_is_used(pos))
			continue;
		udev = pos;
		break;
	}

	if (udev) {
		/*
		 * usbhsh_usbv_to_udev()
		 * usbhsh_udev_to_usbv()
		 * will be enable
		 */
		dev_set_drvdata(&usbv->dev, udev);
		udev->usbv = usbv;
	}

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

	if (!udev) {
		dev_err(dev, "no free usbhsh_device\n");
		return NULL;
	}

	if (usbhsh_device_has_endpoint(udev)) {
		dev_warn(dev, "udev have old endpoint\n");
		usbhsh_endpoint_detach_all(hpriv, udev);
	}

	if (usbhsh_device_has_endpoint(udev0)) {
		dev_warn(dev, "udev0 have old endpoint\n");
		usbhsh_endpoint_detach_all(hpriv, udev0);
	}

	/* uep will be attached */
	INIT_LIST_HEAD(&udev0->ep_list_head);
	INIT_LIST_HEAD(&udev->ep_list_head);

	/*
	 * set device0 config
	 */
	usbhs_set_device_config(priv,
				0, 0, 0, usbv->speed);

	/*
	 * set new device config
	 */
	upphub	= 0;
	hubport	= 0;
	if (!usbhsh_connected_to_rhdev(hcd, udev)) {
		/* if udev is not connected to rhdev, it means parent is Hub */
		struct usbhsh_device *parent = usbhsh_device_parent(udev);

		upphub	= usbhsh_device_number(hpriv, parent);
		hubport	= usbhsh_device_hubport(udev);

		dev_dbg(dev, "%s connecte to Hub [%d:%d](%p)\n", __func__,
			upphub, hubport, parent);
	}

	usbhs_set_device_config(priv,
			       usbhsh_device_number(hpriv, udev),
			       upphub, hubport, usbv->speed);

	dev_dbg(dev, "%s [%d](%p)\n", __func__,
		usbhsh_device_number(hpriv, udev), udev);

	return udev;
}
Exemplo n.º 7
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;
}