Release 4.11 drivers/input/touchscreen/usbtouchscreen.c
/******************************************************************************
* usbtouchscreen.c
* Driver for USB Touchscreens, supporting those devices:
* - eGalax Touchkit
* includes eTurboTouch CT-410/510/700
* - 3M/Microtouch EX II series
* - ITM
* - PanJit TouchSet
* - eTurboTouch
* - Gunze AHL61
* - DMC TSC-10/25
* - IRTOUCHSYSTEMS/UNITOP
* - IdealTEK URTC1000
* - General Touch
* - GoTop Super_Q2/GogoPen/PenPower tablets
* - JASTEC USB touch controller/DigiTech DTR-02U
* - Zytronic capacitive touchscreen
* - NEXIO/iNexio
* - Elo TouchSystems 2700 IntelliTouch
* - EasyTouch USB Dual/Multi touch controller from Data Modul
*
* Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Driver is based on touchkitusb.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
*
*****************************************************************************/
//#define DEBUG
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
#define DRIVER_VERSION "v0.6"
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
#define DRIVER_DESC "USB Touchscreen Driver"
static bool swap_xy;
module_param(swap_xy, bool, 0644);
MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
static bool hwcalib_xy;
module_param(hwcalib_xy, bool, 0644);
MODULE_PARM_DESC(hwcalib_xy, "If set hw-calibrated X/Y are used if available");
/* device specifc data/functions */
struct usbtouch_usb;
struct usbtouch_device_info {
int min_xc, max_xc;
int min_yc, max_yc;
int min_press, max_press;
int rept_size;
/*
* Always service the USB devices irq not just when the input device is
* open. This is useful when devices have a watchdog which prevents us
* from periodically polling the device. Leave this unset unless your
* touchscreen device requires it, as it does consume more of the USB
* bandwidth.
*/
bool irq_always;
void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len);
/*
* used to get the packet len. possible return values:
* > 0: packet len
* = 0: skip one byte
* < 0: -return value more bytes needed
*/
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);
};
/* a usbtouch device */
struct usbtouch_usb {
unsigned char *data;
dma_addr_t data_dma;
int data_size;
unsigned char *buffer;
int buf_len;
struct urb *irq;
struct usb_interface *interface;
struct input_dev *input;
struct usbtouch_device_info *type;
char name[128];
char phys[64];
void *priv;
int x, y;
int touch, press;
};
/* device types */
enum {
DEVTYPE_IGNORE = -1,
DEVTYPE_EGALAX,
DEVTYPE_PANJIT,
DEVTYPE_3M,
DEVTYPE_ITM,
DEVTYPE_ETURBO,
DEVTYPE_GUNZE,
DEVTYPE_DMC_TSC10,
DEVTYPE_IRTOUCH,
DEVTYPE_IRTOUCH_HIRES,
DEVTYPE_IDEALTEK,
DEVTYPE_GENERAL_TOUCH,
DEVTYPE_GOTOP,
DEVTYPE_JASTEC,
DEVTYPE_E2I,
DEVTYPE_ZYTRONIC,
DEVTYPE_TC45USB,
DEVTYPE_NEXIO,
DEVTYPE_ELO,
DEVTYPE_ETOUCH,
};
#define USB_DEVICE_HID_CLASS(vend, prod) \
.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \
| USB_DEVICE_ID_MATCH_DEVICE, \
.idVendor = (vend), \
.idProduct = (prod), \
.bInterfaceClass = USB_INTERFACE_CLASS_HID
static const struct usb_device_id usbtouch_devices[] = {
#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
/* ignore the HID capable devices, handled by usbhid */
{USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},
{USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE},
/* normal device IDs */
{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
{USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT},
{USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT},
{USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT},
{USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_3M
{USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_ITM
{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
{USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
{USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
{USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
{USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
{USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK
{USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH
{USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP
{USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP},
{USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP},
{USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC
{USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_E2I
{USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC
{USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB
/* TC5UH */
{USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB},
/* TC4UM */
{USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
/* data interface only */
{USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00),
.driver_info = DEVTYPE_NEXIO},
{USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00),
.driver_info = DEVTYPE_NEXIO},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_ELO
{USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO},
#endif
#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
{USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH},
#endif
{}
};
/*****************************************************************************
* e2i Part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_E2I
static int e2i_init(struct usbtouch_usb *usbtouch)
{
int ret;
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
0x01, 0x02, 0x0000, 0x0081,
NULL, 0, USB_CTRL_SET_TIMEOUT);
dev_dbg(&usbtouch->interface->dev,
"%s - usb_control_msg - E2I_RESET - bytes|err: %d\n",
__func__, ret);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Florian Echtler | 52 | 71.23% | 1 | 25.00% |
Ondrej Zary | 12 | 16.44% | 1 | 25.00% |
Greg Kroah-Hartman | 9 | 12.33% | 2 | 50.00% |
Total | 73 | 100.00% | 4 | 100.00% |
static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
int tmp = (pkt[0] << 8) | pkt[1];
dev->x = (pkt[2] << 8) | pkt[3];
dev->y = (pkt[4] << 8) | pkt[5];
tmp = tmp - 0xA000;
dev->touch = (tmp > 0);
dev->press = (tmp > 0 ? tmp : 0);
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Florian Echtler | 102 | 100.00% | 1 | 100.00% |
Total | 102 | 100.00% | 1 | 100.00% |
#endif
/*****************************************************************************
* eGalax part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
#ifndef MULTI_PACKET
#define MULTI_PACKET
#endif
#define EGALAX_PKT_TYPE_MASK 0xFE
#define EGALAX_PKT_TYPE_REPT 0x80
#define EGALAX_PKT_TYPE_DIAG 0x0A
static int egalax_init(struct usbtouch_usb *usbtouch)
{
int ret, i;
unsigned char *buf;
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
/*
* An eGalax diagnostic packet kicks the device into using the right
* protocol. We send a "check active" packet. The response will be
* read later and ignored.
*/
buf = kmalloc(3, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf[0] = EGALAX_PKT_TYPE_DIAG;
buf[1] = 1; /* length */
buf[2] = 'A'; /* command - check active */
for (i = 0; i < 3; i++) {
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, 0, buf, 3,
USB_CTRL_SET_TIMEOUT);
if (ret >= 0) {
ret = 0;
break;
}
if (ret != -EPIPE)
break;
}
kfree(buf);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Forest Bond | 151 | 100.00% | 1 | 100.00% |
Total | 151 | 100.00% | 1 | 100.00% |
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;
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;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 98 | 100.00% | 2 | 100.00% |
Total | 98 | 100.00% | 2 | 100.00% |
static int egalax_get_pkt_len(unsigned char *buf, int len)
{
switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
case EGALAX_PKT_TYPE_REPT:
return 5;
case EGALAX_PKT_TYPE_DIAG:
if (len < 2)
return -1;
return buf[1] + 2;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 55 | 100.00% | 2 | 100.00% |
Total | 55 | 100.00% | 2 | 100.00% |
#endif
/*****************************************************************************
* EasyTouch part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH
#ifndef MULTI_PACKET
#define MULTI_PACKET
#endif
#define ETOUCH_PKT_TYPE_MASK 0xFE
#define ETOUCH_PKT_TYPE_REPT 0x80
#define ETOUCH_PKT_TYPE_REPT2 0xB0
#define ETOUCH_PKT_TYPE_DIAG 0x0A
static int etouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if ((pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT &&
(pkt[0] & ETOUCH_PKT_TYPE_MASK) != ETOUCH_PKT_TYPE_REPT2)
return 0;
dev->x = ((pkt[1] & 0x1F) << 7) | (pkt[2] & 0x7F);
dev->y = ((pkt[3] & 0x1F) << 7) | (pkt[4] & 0x7F);
dev->touch = pkt[0] & 0x01;
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Armando Visconti | 109 | 100.00% | 1 | 100.00% |
Total | 109 | 100.00% | 1 | 100.00% |
static int etouch_get_pkt_len(unsigned char *buf, int len)
{
switch (buf[0] & ETOUCH_PKT_TYPE_MASK) {
case ETOUCH_PKT_TYPE_REPT:
case ETOUCH_PKT_TYPE_REPT2:
return 5;
case ETOUCH_PKT_TYPE_DIAG:
if (len < 2)
return -1;
return buf[1] + 2;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Armando Visconti | 58 | 100.00% | 1 | 100.00% |
Total | 58 | 100.00% | 1 | 100.00% |
#endif
/*****************************************************************************
* PanJit Part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3];
dev->touch = pkt[0] & 0x01;
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 74 | 100.00% | 3 | 100.00% |
Total | 74 | 100.00% | 3 | 100.00% |
#endif
/*****************************************************************************
* 3M/Microtouch Part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_3M
#define MTOUCHUSB_ASYNC_REPORT 1
#define MTOUCHUSB_RESET 7
#define MTOUCHUSB_REQ_CTRLLR_ID 10
static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if (hwcalib_xy) {
dev->x = (pkt[4] << 8) | pkt[3];
dev->y = 0xffff - ((pkt[6] << 8) | pkt[5]);
} else {
dev->x = (pkt[8] << 8) | pkt[7];
dev->y = (pkt[10] << 8) | pkt[9];
}
dev->touch = (pkt[2] & 0x40) ? 1 : 0;
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 72 | 59.50% | 3 | 75.00% |
Dan Streetman | 49 | 40.50% | 1 | 25.00% |
Total | 121 | 100.00% | 4 | 100.00% |
static int mtouch_init(struct usbtouch_usb *usbtouch)
{
int ret, i;
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_RESET,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
dev_dbg(&usbtouch->interface->dev,
"%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d\n",
__func__, ret);
if (ret < 0)
return ret;
msleep(150);
for (i = 0; i < 3; i++) {
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
MTOUCHUSB_ASYNC_REPORT,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
dev_dbg(&usbtouch->interface->dev,
"%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d\n",
__func__, ret);
if (ret >= 0)
break;
if (ret != -EPIPE)
return ret;
}
/* Default min/max xy are the raw values, override if using hw-calib */
if (hwcalib_xy) {
input_set_abs_params(usbtouch->input, ABS_X, 0, 0xffff, 0, 0);
input_set_abs_params(usbtouch->input, ABS_Y, 0, 0xffff, 0, 0);
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 141 | 65.89% | 2 | 28.57% |
Dan Streetman | 41 | 19.16% | 1 | 14.29% |
Greg Kroah-Hartman | 18 | 8.41% | 2 | 28.57% |
Ondrej Zary | 12 | 5.61% | 1 | 14.29% |
Harvey Harrison | 2 | 0.93% | 1 | 14.29% |
Total | 214 | 100.00% | 7 | 100.00% |
#endif
/*****************************************************************************
* ITM Part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_ITM
static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
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 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 144 | 100.00% | 3 | 100.00% |
Total | 144 | 100.00% | 3 | 100.00% |
#endif
/*****************************************************************************
* eTurboTouch part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
#ifndef MULTI_PACKET
#define MULTI_PACKET
#endif
static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
unsigned int shift;
/* packets should start with sync */
if (!(pkt[0] & 0x80))
return 0;
shift = (6 - (pkt[0] & 0x03));
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;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 115 | 100.00% | 3 | 100.00% |
Total | 115 | 100.00% | 3 | 100.00% |
static int eturbo_get_pkt_len(unsigned char *buf, int len)
{
if (buf[0] & 0x80)
return 5;
if (buf[0] == 0x01)
return 3;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 41 | 100.00% | 2 | 100.00% |
Total | 41 | 100.00% | 2 | 100.00% |
#endif
/*****************************************************************************
* Gunze part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
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;
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;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Ritz | 118 | 100.00% | 3 | 100.00% |
Total | 118 | 100.00% | 3 | 100.00% |
#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_TOUCHSCREEN_USB_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 = interface_to_usbdev(usbtouch->interface);
int ret = -ENOMEM;
unsigned char *buf;
buf = kmalloc(2, GFP_NOIO);
if (!buf)
goto err_nobuf;
/* 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)
goto err_out;
if (buf[0] != 0x06) {
ret = -ENODEV;
goto err_out;
}
/* TSC-25 data sheet specifies a delay after the RESET command */
msleep(150);
/* 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)
goto err_out;
if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) {
ret = -ENODEV;
goto err_out;
}
/* 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);
err_out:
kfree(buf);
err_nobuf:
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Holger Schurig | 186 | 69.92% | 1 | 16.67% |
Oliver Neukum | 52 | 19.55% | 2 | 33.33% |
Daniel Ritz | 18 | 6.77% | 1 | 16.67% |
Bernhard Bender | 6 | 2.26% | 1 | 16.67% |
Ondrej Zary | 4 | 1.50% | 1 | 16.67% |
Total | 266 | 100.00% | 6 | 100.00% |
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;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Holger Schurig | 63 | 85.14% | 1 | 50.00% |
Daniel Ritz | 11 | 14.86% | 1 | |