* - PanJit TouchSet
* - eTurboTouch
* - Gunze AHL61
+ * - DMC TSC-10/25
*
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
* - ITM parts are from itmtouch.c
* - 3M parts are from mtouchusb.c
* - PanJit parts are from an unmerged driver by Lanslott Gish
+ * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged
+ * driver from Marius Vollmer
*
*****************************************************************************/
#include <linux/usb/input.h>
-#define DRIVER_VERSION "v0.4"
+#define DRIVER_VERSION "v0.5"
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
#define DRIVER_DESC "USB Touchscreen Driver"
void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
int (*get_pkt_len) (unsigned char *pkt, int len);
- int (*read_data) (unsigned char *pkt, int *x, int *y, int *touch, int *press);
+ int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt);
int (*init) (struct usbtouch_usb *usbtouch);
};
struct usbtouch_device_info *type;
char name[128];
char phys[64];
+
+ int x, y;
+ int touch, press;
};
DEVTYPE_ITM,
DEVTYPE_ETURBO,
DEVTYPE_GUNZE,
+ DEVTYPE_DMC_TSC10,
};
static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
#endif
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+ {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
+#endif
+
{}
};
#define EGALAX_PKT_TYPE_REPT 0x80
#define EGALAX_PKT_TYPE_DIAG 0x0A
-static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
return 0;
- *x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
- *y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
- *touch = pkt[0] & 0x01;
+ dev->x = ((pkt[3] & 0x0F) << 7) | (pkt[4] & 0x7F);
+ dev->y = ((pkt[1] & 0x0F) << 7) | (pkt[2] & 0x7F);
+ dev->touch = pkt[0] & 0x01;
return 1;
}
* PanJit Part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
-static int panjit_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
- *x = ((pkt[2] & 0x0F) << 8) | pkt[1];
- *y = ((pkt[4] & 0x0F) << 8) | pkt[3];
- *touch = pkt[0] & 0x01;
+ dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
+ dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3];
+ dev->touch = pkt[0] & 0x01;
return 1;
}
#define MTOUCHUSB_RESET 7
#define MTOUCHUSB_REQ_CTRLLR_ID 10
-static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
- *x = (pkt[8] << 8) | pkt[7];
- *y = (pkt[10] << 8) | pkt[9];
- *touch = (pkt[2] & 0x40) ? 1 : 0;
+ dev->x = (pkt[8] << 8) | pkt[7];
+ dev->y = (pkt[10] << 8) | pkt[9];
+ dev->touch = (pkt[2] & 0x40) ? 1 : 0;
return 1;
}
* ITM Part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_ITM
-static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
- *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
- *y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
- *press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
- *touch = ~pkt[7] & 0x20;
+ int touch;
+ /*
+ * ITM devices report invalid x/y data if not touched.
+ * if the screen was touched before but is not touched any more
+ * report touch as 0 with the last valid x/y data once. then stop
+ * reporting data until touched again.
+ */
+ dev->press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F);
+
+ touch = ~pkt[7] & 0x20;
+ if (!touch) {
+ if (dev->touch) {
+ dev->touch = 0;
+ return 1;
+ }
+
+ return 0;
+ }
+
+ dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
+ dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
+ dev->touch = touch;
- return *touch;
+ return 1;
}
#endif
* eTurboTouch part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
-static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
unsigned int shift;
return 0;
shift = (6 - (pkt[0] & 0x03));
- *x = ((pkt[3] << 7) | pkt[4]) >> shift;
- *y = ((pkt[1] << 7) | pkt[2]) >> shift;
- *touch = (pkt[0] & 0x10) ? 1 : 0;
+ dev->x = ((pkt[3] << 7) | pkt[4]) >> shift;
+ dev->y = ((pkt[1] << 7) | pkt[2]) >> shift;
+ dev->touch = (pkt[0] & 0x10) ? 1 : 0;
return 1;
}
* Gunze part
*/
#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
-static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
return 0;
- *x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
- *y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
- *touch = pkt[0] & 0x20;
+ dev->x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
+ dev->y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
+ dev->touch = pkt[0] & 0x20;
+
+ return 1;
+}
+#endif
+
+/*****************************************************************************
+ * DMC TSC-10/25 Part
+ *
+ * Documentation about the controller and it's protocol can be found at
+ * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
+ * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+
+/* supported data rates. currently using 130 */
+#define TSC10_RATE_POINT 0x50
+#define TSC10_RATE_30 0x40
+#define TSC10_RATE_50 0x41
+#define TSC10_RATE_80 0x42
+#define TSC10_RATE_100 0x43
+#define TSC10_RATE_130 0x44
+#define TSC10_RATE_150 0x45
+
+/* commands */
+#define TSC10_CMD_RESET 0x55
+#define TSC10_CMD_RATE 0x05
+#define TSC10_CMD_DATA1 0x01
+
+static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+{
+ struct usb_device *dev = usbtouch->udev;
+ int ret;
+ unsigned char buf[2];
+
+ /* reset */
+ buf[0] = buf[1] = 0xFF;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_RESET,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ if (buf[0] != 0x06 || buf[1] != 0x00)
+ return -ENODEV;
+
+ /* set coordinate output rate */
+ buf[0] = buf[1] = 0xFF;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_RATE,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ if (buf[0] != 0x06 || buf[1] != 0x00)
+ return -ENODEV;
+
+ /* start sending data */
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_DATA1,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ dev->x = ((pkt[2] & 0x03) << 8) | pkt[1];
+ dev->y = ((pkt[4] & 0x03) << 8) | pkt[3];
+ dev->touch = pkt[0] & 0x01;
return 1;
}
#endif
+
/*****************************************************************************
* the different device descriptors
*/
.read_data = gunze_read_data,
},
#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+ [DEVTYPE_DMC_TSC10] = {
+ .min_xc = 0x0,
+ .max_xc = 0x03ff,
+ .min_yc = 0x0,
+ .max_yc = 0x03ff,
+ .rept_size = 5,
+ .init = dmc_tsc10_init,
+ .read_data = dmc_tsc10_read_data,
+ },
+#endif
};
static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
unsigned char *pkt, int len)
{
- int x, y, touch, press;
struct usbtouch_device_info *type = usbtouch->type;
- if (!type->read_data(pkt, &x, &y, &touch, &press))
+ if (!type->read_data(usbtouch, pkt))
return;
- input_report_key(usbtouch->input, BTN_TOUCH, touch);
+ input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch);
if (swap_xy) {
- input_report_abs(usbtouch->input, ABS_X, y);
- input_report_abs(usbtouch->input, ABS_Y, x);
+ input_report_abs(usbtouch->input, ABS_X, usbtouch->y);
+ input_report_abs(usbtouch->input, ABS_Y, usbtouch->x);
} else {
- input_report_abs(usbtouch->input, ABS_X, x);
- input_report_abs(usbtouch->input, ABS_Y, y);
+ input_report_abs(usbtouch->input, ABS_X, usbtouch->x);
+ input_report_abs(usbtouch->input, ABS_Y, usbtouch->y);
}
if (type->max_press)
- input_report_abs(usbtouch->input, ABS_PRESSURE, press);
+ input_report_abs(usbtouch->input, ABS_PRESSURE, usbtouch->press);
input_sync(usbtouch->input);
}
type->process_pkt = usbtouch_process_pkt;
usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
- SLAB_KERNEL, &usbtouch->data_dma);
+ GFP_KERNEL, &usbtouch->data_dma);
if (!usbtouch->data)
goto out_free;
type->max_press, 0, 0);
usb_fill_int_urb(usbtouch->irq, usbtouch->udev,
- usb_rcvintpipe(usbtouch->udev, 0x81),
+ usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress),
usbtouch->data, type->rept_size,
usbtouch_irq, usbtouch, endpoint->bInterval);