Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 183117
b: refs/heads/master
c: 5197424
h: refs/heads/master
i:
  183115: bddf395
v: v3
  • Loading branch information
Ondrej Zary authored and Dmitry Torokhov committed Feb 4, 2010
1 parent c5c0465 commit fdf9e10
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f4a5e359c4bafc2269766ccd74256024160ed7ac
refs/heads/master: 5197424cdcccd2b0b1922babb93969b2515c43ce
5 changes: 5 additions & 0 deletions trunk/drivers/input/touchscreen/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,11 @@ config TOUCHSCREEN_USB_ETT_TC5UH
bool "ET&T TC5UH touchscreen controler support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE

config TOUCHSCREEN_USB_NEXIO
default y
bool "NEXIO/iNexio device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE

config TOUCHSCREEN_TOUCHIT213
tristate "Sahara TouchIT-213 touchscreen"
select SERIO
Expand Down
261 changes: 259 additions & 2 deletions trunk/drivers/input/touchscreen/usbtouchscreen.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* - GoTop Super_Q2/GogoPen/PenPower tablets
* - JASTEC USB touch controller/DigiTech DTR-02U
* - Zytronic capacitive touchscreen
* - NEXIO/iNexio
*
* Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
Expand Down Expand Up @@ -95,6 +96,7 @@ struct usbtouch_device_info {

int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt);
int (*init) (struct usbtouch_usb *usbtouch);
void (*exit) (struct usbtouch_usb *usbtouch);
};

/* a usbtouch device */
Expand All @@ -109,6 +111,7 @@ struct usbtouch_usb {
struct usbtouch_device_info *type;
char name[128];
char phys[64];
void *priv;

int x, y;
int touch, press;
Expand All @@ -133,6 +136,7 @@ enum {
DEVTYPE_E2I,
DEVTYPE_ZYTRONIC,
DEVTYPE_TC5UH,
DEVTYPE_NEXIO,
};

#define USB_DEVICE_HID_CLASS(vend, prod) \
Expand Down Expand Up @@ -222,6 +226,14 @@ static const struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC5UH},
#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

{}
};

Expand Down Expand Up @@ -691,6 +703,229 @@ static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
}
#endif

/*****************************************************************************
* NEXIO Part
*/
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO

#define NEXIO_TIMEOUT 5000
#define NEXIO_BUFSIZE 1024
#define NEXIO_THRESHOLD 50

struct nexio_priv {
struct urb *ack;
unsigned char *ack_buf;
};

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_pkt[2] = { 0xaa, 0x02 };
static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f };

static void nexio_ack_complete(struct urb *urb)
{
}

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;
int ret = -ENOMEM;
int actual_len, i;
unsigned char *buf;
char *firmware_ver = NULL, *device_name = NULL;
int input_ep = 0, output_ep = 0;

/* find first input and output endpoint */
for (i = 0; i < interface->desc.bNumEndpoints; i++) {
if (!input_ep &&
usb_endpoint_dir_in(&interface->endpoint[i].desc))
input_ep = interface->endpoint[i].desc.bEndpointAddress;
if (!output_ep &&
usb_endpoint_dir_out(&interface->endpoint[i].desc))
output_ep = interface->endpoint[i].desc.bEndpointAddress;
}
if (!input_ep || !output_ep)
return -ENXIO;

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

/* two empty reads */
for (i = 0; i < 2; i++) {
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep),
buf, NEXIO_BUFSIZE, &actual_len,
NEXIO_TIMEOUT);
if (ret < 0)
goto out_buf;
}

/* send init command */
memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt));
ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep),
buf, sizeof(nexio_init_pkt), &actual_len,
NEXIO_TIMEOUT);
if (ret < 0)
goto out_buf;

/* read replies */
for (i = 0; i < 3; i++) {
memset(buf, 0, NEXIO_BUFSIZE);
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep),
buf, NEXIO_BUFSIZE, &actual_len,
NEXIO_TIMEOUT);
if (ret < 0 || actual_len < 1 || buf[1] != actual_len)
continue;
switch (buf[0]) {
case 0x83: /* firmware version */
if (!firmware_ver)
firmware_ver = kstrdup(&buf[2], GFP_KERNEL);
break;
case 0x84: /* device name */
if (!device_name)
device_name = kstrdup(&buf[2], GFP_KERNEL);
break;
}
}

printk(KERN_INFO "Nexio device: %s, firmware version: %s\n",
device_name, firmware_ver);

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 = kmalloc(sizeof(nexio_ack_pkt), GFP_KERNEL);
if (!priv->ack_buf)
goto err_priv;

memcpy(priv->ack_buf, nexio_ack_pkt, sizeof(nexio_ack_pkt));

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;
}

static void nexio_exit(struct usbtouch_usb *usbtouch)
{
struct nexio_priv *priv = usbtouch->priv;

usb_kill_urb(priv->ack);
usb_free_urb(priv->ack);
kfree(priv->ack_buf);
kfree(priv);
}

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;
struct nexio_priv *priv = usbtouch->priv;

/* got touch data? */
if ((pkt[0] & 0xe0) != 0xe0)
return 0;

/* send ACK */
ret = usb_submit_urb(priv->ack, GFP_ATOMIC);

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;
#if 0
/* 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);
#endif
/* 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
*/
Expand Down Expand Up @@ -875,6 +1110,16 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = tc5uh_read_data,
},
#endif

#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
[DEVTYPE_NEXIO] = {
.rept_size = 128,
.irq_always = true,
.read_data = nexio_read_data,
.init = nexio_init,
.exit = nexio_exit,
},
#endif
};


Expand Down Expand Up @@ -1000,6 +1245,7 @@ static void usbtouch_irq(struct urb *urb)
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
case -EPIPE:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
__func__, urb->status);
Expand Down Expand Up @@ -1146,10 +1392,16 @@ static int usbtouch_probe(struct usb_interface *intf,
input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
type->max_press, 0, 0);

usb_fill_int_urb(usbtouch->irq, udev,
if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
usb_fill_int_urb(usbtouch->irq, udev,
usb_rcvintpipe(udev, endpoint->bEndpointAddress),
usbtouch->data, type->rept_size,
usbtouch_irq, usbtouch, endpoint->bInterval);
else
usb_fill_bulk_urb(usbtouch->irq, udev,
usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
usbtouch->data, type->rept_size,
usbtouch_irq, usbtouch);

usbtouch->irq->dev = udev;
usbtouch->irq->transfer_dma = usbtouch->data_dma;
Expand All @@ -1167,7 +1419,7 @@ static int usbtouch_probe(struct usb_interface *intf,
err = input_register_device(usbtouch->input);
if (err) {
dbg("%s - input_register_device failed, err: %d", __func__, err);
goto out_free_buffers;
goto out_do_exit;
}

usb_set_intfdata(intf, usbtouch);
Expand All @@ -1177,6 +1429,9 @@ static int usbtouch_probe(struct usb_interface *intf,

return 0;

out_do_exit:
if (type->exit)
type->exit(usbtouch);
out_free_buffers:
usbtouch_free_buffers(udev, usbtouch);
out_free:
Expand All @@ -1199,6 +1454,8 @@ static void usbtouch_disconnect(struct usb_interface *intf)
/* this will stop IO via close */
input_unregister_device(usbtouch->input);
usb_free_urb(usbtouch->irq);
if (usbtouch->type->exit)
usbtouch->type->exit(usbtouch);
usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
kfree(usbtouch);
}
Expand Down

0 comments on commit fdf9e10

Please sign in to comment.