Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8aef622 authored by Oliver Neukum's avatar Oliver Neukum Committed by Dmitry Torokhov
Browse files

Input: usbtouchscreen - implement reset_resume



This implements reset_resume() by splitting init into allocations
of private data structures and device initializations. Device
initializations are repeated upon reset_resume.

Signed-off-by: default avatarOliver Neukum <oneukum@suse.de>
Tested-by: default avatarPetr Štetiar <ynezz@true.cz>
Tested-by: default avatarOndrej Zary <linux@rainbow-software.org>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 5d9efc59
Loading
Loading
Loading
Loading
+76 −32
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ struct usbtouch_device_info {
	int  (*get_pkt_len) (unsigned char *pkt, int len);

	int  (*read_data)   (struct usbtouch_usb *usbtouch, unsigned char *pkt);
	int  (*alloc)       (struct usbtouch_usb *usbtouch);
	int  (*init)        (struct usbtouch_usb *usbtouch);
	void (*exit)	    (struct usbtouch_usb *usbtouch);
};
@@ -510,7 +511,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
	int ret = -ENOMEM;
	unsigned char *buf;

	buf = kmalloc(2, GFP_KERNEL);
	buf = kmalloc(2, GFP_NOIO);
	if (!buf)
		goto err_nobuf;
	/* reset */
@@ -735,11 +736,43 @@ static void nexio_ack_complete(struct urb *urb)
{
}

static int nexio_alloc(struct usbtouch_usb *usbtouch)
{
	struct nexio_priv *priv;
	int ret = -ENOMEM;

	usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL);
	if (!usbtouch->priv)
		goto out_buf;

	priv = usbtouch->priv;

	priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt),
				GFP_KERNEL);
	if (!priv->ack_buf)
		goto err_priv;

	priv->ack = usb_alloc_urb(0, GFP_KERNEL);
	if (!priv->ack) {
		dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__);
		goto err_ack_buf;
	}

	return 0;

err_ack_buf:
	kfree(priv->ack_buf);
err_priv:
	kfree(priv);
out_buf:
	return ret;
}

static int nexio_init(struct usbtouch_usb *usbtouch)
{
	struct usb_device *dev = interface_to_usbdev(usbtouch->interface);
	struct usb_host_interface *interface = usbtouch->interface->cur_altsetting;
	struct nexio_priv *priv;
	struct nexio_priv *priv = usbtouch->priv;
	int ret = -ENOMEM;
	int actual_len, i;
	unsigned char *buf;
@@ -758,7 +791,7 @@ static int nexio_init(struct usbtouch_usb *usbtouch)
	if (!input_ep || !output_ep)
		return -ENXIO;

	buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL);
	buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO);
	if (!buf)
		goto out_buf;

@@ -790,11 +823,11 @@ static int nexio_init(struct usbtouch_usb *usbtouch)
		switch (buf[0]) {
		case 0x83:	/* firmware version */
			if (!firmware_ver)
				firmware_ver = kstrdup(&buf[2], GFP_KERNEL);
				firmware_ver = kstrdup(&buf[2], GFP_NOIO);
			break;
		case 0x84:	/* device name */
			if (!device_name)
				device_name = kstrdup(&buf[2], GFP_KERNEL);
				device_name = kstrdup(&buf[2], GFP_NOIO);
			break;
		}
	}
@@ -805,36 +838,11 @@ static int nexio_init(struct usbtouch_usb *usbtouch)
	kfree(firmware_ver);
	kfree(device_name);

	/* prepare ACK URB */
	ret = -ENOMEM;

	usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL);
	if (!usbtouch->priv)
		goto out_buf;

	priv = usbtouch->priv;

	priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt),
				GFP_KERNEL);
	if (!priv->ack_buf)
		goto err_priv;

	priv->ack = usb_alloc_urb(0, GFP_KERNEL);
	if (!priv->ack) {
		dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__);
		goto err_ack_buf;
	}

	usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep),
			  priv->ack_buf, sizeof(nexio_ack_pkt),
			  nexio_ack_complete, usbtouch);
	ret = 0;
	goto out_buf;

err_ack_buf:
	kfree(priv->ack_buf);
err_priv:
	kfree(priv);
out_buf:
	kfree(buf);
	return ret;
@@ -1125,6 +1133,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
		.rept_size	= 1024,
		.irq_always	= true,
		.read_data	= nexio_read_data,
		.alloc		= nexio_alloc,
		.init		= nexio_init,
		.exit		= nexio_exit,
	},
@@ -1337,6 +1346,31 @@ static int usbtouch_resume(struct usb_interface *intf)
	return result;
}

static int usbtouch_reset_resume(struct usb_interface *intf)
{
	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
	struct input_dev *input = usbtouch->input;
	int err = 0;

	/* reinit the device */
	if (usbtouch->type->init) {
		err = usbtouch->type->init(usbtouch);
		if (err) {
			dbg("%s - type->init() failed, err: %d",
			    __func__, err);
			return err;
		}
	}

	/* restart IO if needed */
	mutex_lock(&input->mutex);
	if (input->users)
		err = usb_submit_urb(usbtouch->irq, GFP_NOIO);
	mutex_unlock(&input->mutex);

	return err;
}

static void usbtouch_free_buffers(struct usb_device *udev,
				  struct usbtouch_usb *usbtouch)
{
@@ -1456,12 +1490,21 @@ static int usbtouch_probe(struct usb_interface *intf,
	usbtouch->irq->transfer_dma = usbtouch->data_dma;
	usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	/* device specific init */
	/* device specific allocations */
	if (type->alloc) {
		err = type->alloc(usbtouch);
		if (err) {
			dbg("%s - type->alloc() failed, err: %d", __func__, err);
			goto out_free_urb;
		}
	}

	/* device specific initialisation*/
	if (type->init) {
		err = type->init(usbtouch);
		if (err) {
			dbg("%s - type->init() failed, err: %d", __func__, err);
			goto out_free_urb;
			goto out_do_exit;
		}
	}

@@ -1531,6 +1574,7 @@ static struct usb_driver usbtouch_driver = {
	.disconnect	= usbtouch_disconnect,
	.suspend	= usbtouch_suspend,
	.resume		= usbtouch_resume,
	.reset_resume	= usbtouch_reset_resume,
	.id_table	= usbtouch_devices,
	.supports_autosuspend = 1,
};