Exemple #1
0
/*
 *		USB_TYPE handler
 */
static int usbhsg_recip_run_handle(struct usbhs_priv *priv,
				   struct usbhsg_recip_handle *handler,
				   struct usb_ctrlrequest *ctrl)
{
	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usbhsg_uep *uep;
	struct usbhs_pipe *pipe;
	int recip = ctrl->bRequestType & USB_RECIP_MASK;
	int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
	int ret = 0;
	int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep,
		    struct usb_ctrlrequest *ctrl);
	char *msg;

	uep = usbhsg_gpriv_to_nth_uep(gpriv, nth);
	pipe = usbhsg_uep_to_pipe(uep);
	if (!pipe) {
		dev_err(dev, "wrong recip request\n");
		return -EINVAL;
	}

	switch (recip) {
	case USB_RECIP_DEVICE:
		msg	= "DEVICE";
		func	= handler->device;
		break;
	case USB_RECIP_INTERFACE:
		msg	= "INTERFACE";
		func	= handler->interface;
		break;
	case USB_RECIP_ENDPOINT:
		msg	= "ENDPOINT";
		func	= handler->endpoint;
		break;
	default:
		dev_warn(dev, "unsupported RECIP(%d)\n", recip);
		func = NULL;
		ret = -EINVAL;
	}

	if (func) {
		dev_dbg(dev, "%s (pipe %d :%s)\n", handler->name, nth, msg);
		ret = func(priv, uep, ctrl);
	}

	return ret;
}
Exemple #2
0
/*
 *		queue push/pop
 */
static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
			       struct usbhsg_request *ureq,
			       int status)
{
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);

	dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));

	ureq->req.status = status;
	spin_unlock(usbhs_priv_to_lock(priv));
	usb_gadget_giveback_request(&uep->ep, &ureq->req);
	spin_lock(usbhs_priv_to_lock(priv));
}
static int __usbhsg_queue_handler(struct usbhsg_uep *uep, int prepare)
{
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usbhsg_request *ureq;
	spinlock_t *lock;
	unsigned long flags;
	int ret = 0;

	if (!uep->handler) {
		dev_err(dev, "no handler function\n");
		return -EIO;
	}

	/*
	 * CAUTION [*queue handler*]
	 *
	 * This function will be called for start/restart queue operation.
	 * OTOH the most much worry for USB driver is spinlock nest.
	 * Specially it are
	 *   - usb_ep_ops  :: queue
	 *   - usb_request :: complete
	 *
	 * But the caller of this function need not care about spinlock.
	 * This function is using usbhsg_trylock for it.
	 * if "is_locked" is 1, this mean this function lock it.
	 * but if it is 0, this mean it is already under spin lock.
	 * see also
	 *   CAUTION [*endpoint queue*]
	 *   CAUTION [*request complete*]
	 */

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

	ureq = usbhsg_queue_get(uep);
	if (ureq) {
		if (prepare)
			ret = uep->handler->prepare(uep, ureq);
		else
			ret = uep->handler->try_run(uep, ureq);
	}
	usbhsg_unlock(lock, &flags);
	/********************  spin unlock ******************/

	return ret;
}
Exemple #4
0
/*
 *		queue push/pop
 */
static void usbhsg_queue_push(struct usbhsg_uep *uep,
			      struct usbhsg_request *ureq)
{
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct usbhs_pkt *pkt = usbhsg_ureq_to_pkt(ureq);
	struct usb_request *req = &ureq->req;

	req->actual = 0;
	req->status = -EINPROGRESS;
	usbhs_pkt_push(pipe, pkt, uep->handler,
		       req->buf, req->length, req->zero);

	dev_dbg(dev, "pipe %d : queue push (%d)\n",
		usbhs_pipe_number(pipe),
		req->length);
}
/*
 *		list push/pop
 */
static void usbhsg_queue_push(struct usbhsg_uep *uep,
			      struct usbhsg_request *ureq)
{
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);

	/*
	 *********  assume under spin lock  *********
	 */
	list_del_init(&ureq->node);
	list_add_tail(&ureq->node, &uep->list);
	ureq->req.actual = 0;
	ureq->req.status = -EINPROGRESS;

	dev_dbg(dev, "pipe %d : queue push (%d)\n",
		usbhs_pipe_number(pipe),
		ureq->req.length);
}
static int __usbhsg_ep_set_halt_wedge(struct usb_ep *ep, int halt, int wedge)
{
	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	spinlock_t *lock;
	unsigned long flags;
	int ret = -EAGAIN;

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

	/********************  spin lock ********************/
	lock = usbhsg_trylock(gpriv, &flags);
	if (!usbhsg_queue_get(uep)) {

		dev_dbg(dev, "set halt %d (pipe %d)\n",
			halt, usbhs_pipe_number(pipe));

		if (halt)
			usbhs_fifo_stall(pipe);
		else
			usbhs_fifo_disable(pipe);

		if (halt && wedge)
			usbhsg_status_set(gpriv, USBHSG_STATUS_WEDGE);
		else
			usbhsg_status_clr(gpriv, USBHSG_STATUS_WEDGE);

		ret = 0;
	}

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

	return ret;
}
static void usbhsg_queue_pop(struct usbhsg_uep *uep,
			     struct usbhsg_request *ureq,
			     int status)
{
	struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);

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

	/*
	 * CAUTION [*request complete*]
	 *
	 * There is a possibility not to be called in correct order
	 * if "complete" is called without spinlock.
	 *
	 * So, this function assume it is under spinlock,
	 * and call usb_request :: complete.
	 *
	 * But this "complete" will push next usb_request.
	 * It mean "usb_ep_ops :: queue" which is using spinlock is called
	 * under spinlock.
	 *
	 * To avoid dead-lock, this driver is using usbhsg_trylock.
	 *   CAUTION [*endpoint queue*]
	 *   CAUTION [*queue handler*]
	 */

	dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));

	list_del_init(&ureq->node);

	ureq->req.status = status;
	ureq->req.complete(&uep->ep, &ureq->req);

	/* more request ? */
	if (0 == status)
		usbhsg_queue_prepare(uep);
}
Exemple #8
0
static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv,
				       unsigned short status)
{
	struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usb_request *req;
	unsigned short *buf;

	/* alloc new usb_request for recip */
	req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC);
	if (!req) {
		dev_err(dev, "recip request allocation fail\n");
		return;
	}

	/* alloc recip data buffer */
	buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
	if (!buf) {
		usb_ep_free_request(&dcp->ep, req);
		dev_err(dev, "recip data allocation fail\n");
		return;
	}

	/* recip data is status */
	*buf = cpu_to_le16(status);

	/* allocated usb_request/buffer will be freed */
	req->complete	= __usbhsg_recip_send_complete;
	req->buf	= buf;
	req->length	= sizeof(*buf);
	req->zero	= 0;

	/* push packet */
	pipe->handler = &usbhs_fifo_pio_push_handler;
	usbhsg_queue_push(dcp, usbhsg_req_to_ureq(req));
}
Exemple #9
0
static int usbhsg_gadget_stop(struct usb_gadget_driver *driver)
{
	struct usbhsg_gpriv *gpriv;
	struct usbhs_priv *priv;
	struct device *dev;

	if (!driver		||
	    !driver->unbind)
		return -EINVAL;

	/*
	 * find controller
	 */
	usbhsg_for_each_controller(gpriv) {
		if (gpriv->driver == driver)
			goto find_matching_controller;
	}
	return -ENODEV;

find_matching_controller:

	dev  = usbhsg_gpriv_to_dev(gpriv);
	priv = usbhsg_gpriv_to_priv(gpriv);

	usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
	device_del(&gpriv->gadget.dev);
	gpriv->driver = NULL;

	if (driver->disconnect)
		driver->disconnect(&gpriv->gadget);

	driver->unbind(&gpriv->gadget);
	dev_dbg(dev, "unbind %s\n", driver->driver.name);

	return 0;
}
static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv,
				 struct usbhs_irq_state *irq_state)
{
	struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
	struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
	struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp);
	struct device *dev = usbhsg_gpriv_to_dev(gpriv);
	struct usb_ctrlrequest ctrl;
	struct usbhsg_recip_handle *recip_handler = NULL;
	int stage = usbhs_status_get_ctrl_stage(irq_state);
	int ret = 0;

	dev_dbg(dev, "stage = %d\n", stage);

	/*
	 * see Manual
	 *
	 *  "Operation"
	 *  - "Interrupt Function"
	 *    - "Control Transfer Stage Transition Interrupt"
	 *      - Fig. "Control Transfer Stage Transitions"
	 */

	switch (stage) {
	case READ_DATA_STAGE:
		dcp->handler = &usbhsg_handler_send_ctrl;
		break;
	case WRITE_DATA_STAGE:
		dcp->handler = &usbhsg_handler_recv_ctrl;
		break;
	case NODATA_STATUS_STAGE:
		dcp->handler = &usbhsg_handler_ctrl_stage_end;
		break;
	default:
		return ret;
	}

	/*
	 * get usb request
	 */
	usbhs_usbreq_get_val(priv, &ctrl);

	switch (ctrl.bRequestType & USB_TYPE_MASK) {
	case USB_TYPE_STANDARD:
		switch (ctrl.bRequest) {
		case USB_REQ_CLEAR_FEATURE:
			recip_handler = &req_clear_feature;
			break;
		}
	}

	/*
	 * setup stage / run recip
	 */
	if (recip_handler)
		ret = usbhsg_recip_run_handle(priv, recip_handler, &ctrl);
	else
		ret = gpriv->driver->setup(&gpriv->gadget, &ctrl);

	if (ret < 0)
		usbhs_fifo_stall(pipe);

	return ret;
}
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;
}