X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Finput%2Ftouchscreen%2Fusbtouchscreen.c;h=792b2708a137ccfc2165b90e5a8a5cc33cc09f8c;hb=15439dd37f92f930ac7fc65a4f261834e4215bb0;hp=9fb3d5c309998162c5f14d40c6587e95c95395a5;hpb=fb9fc395174138983a49f2da982ed14caabbe741;p=linux-2.6 diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 9fb3d5c309..792b2708a1 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -11,8 +11,10 @@ * - DMC TSC-10/25 * - IRTOUCHSYSTEMS/UNITOP * - IdealTEK URTC1000 + * - General Touch + * - GoTop Super_Q2/GogoPen/PenPower tablets * - * Copyright (C) 2004-2006 by Daniel Ritz + * Copyright (C) 2004-2007 by Daniel Ritz * Copyright (C) by Todd E. Johnson (mtouchusb.c) * * This program is free software; you can redistribute it and/or @@ -49,7 +51,7 @@ #include -#define DRIVER_VERSION "v0.5" +#define DRIVER_VERSION "v0.6" #define DRIVER_AUTHOR "Daniel Ritz " #define DRIVER_DESC "USB Touchscreen Driver" @@ -64,17 +66,21 @@ struct usbtouch_device_info { int min_yc, max_yc; int min_press, max_press; int rept_size; - int flags; 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 (*init) (struct usbtouch_usb *usbtouch); }; -#define USBTOUCH_FLG_BUFFER 0x01 - - /* a usbtouch device */ struct usbtouch_usb { unsigned char *data; @@ -93,15 +99,6 @@ struct usbtouch_usb { }; -#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO) || defined(CONFIG_TOUCHSCREEN_USB_IDEALTEK) -#define MULTI_PACKET -#endif - -#ifdef MULTI_PACKET -static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len); -#endif - /* device types */ enum { DEVTPYE_DUMMY = -1, @@ -115,6 +112,7 @@ enum { DEVTYPE_IRTOUCH, DEVTYPE_IDEALTEK, DEVTYPE_GENERAL_TOUCH, + DEVTYPE_GOTOP, }; static struct usb_device_id usbtouch_devices[] = { @@ -168,6 +166,12 @@ static struct usb_device_id usbtouch_devices[] = { {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 + {} }; @@ -178,6 +182,10 @@ static struct usb_device_id usbtouch_devices[] = { #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 @@ -254,7 +262,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", - __FUNCTION__, ret); + __func__, ret); if (ret < 0) return ret; msleep(150); @@ -265,7 +273,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", - __FUNCTION__, ret); + __func__, ret); if (ret >= 0) break; if (ret != -EPIPE) @@ -315,6 +323,9 @@ static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) * 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; @@ -385,9 +396,12 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) { struct usb_device *dev = usbtouch->udev; - int ret; - unsigned char buf[2]; + int ret = -ENOMEM; + unsigned char *buf; + buf = kmalloc(2, GFP_KERNEL); + if (!buf) + goto err_nobuf; /* reset */ buf[0] = buf[1] = 0xFF; ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), @@ -395,9 +409,11 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) 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; + goto err_out; + if (buf[0] != 0x06 || buf[1] != 0x00) { + ret = -ENODEV; + goto err_out; + } /* set coordinate output rate */ buf[0] = buf[1] = 0xFF; @@ -406,20 +422,22 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); if (ret < 0) - return ret; + goto err_out; if ((buf[0] != 0x06 || buf[1] != 0x00) && - (buf[0] != 0x15 || buf[1] != 0x01)) - return -ENODEV; + (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); - if (ret < 0) - return ret; - - return 0; +err_out: + kfree(buf); +err_nobuf: + return ret; } @@ -453,6 +471,9 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) * IdealTEK URTC1000 Part */ #ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK +#ifndef MULTI_PACKET +#define MULTI_PACKET +#endif static int idealtek_get_pkt_len(unsigned char *buf, int len) { if (buf[0] & 0x80) @@ -500,9 +521,28 @@ static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) } #endif +/***************************************************************************** + * GoTop Part + */ +#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP +static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) +{ + dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; + dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; + dev->touch = pkt[0] & 0x01; + return 1; +} +#endif + + /***************************************************************************** * the different device descriptors */ +#ifdef MULTI_PACKET +static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, + unsigned char *pkt, int len); +#endif + static struct usbtouch_device_info usbtouch_dev_info[] = { #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX [DEVTYPE_EGALAX] = { @@ -511,7 +551,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .min_yc = 0x0, .max_yc = 0x07ff, .rept_size = 16, - .flags = USBTOUCH_FLG_BUFFER, .process_pkt = usbtouch_process_multi, .get_pkt_len = egalax_get_pkt_len, .read_data = egalax_read_data, @@ -560,7 +599,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .min_yc = 0x0, .max_yc = 0x07ff, .rept_size = 8, - .flags = USBTOUCH_FLG_BUFFER, .process_pkt = usbtouch_process_multi, .get_pkt_len = eturbo_get_pkt_len, .read_data = eturbo_read_data, @@ -608,7 +646,6 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .min_yc = 0x0, .max_yc = 0x0fff, .rept_size = 8, - .flags = USBTOUCH_FLG_BUFFER, .process_pkt = usbtouch_process_multi, .get_pkt_len = idealtek_get_pkt_len, .read_data = idealtek_read_data, @@ -623,9 +660,19 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .max_yc = 0x0500, .rept_size = 7, .read_data = general_touch_read_data, - } + }, #endif +#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP + [DEVTYPE_GOTOP] = { + .min_xc = 0x0, + .max_xc = 0x03ff, + .min_yc = 0x0, + .max_yc = 0x03ff, + .rept_size = 4, + .read_data = gotop_read_data, + }, +#endif }; @@ -706,11 +753,14 @@ static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, pos = 0; while (pos < buf_len) { /* get packet len */ - pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len); + pkt_len = usbtouch->type->get_pkt_len(buffer + pos, + buf_len - pos); - /* unknown packet: drop everything */ - if (unlikely(!pkt_len)) - goto out_flush_buf; + /* unknown packet: skip one byte */ + if (unlikely(!pkt_len)) { + pos++; + continue; + } /* full packet: process */ if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) { @@ -743,18 +793,18 @@ static void usbtouch_irq(struct urb *urb) case -ETIME: /* this urb is timing out */ dbg("%s - urb timed out - was the device unplugged?", - __FUNCTION__); + __func__); return; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", - __FUNCTION__, urb->status); + __func__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); + __func__, urb->status); goto exit; } @@ -764,7 +814,7 @@ exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) err("%s - usb_submit_urb failed with result: %d", - __FUNCTION__, retval); + __func__, retval); } static int usbtouch_open(struct input_dev *input) @@ -825,7 +875,7 @@ static int usbtouch_probe(struct usb_interface *intf, if (!usbtouch->data) goto out_free; - if (type->flags & USBTOUCH_FLG_BUFFER) { + if (type->get_pkt_len) { usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); if (!usbtouch->buffer) goto out_free_buffers; @@ -833,7 +883,7 @@ static int usbtouch_probe(struct usb_interface *intf, usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); if (!usbtouch->irq) { - dbg("%s - usb_alloc_urb failed: usbtouch->irq", __FUNCTION__); + dbg("%s - usb_alloc_urb failed: usbtouch->irq", __func__); goto out_free_buffers; } @@ -868,8 +918,8 @@ static int usbtouch_probe(struct usb_interface *intf, input_dev->open = usbtouch_open; input_dev->close = usbtouch_close; - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(input_dev, ABS_X, type->min_xc, type->max_xc, 0, 0); input_set_abs_params(input_dev, ABS_Y, type->min_yc, type->max_yc, 0, 0); if (type->max_press) @@ -889,14 +939,14 @@ static int usbtouch_probe(struct usb_interface *intf, if (type->init) { err = type->init(usbtouch); if (err) { - dbg("%s - type->init() failed, err: %d", __FUNCTION__, err); + dbg("%s - type->init() failed, err: %d", __func__, err); goto out_free_buffers; } } err = input_register_device(usbtouch->input); if (err) { - dbg("%s - input_register_device failed, err: %d", __FUNCTION__, err); + dbg("%s - input_register_device failed, err: %d", __func__, err); goto out_free_buffers; } @@ -916,12 +966,12 @@ static void usbtouch_disconnect(struct usb_interface *intf) { struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); - dbg("%s - called", __FUNCTION__); + dbg("%s - called", __func__); if (!usbtouch) return; - dbg("%s - usbtouch is initialized, cleaning up", __FUNCTION__); + dbg("%s - usbtouch is initialized, cleaning up", __func__); usb_set_intfdata(intf, NULL); usb_kill_urb(usbtouch->irq); input_unregister_device(usbtouch->input);