All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] NEXIO (or iNexio) support for usbtouchscreen
@ 2009-11-09 14:37 Ondrej Zary
  2009-11-10 13:07 ` [RFC PATCH v2] " Ondrej Zary
  0 siblings, 1 reply; 4+ messages in thread
From: Ondrej Zary @ 2009-11-09 14:37 UTC (permalink / raw)
  To: daniel.ritz; +Cc: linux-kernel

Hello,
I have a NEXIO (or iNexio) NEX170MRT LCD monitor with integrated touchscreen 
with USB interface:
T:  Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 54 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=1870 ProdID=0001 Rev= 1.00
S:  Manufacturer=iNexio
S:  Product=iNexio USB
C:* #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=00 Driver=usbtouchscreen
E:  Ad=83(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=(none)
E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms


There's a iNexio serial touchscreen driver in kernel but it does not work for 
this touchscreen. Without a driver, it just connects and disconnects (after a 
while) repeatedly:
usb 2-2: new full speed USB device using uhci_hcd and address 3
usb 2-2: New USB device found, idVendor=1870, idProduct=0001
usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-2: Product: iNexio USB
usb 2-2: Manufacturer: iNexio
usb 2-2: configuration #1 chosen from 1 choice
usb 2-2: USB disconnect, address 3
usb 2-2: new full speed USB device using uhci_hcd and address 4
usb 2-2: New USB device found, idVendor=1870, idProduct=0001
usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 2-2: Product: iNexio USB
usb 2-2: Manufacturer: iNexio
usb 2-2: configuration #1 chosen from 1 choice
usb 2-2: USB disconnect, address 4


I captured (using SniffUSB) the communication between the Windows driver and 
the touchscreen after plugging in:
http://www.rainbow-software.org/linux_files/nexio/UsbSnoop-plug.log

Log with some touches after plugging in:
http://www.rainbow-software.org/linux_files/nexio/UsbSnoop-plugandtouch.log

If I understand it correctly, there's system initialization (first 3 URBs), 
then the driver starts communication:
URB 4: read, touchscreen returns 82 04 ab aa
URB 5: read, touchscreen returns nothing
URB 6: write 82 04 0a 0f
URB 7: read, touchscreen returns 84 04 0a 0f
URB 8: read, touchscreen returns 83 0a 32 2e 31 30 53 4d 53 4e (2.10SMSN - 
       firmware version as Windows driver displays)
URB 9: read, touchscreen returns 84 09 6d 2d 4e 65 78 69 6f (m-Nexio - device
       name as Windows driver displays)
URB 10: read, touchscreen returns nothing

Then 3 reads touchscreen returns nothing and returns "82 04 ab aa" on the 4th 
read.

Touchscreen sends 123 bytes of touch data:
    00000000: e1 00 74 00 40 00 34 00 00 00 11 10 0d 00 11 00
    00000010: 0a 00 01 07 03 04 02 03 00 05 00 0e 09 00 02 08
    00000020: 00 01 00 01 01 06 00 0e 00 0b 14 01 0d 06 00 00
    00000030: 02 02 00 02 11 11 06 01 00 02 01 0a 62 64 00 07
    00000040: 05 03 00 03 00 03 00 00 03 02 03 02 00 02 0a 00
    00000050: 02 05 00 06 64 64 64 01 02 04 03 0d 02 02 01 02
    00000060: 07 02 02 00 00 07 03 04 03 01 04 03 03 03 00 03
    00000070: 06 04 04 01 02 03 00 02 02 01 11
and driver acknowledges with "aa 02".

All reads are coming from endpoint 0x82 and all writes go to endpoint 0x01.

The driver continuously submits read URBs to endpoint 0x82. Touchscreen 
answers after 1 second if there's no activity or immediately with touch data.


I did this (but I don't know much about USB programming). The initialization
seems to work (outputs firmware version and device name correctly). But
the device disconnects probably because of absent communication. The first
URB should be probably sent in nexio_init().
Also the usbtouchscreen tries to bind to both device interfaces and it fails 
the second time. How to solve this?

--- drivers/input/touchscreen/usbtouchscreen.c.orig	2009-09-10 
00:13:59.000000000 +0200
+++ drivers/input/touchscreen/usbtouchscreen.c	2009-11-09 14:39:48.000000000 
+0100
@@ -13,6 +13,7 @@
  *  - IdealTEK URTC1000
  *  - General Touch
  *  - GoTop Super_Q2/GogoPen/PenPower tablets
+ *  - NEXIO/iNexio
  *
  * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -118,6 +119,7 @@
 	DEVTYPE_IDEALTEK,
 	DEVTYPE_GENERAL_TOUCH,
 	DEVTYPE_GOTOP,
+	DEVTYPE_NEXIO,
 };
 
 #define USB_DEVICE_HID_CLASS(vend, prod) \
@@ -191,6 +193,11 @@
 	{USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+	{USB_DEVICE(0x10f0, 0x2002), .driver_info = DEVTYPE_NEXIO},
+	{USB_DEVICE(0x1870, 0x0001), .driver_info = DEVTYPE_NEXIO},
+#endif
+
 	{}
 };
 
@@ -563,6 +570,87 @@
 }
 #endif
 
+/*****************************************************************************
+ * NEXIO Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+
+#define NEXIO_OUTPUT_EP	0x01
+#define NEXIO_INPUT_EP	0x82
+#define NEXIO_TIMEOUT	5000
+#define NEXIO_BUFSIZE	1024
+
+static int nexio_init(struct usbtouch_usb *usbtouch)
+{
+	struct usb_device *dev = usbtouch->udev;
+	int ret = -ENOMEM;
+	int actual_len;
+	unsigned char *buf;
+
+	buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL);
+	if (!buf)
+		goto err_nobuf;
+	printk("1 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	printk("2 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* Send some command */
+	printk("3 write \n");
+	buf[0] = 0x82;
+	buf[1] = 0x04;
+	buf[2] = 0x0a;
+	buf[3] = 0x0f;
+	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, NEXIO_OUTPUT_EP), buf, 4,
+			   &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* Read it back */
+	printk("4 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			  NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* Read firmware version */
+	printk("5 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x82), buf, NEXIO_BUFSIZE,
+			   &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	buf[buf[1]] = 0;
+	printk("Firmware version %s\n", &buf[2]);
+	/* Read device name */
+	printk("6 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x82), buf, NEXIO_BUFSIZE,
+			   &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	buf[buf[1]] = 0;
+	printk("Device name %s\n", &buf[2]);
+	if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
+		return -EIO;
+err_out:
+	kfree(buf);
+err_nobuf:
+	return ret;
+}
+
+static int nexio_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+	int i;
+	printk("nexio_read_data: ");
+	for (i = 0; i < pkt[1]; i++)
+		printk("%02X", pkt[i]);
+
+	return 0;
+}
+#endif
+
 
 /*****************************************************************************
  * the different device descriptors
@@ -702,6 +790,18 @@
 		.read_data	= gotop_read_data,
 	},
 #endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+	[DEVTYPE_NEXIO] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x03ff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x03ff,
+		.rept_size	= 4,
+		.read_data	= nexio_read_data,
+		.init		= nexio_init,
+	},
+#endif
 };
 


-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH v2] NEXIO (or iNexio) support for usbtouchscreen
  2009-11-09 14:37 [PATCH] NEXIO (or iNexio) support for usbtouchscreen Ondrej Zary
@ 2009-11-10 13:07 ` Ondrej Zary
  0 siblings, 0 replies; 4+ messages in thread
From: Ondrej Zary @ 2009-11-10 13:07 UTC (permalink / raw)
  To: daniel.ritz; +Cc: linux-kernel

On Monday 09 November 2009, Ondrej Zary wrote:
> Hello,
> I have a NEXIO (or iNexio) NEX170MRT LCD monitor with integrated
> touchscreen with USB interface:
> T:  Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 54 Spd=12  MxCh= 0
> D:  Ver= 1.10 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
> P:  Vendor=1870 ProdID=0001 Rev= 1.00
> S:  Manufacturer=iNexio
> S:  Product=iNexio USB
> C:* #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=500mA
> I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=00
> Driver=usbtouchscreen E:  Ad=83(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
> I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=(none)
> E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
> E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms
>
>
> There's a iNexio serial touchscreen driver in kernel but it does not work
> for this touchscreen. Without a driver, it just connects and disconnects
> (after a while) repeatedly:
> usb 2-2: new full speed USB device using uhci_hcd and address 3
> usb 2-2: New USB device found, idVendor=1870, idProduct=0001
> usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> usb 2-2: Product: iNexio USB
> usb 2-2: Manufacturer: iNexio
> usb 2-2: configuration #1 chosen from 1 choice
> usb 2-2: USB disconnect, address 3
> usb 2-2: new full speed USB device using uhci_hcd and address 4
> usb 2-2: New USB device found, idVendor=1870, idProduct=0001
> usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> usb 2-2: Product: iNexio USB
> usb 2-2: Manufacturer: iNexio
> usb 2-2: configuration #1 chosen from 1 choice
> usb 2-2: USB disconnect, address 4
>
>
> I captured (using SniffUSB) the communication between the Windows driver
> and the touchscreen after plugging in:
> http://www.rainbow-software.org/linux_files/nexio/UsbSnoop-plug.log
>
> Log with some touches after plugging in:
> http://www.rainbow-software.org/linux_files/nexio/UsbSnoop-plugandtouch.log
>
> If I understand it correctly, there's system initialization (first 3 URBs),
> then the driver starts communication:
> URB 4: read, touchscreen returns 82 04 ab aa
> URB 5: read, touchscreen returns nothing
> URB 6: write 82 04 0a 0f
> URB 7: read, touchscreen returns 84 04 0a 0f
> URB 8: read, touchscreen returns 83 0a 32 2e 31 30 53 4d 53 4e (2.10SMSN -
>        firmware version as Windows driver displays)
> URB 9: read, touchscreen returns 84 09 6d 2d 4e 65 78 69 6f (m-Nexio -
> device name as Windows driver displays)
> URB 10: read, touchscreen returns nothing
>
> Then 3 reads touchscreen returns nothing and returns "82 04 ab aa" on the
> 4th read.
>
> Touchscreen sends 123 bytes of touch data:
>     00000000: e1 00 74 00 40 00 34 00 00 00 11 10 0d 00 11 00
>     00000010: 0a 00 01 07 03 04 02 03 00 05 00 0e 09 00 02 08
>     00000020: 00 01 00 01 01 06 00 0e 00 0b 14 01 0d 06 00 00
>     00000030: 02 02 00 02 11 11 06 01 00 02 01 0a 62 64 00 07
>     00000040: 05 03 00 03 00 03 00 00 03 02 03 02 00 02 0a 00
>     00000050: 02 05 00 06 64 64 64 01 02 04 03 0d 02 02 01 02
>     00000060: 07 02 02 00 00 07 03 04 03 01 04 03 03 03 00 03
>     00000070: 06 04 04 01 02 03 00 02 02 01 11
> and driver acknowledges with "aa 02".
>
> All reads are coming from endpoint 0x82 and all writes go to endpoint 0x01.
>
> The driver continuously submits read URBs to endpoint 0x82. Touchscreen
> answers after 1 second if there's no activity or immediately with touch
> data.
>
>
> I did this (but I don't know much about USB programming). The
> initialization seems to work (outputs firmware version and device name
> correctly). But the device disconnects probably because of absent
> communication. The first URB should be probably sent in nexio_init().
> Also the usbtouchscreen tries to bind to both device interfaces and it
> fails the second time. How to solve this?
>
> --- drivers/input/touchscreen/usbtouchscreen.c.orig	2009-09-10
> 00:13:59.000000000 +0200
> +++ drivers/input/touchscreen/usbtouchscreen.c	2009-11-09
> 14:39:48.000000000 +0100
> @@ -13,6 +13,7 @@
>   *  - IdealTEK URTC1000
>   *  - General Touch
>   *  - GoTop Super_Q2/GogoPen/PenPower tablets
> + *  - NEXIO/iNexio
>   *
>   * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
>   * Copyright (C) by Todd E. Johnson (mtouchusb.c)
> @@ -118,6 +119,7 @@
>  	DEVTYPE_IDEALTEK,
>  	DEVTYPE_GENERAL_TOUCH,
>  	DEVTYPE_GOTOP,
> +	DEVTYPE_NEXIO,
>  };
>
>  #define USB_DEVICE_HID_CLASS(vend, prod) \
> @@ -191,6 +193,11 @@
>  	{USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
>  #endif
>
> +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
> +	{USB_DEVICE(0x10f0, 0x2002), .driver_info = DEVTYPE_NEXIO},
> +	{USB_DEVICE(0x1870, 0x0001), .driver_info = DEVTYPE_NEXIO},
> +#endif
> +
>  	{}
>  };
>
> @@ -563,6 +570,87 @@
>  }
>  #endif
>
> +/*************************************************************************
>**** + * NEXIO Part
> + */
> +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
> +
> +#define NEXIO_OUTPUT_EP	0x01
> +#define NEXIO_INPUT_EP	0x82
> +#define NEXIO_TIMEOUT	5000
> +#define NEXIO_BUFSIZE	1024
> +
> +static int nexio_init(struct usbtouch_usb *usbtouch)
> +{
> +	struct usb_device *dev = usbtouch->udev;
> +	int ret = -ENOMEM;
> +	int actual_len;
> +	unsigned char *buf;
> +
> +	buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL);
> +	if (!buf)
> +		goto err_nobuf;
> +	printk("1 read\n");
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
> +			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	printk("2 read\n");
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
> +			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	/* Send some command */
> +	printk("3 write \n");
> +	buf[0] = 0x82;
> +	buf[1] = 0x04;
> +	buf[2] = 0x0a;
> +	buf[3] = 0x0f;
> +	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, NEXIO_OUTPUT_EP), buf, 4,
> +			   &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	/* Read it back */
> +	printk("4 read\n");
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
> +			  NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	/* Read firmware version */
> +	printk("5 read\n");
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x82), buf, NEXIO_BUFSIZE,
> +			   &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	buf[buf[1]] = 0;
> +	printk("Firmware version %s\n", &buf[2]);
> +	/* Read device name */
> +	printk("6 read\n");
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x82), buf, NEXIO_BUFSIZE,
> +			   &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	buf[buf[1]] = 0;
> +	printk("Device name %s\n", &buf[2]);
> +	if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
> +		return -EIO;
> +err_out:
> +	kfree(buf);
> +err_nobuf:
> +	return ret;
> +}
> +
> +static int nexio_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
> +{
> +	int i;
> +	printk("nexio_read_data: ");
> +	for (i = 0; i < pkt[1]; i++)
> +		printk("%02X", pkt[i]);
> +
> +	return 0;
> +}
> +#endif
> +
>
> 
> /**************************************************************************
>*** * the different device descriptors
> @@ -702,6 +790,18 @@
>  		.read_data	= gotop_read_data,
>  	},
>  #endif
> +
> +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
> +	[DEVTYPE_NEXIO] = {
> +		.min_xc		= 0x0,
> +		.max_xc		= 0x03ff,
> +		.min_yc		= 0x0,
> +		.max_yc		= 0x03ff,
> +		.rept_size	= 4,
> +		.read_data	= nexio_read_data,
> +		.init		= nexio_init,
> +	},
> +#endif
>  };

Here's another patch. It's getting better - the device does not disconnect
anymore and I get the touch data (but don't know its structure). Either I
don't understand it correctly or the device's USB implementation is broken.
Sending the interrupt URB to endpoint 0x83 but it works with endpoint 0x82.

--- drivers/input/touchscreen/usbtouchscreen.c.orig	2009-09-10 00:13:59.000000000 +0200
+++ drivers/input/touchscreen/usbtouchscreen.c	2009-11-10 13:36:14.000000000 +0100
@@ -13,6 +13,7 @@
  *  - IdealTEK URTC1000
  *  - General Touch
  *  - GoTop Super_Q2/GogoPen/PenPower tablets
+ *  - NEXIO/iNexio
  *
  * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -40,7 +41,7 @@
  *
  *****************************************************************************/
 
-//#define DEBUG
+#define DEBUG
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -118,6 +119,7 @@
 	DEVTYPE_IDEALTEK,
 	DEVTYPE_GENERAL_TOUCH,
 	DEVTYPE_GOTOP,
+	DEVTYPE_NEXIO,
 };
 
 #define USB_DEVICE_HID_CLASS(vend, prod) \
@@ -191,6 +193,15 @@
 	{USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+	/* ignore the comm interface */
+	{USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x02, 0x02, 0x00), .driver_info = DEVTYPE_IGNORE},
+	{USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x02, 0x02, 0x00), .driver_info = DEVTYPE_IGNORE},
+	/* normal device IDs */
+	{USB_DEVICE(0x10f0, 0x2002), .driver_info = DEVTYPE_NEXIO},
+	{USB_DEVICE(0x1870, 0x0001), .driver_info = DEVTYPE_NEXIO},
+#endif
+
 	{}
 };
 
@@ -563,6 +574,94 @@
 }
 #endif
 
+/*****************************************************************************
+ * NEXIO Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+
+#define NEXIO_OUTPUT_EP	0x01
+#define NEXIO_INPUT_EP	0x82
+#define NEXIO_TIMEOUT	5000
+#define NEXIO_BUFSIZE	1024
+#define NEXIO_PKT_LEN	 122
+
+static int nexio_init(struct usbtouch_usb *usbtouch)
+{
+	struct usb_device *dev = usbtouch->udev;
+	int ret = -ENOMEM;
+	int actual_len;
+	unsigned char *buf;
+
+	buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL);
+	if (!buf)
+		goto err_nobuf;
+	printk("1 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	printk("2 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* send some command */
+	printk("3 write \n");
+	buf[0] = 0x82;
+	buf[1] = 0x04;
+	buf[2] = 0x0a;
+	buf[3] = 0x0f;
+	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, NEXIO_OUTPUT_EP), buf, 4,
+			   &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* read it back */
+	printk("4 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			  NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* read firmware version */
+	printk("5 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x82), buf, NEXIO_BUFSIZE,
+			   &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	buf[buf[1]] = 0;
+	printk("Firmware version %s\n", &buf[2]);
+	/* read device name */
+	printk("6 read\n");
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, 0x82), buf, NEXIO_BUFSIZE,
+			   &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	buf[buf[1]] = 0;
+	printk("Device name %s\n", &buf[2]);
+	ret = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
+err_out:
+	kfree(buf);
+err_nobuf:
+	return ret;
+}
+
+static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
+{
+	int i, ret, actual_len;
+	unsigned char ack[2] = { 0xaa, 0x02 };
+	struct usb_device *dev = usbtouch->udev;
+
+	printk("nexio_read_data: ");
+	for (i = 0; i < pkt[1]; i++)
+		printk("%02X ", pkt[i]);
+	/* got touch data? */
+	if (pkt[0] & 0xe0 == 0xe0) {
+		for (i = 0; i < NEXIO_PKT_LEN; i++)
+			printk("%02X ", pkt[i]);
+	}
+	return 0;
+}
+#endif
+
 
 /*****************************************************************************
  * the different device descriptors
@@ -702,6 +801,18 @@
 		.read_data	= gotop_read_data,
 	},
 #endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+	[DEVTYPE_NEXIO] = {
+		.min_xc		= 0x0,
+		.max_xc		= 0x03ff,
+		.min_yc		= 0x0,
+		.max_yc		= 0x03ff,
+		.rept_size	= 128,
+		.read_data	= nexio_read_data,
+		.init		= nexio_init,
+	},
+#endif
 };
 
 
@@ -814,7 +925,7 @@
 {
 	struct usbtouch_usb *usbtouch = urb->context;
 	int retval;
-
+	printk("usbtouch_irq\n");
 	switch (urb->status) {
 	case 0:
 		/* success */
@@ -841,6 +952,7 @@
 
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	printk("new submit_urb\n");
 	if (retval)
 		err("%s - usb_submit_urb failed with result: %d",
 		    __func__, retval);
@@ -960,10 +1072,10 @@
 		                     type->max_press, 0, 0);
 
 	usb_fill_int_urb(usbtouch->irq, usbtouch->udev,
-			 usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress),
+			 usb_rcvintpipe(usbtouch->udev, /*endpoint->bEndpointAddress*/0x82),
 			 usbtouch->data, type->rept_size,
-			 usbtouch_irq, usbtouch, endpoint->bInterval);
-
+			 usbtouch_irq, usbtouch, /*endpoint->bInterval*/255);
+	printk("bEndpointAddress: %d, bInterval %d\n", endpoint->bEndpointAddress, endpoint->bInterval);
 	usbtouch->irq->dev = usbtouch->udev;
 	usbtouch->irq->transfer_dma = usbtouch->data_dma;
 	usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;



-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] NEXIO (or iNexio) support for usbtouchscreen
  2009-11-16 14:14 [PATCH] " Ondrej Zary
@ 2009-11-17 15:25 ` Oliver Neukum
  0 siblings, 0 replies; 4+ messages in thread
From: Oliver Neukum @ 2009-11-17 15:25 UTC (permalink / raw)
  To: Ondrej Zary, linux-usb; +Cc: daniel.ritz, linux-kernel

Am Montag, 16. November 2009 15:14:59 schrieb Ondrej Zary:

Hi,

firstly can you please send patches with -up? It makes them more readable.
> ---

> @@ -92,7 +95,7 @@
>  	dma_addr_t data_dma;
>  	unsigned char *buffer;
>  	int buf_len;
> -	struct urb *irq;
> +	struct urb *irq, *ack;

Where is this urb handled in case of disconnection?

> +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
> +	/* ignore the comm interface */
> +	{USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x02, 0x02, 0x00),
> +		.driver_info = DEVTYPE_IGNORE},
> +	{USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x02, 0x02, 0x00),
> +		.driver_info = DEVTYPE_IGNORE},
> +	/* normal device IDs */
> +	{USB_DEVICE(0x10f0, 0x2002), .driver_info = DEVTYPE_NEXIO},
> +	{USB_DEVICE(0x1870, 0x0001), .driver_info = DEVTYPE_NEXIO},

Why not go for the interfaces you want?

> +static unsigned char nexio_ack[2] = { 0xaa, 0x02 };
> +
> +static int nexio_init(struct usbtouch_usb *usbtouch)
> +{
> +	struct usb_device *dev = usbtouch->udev;
> +	int ret = -ENOMEM;
> +	int actual_len;
> +	unsigned char *buf;
> +	unsigned char init[4] = { 0x82, 0x04, 0x0a, 0x0f };
> +	char *firmware_ver;
> +
> +	buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL);
> +	if (!buf)
> +		goto err_nobuf;
> +	/* two reads */
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
> +			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
> +			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
> +	if (ret < 0)
> +		goto err_out;
> +	/* send init command */
> +	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, NEXIO_OUTPUT_EP), init,
> +			   sizeof(init), &actual_len, NEXIO_TIMEOUT);

DMA on the kernel stack

	Regards
		Oliver



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] NEXIO (or iNexio) support for usbtouchscreen
@ 2009-11-16 14:14 Ondrej Zary
  2009-11-17 15:25 ` Oliver Neukum
  0 siblings, 1 reply; 4+ messages in thread
From: Ondrej Zary @ 2009-11-16 14:14 UTC (permalink / raw)
  To: daniel.ritz; +Cc: linux-kernel

Hello,
this adds support for NEXIO (or iNexio) USB touchscreens to usbtouchscreen
driver. Tested with NEX170MRT 17" LCD monitor with integrated touchscreen
(with xserver-xorg-input-evtouch 0.8.8-1):

T:  Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 54 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=1870 ProdID=0001 Rev= 1.00
S:  Manufacturer=iNexio
S:  Product=iNexio USB
C:* #Ifs= 2 Cfg#= 1 Atr=c0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=00 Driver=(none)
E:  Ad=83(I) Atr=03(Int.) MxPS=   8 Ivl=255ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=(none)
E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms

No datasheet is available, this was written by capturing some data with
SniffUSB in Windows:
http://www.rainbow-software.org/linux_files/nexio/

The device is a bit specific (read: broken) in at least 5 ways:
1. It's very slow to initialize (takes many seconds)
2. The driver must communicate with the device or it disconnects
   (that's why the irq URB is sent during init)
3. The endpoints are mixed up somehow, irq URB works on EP 0x82, the
   first interface with endpoint 0x83 is probably useless
4. It has weird limited multi-touch capability
5. It sends the X and Y range only in touch data, not during initialization


Signed-off-by: Ondrej Zary <linux@rainbow-software.org>

--- linux-source-2.6.31/drivers/input/touchscreen/usbtouchscreen.c.orig	2009-09-10 00:13:59.000000000 +0200
+++ linux-source-2.6.31/drivers/input/touchscreen/usbtouchscreen.c	2009-11-16 14:37:15.000000000 +0100
@@ -13,6 +13,7 @@
  *  - IdealTEK URTC1000
  *  - General Touch
  *  - GoTop Super_Q2/GogoPen/PenPower tablets
+ *  - NEXIO/iNexio
  *
  * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -71,6 +72,8 @@
 	int min_yc, max_yc;
 	int min_press, max_press;
 	int rept_size;
+	bool no_urb_in_open;
+	int endpoint, interval;
 
 	void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
 
@@ -92,7 +95,7 @@
 	dma_addr_t data_dma;
 	unsigned char *buffer;
 	int buf_len;
-	struct urb *irq;
+	struct urb *irq, *ack;
 	struct usb_device *udev;
 	struct input_dev *input;
 	struct usbtouch_device_info *type;
@@ -118,6 +121,7 @@
 	DEVTYPE_IDEALTEK,
 	DEVTYPE_GENERAL_TOUCH,
 	DEVTYPE_GOTOP,
+	DEVTYPE_NEXIO,
 };
 
 #define USB_DEVICE_HID_CLASS(vend, prod) \
@@ -191,6 +195,17 @@
 	{USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+	/* ignore the comm interface */
+	{USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x02, 0x02, 0x00),
+		.driver_info = DEVTYPE_IGNORE},
+	{USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x02, 0x02, 0x00),
+		.driver_info = DEVTYPE_IGNORE},
+	/* normal device IDs */
+	{USB_DEVICE(0x10f0, 0x2002), .driver_info = DEVTYPE_NEXIO},
+	{USB_DEVICE(0x1870, 0x0001), .driver_info = DEVTYPE_NEXIO},
+#endif
+
 	{}
 };
 
@@ -563,6 +578,167 @@
 }
 #endif
 
+/*****************************************************************************
+ * NEXIO Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+
+#define NEXIO_OUTPUT_EP	0x01
+#define NEXIO_INPUT_EP	0x82
+#define NEXIO_TIMEOUT	5000
+#define NEXIO_BUFSIZE	1024
+#define NEXIO_THRESHOLD	50
+
+struct nexio_touch_packet {
+	u8	flags;		/* 0xe1 = touch, 0xe1 = release */
+	__be16	data_len;	/* total bytes of touch data */
+	__be16	x_len;		/* bytes for X axis */
+	__be16	y_len;		/* bytes for Y axis */
+	u8	data[];
+} __attribute__ ((packed));
+
+static unsigned char nexio_ack[2] = { 0xaa, 0x02 };
+
+static int nexio_init(struct usbtouch_usb *usbtouch)
+{
+	struct usb_device *dev = usbtouch->udev;
+	int ret = -ENOMEM;
+	int actual_len;
+	unsigned char *buf;
+	unsigned char init[4] = { 0x82, 0x04, 0x0a, 0x0f };
+	char *firmware_ver;
+
+	buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL);
+	if (!buf)
+		goto err_nobuf;
+	/* two reads */
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* send init command */
+	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, NEXIO_OUTPUT_EP), init,
+			   sizeof(init), &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* read it back */
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			  NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	/* read firmware version */
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0)
+		goto err_out;
+	buf[buf[1]] = 0;	/* second byte is data(string) length */
+	firmware_ver = kstrdup(&buf[2], GFP_KERNEL);
+	/* read device name */
+	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, NEXIO_INPUT_EP), buf,
+			   NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT);
+	if (ret < 0) {
+		kfree(firmware_ver);
+		goto err_out;
+	}
+	buf[buf[1]] = 0;
+	printk(KERN_INFO "Nexio device: %s, firmware version %s\n",
+	       &buf[2], firmware_ver);
+	kfree(firmware_ver);
+
+	/* prepare ACK URB */
+	usbtouch->ack = usb_alloc_urb(0, GFP_KERNEL);
+	if (!usbtouch->ack) {
+		dbg("%s - usb_alloc_urb failed: ack_urb", __func__);
+		return 0;
+	}
+	usb_fill_bulk_urb(usbtouch->ack, usbtouch->udev,
+			 usb_sndbulkpipe(usbtouch->udev, NEXIO_OUTPUT_EP),
+			 nexio_ack, sizeof(nexio_ack), NULL, usbtouch);
+	/* submit first IRQ URB */
+	ret = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
+err_out:
+	kfree(buf);
+err_nobuf:
+	return ret;
+}
+
+static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
+{
+	int x, y, begin_x, begin_y, end_x, end_y, w, h, ret;
+	struct nexio_touch_packet *packet = (void *) pkt;
+
+	/* got touch data? */
+	if ((pkt[0] & 0xe0) != 0xe0)
+		return 0;
+
+	/* send ACK */
+	ret = usb_submit_urb(usbtouch->ack, GFP_KERNEL);
+
+	if (!usbtouch->type->max_xc) {
+		usbtouch->type->max_xc = 2 * be16_to_cpu(packet->x_len);
+		input_set_abs_params(usbtouch->input, ABS_X, 0,
+				     2 * be16_to_cpu(packet->x_len), 0, 0);
+		usbtouch->type->max_yc = 2 * be16_to_cpu(packet->y_len);
+		input_set_abs_params(usbtouch->input, ABS_Y, 0,
+				     2 * be16_to_cpu(packet->y_len), 0, 0);
+	}
+	/* The device reports state of IR sensors on X and Y axes.
+	 * Each byte represents "darkness" percentage (0-100) of one element.
+	 * 17" touchscreen reports only 64 x 52 bytes so the resolution is low.
+	 * This also means that there's a limited multi-touch capability but
+	 * it's disabled (and untested) here as there's no X driver for that.
+	 */
+	begin_x = end_x = begin_y = end_y = -1;
+	for (x = 0; x < be16_to_cpu(packet->x_len); x++) {
+		if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) {
+			begin_x = x;
+			continue;
+		}
+		if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) {
+			end_x = x - 1;
+			for (y = be16_to_cpu(packet->x_len);
+			     y < be16_to_cpu(packet->data_len); y++) {
+				if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) {
+					begin_y = y - be16_to_cpu(packet->x_len);
+					continue;
+				}
+				if (end_y == -1 &&
+				    begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) {
+					end_y = y - 1 - be16_to_cpu(packet->x_len);
+					w = end_x - begin_x;
+					h = end_y - begin_y;
+					/* multi-touch */
+/*					input_report_abs(usbtouch->input,
+						    ABS_MT_TOUCH_MAJOR, max(w,h));
+					input_report_abs(usbtouch->input,
+						    ABS_MT_TOUCH_MINOR, min(x,h));
+					input_report_abs(usbtouch->input,
+						    ABS_MT_POSITION_X, 2*begin_x+w);
+					input_report_abs(usbtouch->input,
+						    ABS_MT_POSITION_Y, 2*begin_y+h);
+					input_report_abs(usbtouch->input,
+						    ABS_MT_ORIENTATION, w > h);
+					input_mt_sync(usbtouch->input);*/
+					/* single touch */
+					usbtouch->x = 2 * begin_x + w;
+					usbtouch->y = 2 * begin_y + h;
+					usbtouch->touch = packet->flags & 0x01;
+					begin_y = end_y = -1;
+					return 1;
+				}
+			}
+			begin_x = end_x = -1;
+		}
+
+	}
+	return 0;
+}
+#endif
+
 
 /*****************************************************************************
  * the different device descriptors
@@ -702,6 +878,17 @@
 		.read_data	= gotop_read_data,
 	},
 #endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
+	[DEVTYPE_NEXIO] = {
+		.rept_size	= 128,
+		.no_urb_in_open = 1,
+		.endpoint	= NEXIO_INPUT_EP,
+		.interval	= 0xff,
+		.read_data	= nexio_read_data,
+		.init		= nexio_init,
+	},
+#endif
 };
 
 
@@ -852,8 +1039,9 @@
 
 	usbtouch->irq->dev = usbtouch->udev;
 
-	if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
-		return -EIO;
+	if (!usbtouch->type->no_urb_in_open)
+		if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
+			return -EIO;
 
 	return 0;
 }
@@ -960,10 +1148,12 @@
 		                     type->max_press, 0, 0);
 
 	usb_fill_int_urb(usbtouch->irq, usbtouch->udev,
-			 usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress),
+			 usb_rcvintpipe(usbtouch->udev,
+					type->endpoint ? type->endpoint
+							: endpoint->bEndpointAddress),
 			 usbtouch->data, type->rept_size,
-			 usbtouch_irq, usbtouch, endpoint->bInterval);
-
+			 usbtouch_irq, usbtouch,
+			 type->interval ? type->interval : endpoint->bInterval);
 	usbtouch->irq->dev = usbtouch->udev;
 	usbtouch->irq->transfer_dma = usbtouch->data_dma;
 	usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -1009,6 +1199,7 @@
 	usb_kill_urb(usbtouch->irq);
 	input_unregister_device(usbtouch->input);
 	usb_free_urb(usbtouch->irq);
+	usb_free_urb(usbtouch->ack);
 	usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
 	kfree(usbtouch);
 }


-- 
Ondrej Zary

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-11-17 15:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-09 14:37 [PATCH] NEXIO (or iNexio) support for usbtouchscreen Ondrej Zary
2009-11-10 13:07 ` [RFC PATCH v2] " Ondrej Zary
2009-11-16 14:14 [PATCH] " Ondrej Zary
2009-11-17 15:25 ` Oliver Neukum

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.