open/close race conditions fixed, get_unaligned_be16 removed

This commit is contained in:
Ondra Havel 2012-01-23 01:36:01 +01:00
parent 7d86a5ff35
commit 614a2aa30e
2 changed files with 23 additions and 20 deletions

6
README
View File

@ -1,9 +1,9 @@
Hanvon tablet driver Hanvon tablet driver
==================== ====================
Driver for Linux kernels which supports complete functionality of the tablet: Linux kernel driver for some Hanvon tablet usb models. Following functionality
pen coordinates, touch/float/click detection, pressure, x and y tilt, pen is covered. pen coordinates, touch/float/click detection, pressure, x and y
button. On Artmaster I four simple tablet buttons (note that the first tilt, pen button. On Artmaster I four simple tablet buttons (note that the first
one works only together with pen activity), and the slider button. one works only together with pen activity), and the slider button.

View File

@ -3,9 +3,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/usb/input.h> #include <linux/usb/input.h>
#include <asm/unaligned.h>
#define DRIVER_VERSION "0.4" #define DRIVER_VERSION "0.4a"
#define DRIVER_AUTHOR "Ondra Havel <ondra.havel@gmail.com>" #define DRIVER_AUTHOR "Ondra Havel <ondra.havel@gmail.com>"
#define DRIVER_DESC "USB Hanvon tablet driver" #define DRIVER_DESC "USB Hanvon tablet driver"
#define DRIVER_LICENSE "GPL" #define DRIVER_LICENSE "GPL"
@ -35,6 +34,7 @@ static int rbuttons[]={BTN_4,BTN_5,BTN_6,BTN_7}; /* reported on AM1107+ */
struct hanvon { struct hanvon {
unsigned char *data; unsigned char *data;
dma_addr_t data_dma; dma_addr_t data_dma;
struct mutex mutex;
struct input_dev *dev; struct input_dev *dev;
struct usb_device *usbdev; struct usb_device *usbdev;
struct urb *irq; struct urb *irq;
@ -91,14 +91,13 @@ static void hanvon_irq(struct urb *urb)
if(data[3]==0xaa) /* right side (am1107, am1209) */ if(data[3]==0xaa) /* right side (am1107, am1209) */
report_buttons(hanvon,rbuttons,data[4]); report_buttons(hanvon,rbuttons,data[4]);
break; break;
case 0x02: /* position change */ case 0x02: /* position change */
if((data[1] & 0xf0) != 0) { if((data[1] & 0xf0) != 0) {
input_report_abs(dev, ABS_X, get_unaligned_be16(&data[2])); input_report_abs(dev, ABS_X, be16_to_cpup((__be16 *)&data[2]));
input_report_abs(dev, ABS_Y, get_unaligned_be16(&data[4])); input_report_abs(dev, ABS_Y, be16_to_cpup((__be16 *)&data[4]));
input_report_abs(dev, ABS_TILT_X, data[7] & 0x3f); input_report_abs(dev, ABS_TILT_X, data[7] & 0x3f);
input_report_abs(dev, ABS_TILT_Y, data[8]); input_report_abs(dev, ABS_TILT_Y, data[8]);
input_report_abs(dev, ABS_PRESSURE, get_unaligned_be16(&data[6])>>6); input_report_abs(dev, ABS_PRESSURE, be16_to_cpup((__be16 *)&data[6])>>6);
} }
input_report_key(dev, BTN_LEFT, data[1] & 0x1); input_report_key(dev, BTN_LEFT, data[1] & 0x1);
@ -127,21 +126,25 @@ MODULE_DEVICE_TABLE(usb, hanvon_ids);
static int hanvon_open(struct input_dev *dev) static int hanvon_open(struct input_dev *dev)
{ {
int ret=0;
struct hanvon *hanvon = input_get_drvdata(dev); struct hanvon *hanvon = input_get_drvdata(dev);
hanvon->old_wheel_pos = -AM_WHEEL_THRESHOLD-1; hanvon->old_wheel_pos = -AM_WHEEL_THRESHOLD-1;
hanvon->irq->dev = hanvon->usbdev; hanvon->irq->dev = hanvon->usbdev;
if (usb_submit_urb(hanvon->irq, GFP_KERNEL)) mutex_lock(&hanvon->mutex);
return -EIO; if(usb_submit_urb(hanvon->irq, GFP_KERNEL))
ret = -EIO;
return 0; mutex_unlock(&hanvon->mutex);
return ret;
} }
static void hanvon_close(struct input_dev *dev) static void hanvon_close(struct input_dev *dev)
{ {
struct hanvon *hanvon = input_get_drvdata(dev); struct hanvon *hanvon = input_get_drvdata(dev);
mutex_lock(&hanvon->mutex);
usb_kill_urb(hanvon->irq); usb_kill_urb(hanvon->irq);
mutex_unlock(&hanvon->mutex);
} }
static int hanvon_probe(struct usb_interface *intf, const struct usb_device_id *id) static int hanvon_probe(struct usb_interface *intf, const struct usb_device_id *id)
@ -210,6 +213,7 @@ static int hanvon_probe(struct usb_interface *intf, const struct usb_device_id *
goto fail3; goto fail3;
usb_set_intfdata(intf, hanvon); usb_set_intfdata(intf, hanvon);
mutex_init(&hanvon->mutex);
return 0; return 0;
fail3: usb_free_urb(hanvon->irq); fail3: usb_free_urb(hanvon->irq);
@ -224,13 +228,12 @@ static void hanvon_disconnect(struct usb_interface *intf)
struct hanvon *hanvon = usb_get_intfdata(intf); struct hanvon *hanvon = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
if (hanvon) {
usb_kill_urb(hanvon->irq); usb_kill_urb(hanvon->irq);
input_unregister_device(hanvon->dev); input_unregister_device(hanvon->dev);
usb_free_urb(hanvon->irq); usb_free_urb(hanvon->irq);
usb_free_coherent(interface_to_usbdev(intf), USB_AM_PACKET_LEN, hanvon->data, hanvon->data_dma); usb_free_coherent(interface_to_usbdev(intf), USB_AM_PACKET_LEN, hanvon->data, hanvon->data_dma);
kfree(hanvon); kfree(hanvon);
}
} }
static struct usb_driver hanvon_driver = { static struct usb_driver hanvon_driver = {