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

Commit 89f84b84 authored by Nick Dyer's avatar Nick Dyer Committed by Dmitry Torokhov
Browse files

Input: usbtouchscreen - add sysfs attribute for 3M MTouch firmware rev



Allow querying of the firmware revision of the device

example:

4.10

Tested on ZII RDU2 platform and on Intel x86_64 PC.

Signed-off-by: default avatarNick Dyer <nick@shmanahar.org>
Tested-by: default avatarNikita Yushchenko <nikita.yoush@cogentembedded.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent ff7242ab
Loading
Loading
Loading
Loading
+94 −0
Original line number Diff line number Diff line
@@ -440,6 +440,8 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
#define MTOUCHUSB_RESET                 7
#define MTOUCHUSB_REQ_CTRLLR_ID         10

#define MTOUCHUSB_REQ_CTRLLR_ID_LEN	16

static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
	if (hwcalib_xy) {
@@ -454,11 +456,93 @@ static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
	return 1;
}

struct mtouch_priv {
	u8 fw_rev_major;
	u8 fw_rev_minor;
};

static ssize_t mtouch_firmware_rev_show(struct device *dev,
				struct device_attribute *attr, char *output)
{
	struct usb_interface *intf = to_usb_interface(dev);
	struct usbtouch_usb *usbtouch = usb_get_intfdata(intf);
	struct mtouch_priv *priv = usbtouch->priv;

	return scnprintf(output, PAGE_SIZE, "%1x.%1x\n",
			 priv->fw_rev_major, priv->fw_rev_minor);
}
static DEVICE_ATTR(firmware_rev, 0444, mtouch_firmware_rev_show, NULL);

static struct attribute *mtouch_attrs[] = {
	&dev_attr_firmware_rev.attr,
	NULL
};

static const struct attribute_group mtouch_attr_group = {
	.attrs = mtouch_attrs,
};

static int mtouch_get_fw_revision(struct usbtouch_usb *usbtouch)
{
	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
	struct mtouch_priv *priv = usbtouch->priv;
	u8 *buf;
	int ret;

	buf = kzalloc(MTOUCHUSB_REQ_CTRLLR_ID_LEN, GFP_NOIO);
	if (!buf)
		return -ENOMEM;

	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
			      MTOUCHUSB_REQ_CTRLLR_ID,
			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			      0, 0, buf, MTOUCHUSB_REQ_CTRLLR_ID_LEN,
			      USB_CTRL_SET_TIMEOUT);
	if (ret != MTOUCHUSB_REQ_CTRLLR_ID_LEN) {
		dev_warn(&usbtouch->interface->dev,
			 "Failed to read FW rev: %d\n", ret);
		ret = ret < 0 ? ret : -EIO;
		goto free;
	}

	priv->fw_rev_major = buf[3];
	priv->fw_rev_minor = buf[4];

	ret = 0;

free:
	kfree(buf);
	return ret;
}

static int mtouch_alloc(struct usbtouch_usb *usbtouch)
{
	int ret;

	usbtouch->priv = kmalloc(sizeof(struct mtouch_priv), GFP_KERNEL);
	if (!usbtouch->priv)
		return -ENOMEM;

	ret = sysfs_create_group(&usbtouch->interface->dev.kobj,
				 &mtouch_attr_group);
	if (ret) {
		kfree(usbtouch->priv);
		usbtouch->priv = NULL;
		return ret;
	}

	return 0;
}

static int mtouch_init(struct usbtouch_usb *usbtouch)
{
	int ret, i;
	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);

	ret = mtouch_get_fw_revision(usbtouch);
	if (ret)
		return ret;

	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
	                      MTOUCHUSB_RESET,
	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
@@ -492,6 +576,14 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)

	return 0;
}

static void mtouch_exit(struct usbtouch_usb *usbtouch)
{
	struct mtouch_priv *priv = usbtouch->priv;

	sysfs_remove_group(&usbtouch->interface->dev.kobj, &mtouch_attr_group);
	kfree(priv);
}
#endif


@@ -1119,7 +1211,9 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
		.max_yc		= 0x4000,
		.rept_size	= 11,
		.read_data	= mtouch_read_data,
		.alloc		= mtouch_alloc,
		.init		= mtouch_init,
		.exit		= mtouch_exit,
	},
#endif